Selector rewrite: values other than long, interpret identifiers
according to context, to make `lstat * ?type#spy&spy>1' work. Closes bug#825363, #905809, #905814 and #922968. (nsc_type, packed_nsc_type, nsc_cat, packed_nsc_cat, nsc_flags): New. (valstr): New. Old code encoded values in type long, which was somewhat hard to read and could only support signed integer values. (nscstr): Redesign. Use valstr. Typed operator. (castr): Split ca_code into ca_type, ca_flags, ca_off. Tables changed. (nstr_comp, nstr_exec): Redesign and rewrite. Callers changed. They used the old design incorrectly, which let players smash the stack by supplying more than NCOND conditions. (encode, nstr_comp_val, decode, nstr_exec_val): Rename, redesign, and rewrite. Callers changed. (nstr_coerce_val): New. (var_ca, sect_ca, ship_ca, land_ca): Checking both var_ca[] and the object's ca complicates proper recognition of unique abbreviations. Copy contents of var_ca[] into the ca of objects, remove var_ca[]. (surv): Reject values with category other than NSC_OFF and types that can't be coerced to NSC_LONG. Old code happily passed values with category NSC_VAL to code_char(). The previous version interpreted them correctly, but earlier versions interpreted them as NSC_OFF, then logged `bad type in decode: 0' and evaluated them into zero. (code_char): Used to test category NSC_VAR to decide whether to display tens or hundreds. NSC_VAR no longer exists. Test type instead. Makes more sense anyway.
This commit is contained in:
parent
47c8a32ae3
commit
4366c5ac6e
13 changed files with 726 additions and 544 deletions
|
@ -123,7 +123,7 @@ rout(void)
|
|||
continue;
|
||||
p = &map[ns.dy][ns.dx * 2];
|
||||
if ((dir = sect.sct_del[i_del] & 0x7) &&
|
||||
nstr_exec(cond, ncond, (s_char *)§, EF_SECTOR))
|
||||
nstr_exec(cond, ncond, §))
|
||||
memcpy(p, routech[dir][0], 3);
|
||||
p[1] = dchr[sect.sct_type].d_mnem;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ sct(void)
|
|||
continue;
|
||||
ptr = &map[ns.dy][ns.dx];
|
||||
*ptr = dchr[sect.sct_type].d_mnem;
|
||||
if (nstr_exec(cond, ncond, (s_char *)§, EF_SECTOR)) {
|
||||
if (nstr_exec(cond, ncond, §)) {
|
||||
++nsect;
|
||||
*ptr |= 0x80;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
* Dave Pare, 1986
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "misc.h"
|
||||
#include "player.h"
|
||||
#include "var.h"
|
||||
|
@ -43,7 +44,7 @@
|
|||
#include "commands.h"
|
||||
#include "optlist.h"
|
||||
|
||||
static s_char code_char(long int coding, struct sctstr *sp);
|
||||
static char code_char(struct valstr, struct sctstr *sp);
|
||||
|
||||
/*
|
||||
* survey type <sarg> ?cond
|
||||
|
@ -55,7 +56,7 @@ surv(void)
|
|||
int nsect;
|
||||
struct nstr_sect nstr;
|
||||
int y;
|
||||
long coding;
|
||||
struct valstr val;
|
||||
struct natstr *np;
|
||||
struct sctstr sect;
|
||||
struct range range;
|
||||
|
@ -72,10 +73,17 @@ surv(void)
|
|||
static s_char **map = (s_char **)0;
|
||||
|
||||
nsect = 0;
|
||||
if ((ptr =
|
||||
getstarg(player->argp[1], "commodity or variable? ", buf)) == 0)
|
||||
if ((ptr = getstarg(player->argp[1], "commodity or variable? ", buf)) == 0)
|
||||
return RET_SYN;
|
||||
if (encode(ptr, &coding, EF_SECTOR) < 0)
|
||||
ptr = nstr_comp_val(ptr, &val, EF_SECTOR);
|
||||
if (!ptr)
|
||||
return RET_SYN;
|
||||
if (val.val_cat != NSC_OFF || nstr_coerce_val(&val, NSC_LONG, NULL) < 0) {
|
||||
pr("Can't survey this\n");
|
||||
return RET_SYN;
|
||||
}
|
||||
for (; isspace(*ptr); ++ptr) ;
|
||||
if (*ptr)
|
||||
return RET_SYN;
|
||||
if (player->argp[2] == (s_char *)0) {
|
||||
if ((str = getstring("(sects)? ", buf)) == 0)
|
||||
|
@ -92,10 +100,9 @@ surv(void)
|
|||
} else if (!snxtsct(&nstr, str))
|
||||
return RET_SYN;
|
||||
if (!mapbuf)
|
||||
mapbuf =
|
||||
(s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char));
|
||||
mapbuf = malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char));
|
||||
if (!map) {
|
||||
map = (s_char **)malloc(WORLD_Y * sizeof(s_char *));
|
||||
map = malloc(WORLD_Y * sizeof(s_char *));
|
||||
if (map && mapbuf) {
|
||||
for (i = 0; i < WORLD_Y; i++)
|
||||
map[i] = &mapbuf[MAPWIDTH(1) * i];
|
||||
|
@ -120,9 +127,9 @@ surv(void)
|
|||
if (!player->owner)
|
||||
continue;
|
||||
ptr = &map[nstr.dy][nstr.dx];
|
||||
if (nstr_exec(cond, ncond, (s_char *)§, EF_SECTOR)) {
|
||||
if (nstr_exec(cond, ncond, §)) {
|
||||
++nsect;
|
||||
*ptr = 0x80 | code_char(coding, §);
|
||||
*ptr = 0x80 | code_char(val, §);
|
||||
} else {
|
||||
*ptr = dchr[sect.sct_type].d_mnem;
|
||||
}
|
||||
|
@ -141,22 +148,19 @@ surv(void)
|
|||
return RET_OK;
|
||||
}
|
||||
|
||||
static s_char
|
||||
code_char(long int coding, struct sctstr *sp)
|
||||
static char
|
||||
code_char(struct valstr val, struct sctstr *sp)
|
||||
{
|
||||
int amt;
|
||||
int n;
|
||||
int large = val.val_type != NSC_CHAR && val.val_type != NSC_UCHAR;
|
||||
|
||||
amt = decode(player->cnum, coding, (s_char *)sp, EF_SECTOR);
|
||||
n = 0;
|
||||
if ((coding & NSC_CMASK) == NSC_VAR) {
|
||||
if (amt != 0)
|
||||
n = (amt / 100) + 1;
|
||||
} else if (amt != 0)
|
||||
n = (amt / 10) + 1;
|
||||
if (n > 11)
|
||||
n = 11;
|
||||
if (n < 0)
|
||||
n = 0;
|
||||
return " 0123456789$"[n];
|
||||
nstr_exec_val(&val, player->cnum, sp, NSC_LONG);
|
||||
amt = val.val_as.lng;
|
||||
if (amt <= 0)
|
||||
return ' ';
|
||||
n = amt / (large ? 100 : 10);
|
||||
if (n >= 10)
|
||||
return '$';
|
||||
return "0123456789"[n];
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ tend_nxtitem(struct nstr_item *np, caddr_t ptr)
|
|||
}
|
||||
if (selected && np->ncond) {
|
||||
/* nstr_exec is expensive, so we do it last */
|
||||
if (!nstr_exec(np->cond, np->ncond, ptr, np->type))
|
||||
if (!nstr_exec(np->cond, np->ncond, ptr))
|
||||
selected = 0;
|
||||
}
|
||||
} while (!selected);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue