nsc: Rename nstr_exec_val() to nstr_eval() and tighten contract

nstr_exec_val() can produce three different error values: NSC_NOTYPE
on invalid category, invalid type with zero val_as.lng on invalid type
(this is a bug), and the wanted type with zero val_s when it can't
coerce.  None of these should ever happen.

Fix it to always produce an NSC_NOTYPE error value.  Fix up callers to
check for it.

Specify the result's type is promoted on success.  Ensure it is even
when the argument is NSC_VAL with an unpromoted type, which is
invalid.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
This commit is contained in:
Markus Armbruster 2014-02-02 09:39:35 +01:00
parent 5a1544f925
commit 143a4e4e6f
6 changed files with 29 additions and 20 deletions

View file

@ -286,8 +286,8 @@ extern struct symbol sector_navigation[];
/* src/lib/common/nstreval.c */ /* src/lib/common/nstreval.c */
extern struct valstr *nstr_mksymval(struct valstr *, struct castr *, int); extern struct valstr *nstr_mksymval(struct valstr *, struct castr *, int);
extern struct valstr *nstr_exec_val(struct valstr *, natid, void *, extern struct valstr *nstr_eval(struct valstr *, natid, void *,
enum nsc_type); enum nsc_type);
extern int nstr_promote(int); extern int nstr_promote(int);
extern char *symbol_by_value(int, struct symbol *); extern char *symbol_by_value(int, struct symbol *);
/* src/lib/global/nsc.c */ /* src/lib/global/nsc.c */

View file

@ -28,6 +28,7 @@
* *
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1986 * Dave Pare, 1986
* Markus Armbruster, 2004-2014
*/ */
#include <config.h> #include <config.h>
@ -135,7 +136,9 @@ code_char(struct valstr val, struct sctstr *sp)
int n; int n;
int large = val.val_type != NSC_CHAR && val.val_type != NSC_UCHAR; int large = val.val_type != NSC_CHAR && val.val_type != NSC_UCHAR;
nstr_exec_val(&val, player->cnum, sp, NSC_LONG); nstr_eval(&val, player->cnum, sp, NSC_LONG);
if (CANT_HAPPEN(val.val_type != NSC_LONG))
return ' ';
amt = val.val_as.lng; amt = val.val_as.lng;
if (amt <= 0) if (amt <= 0)
return ' '; return ' ';

View file

@ -169,7 +169,7 @@ verify_row(int type, int row)
if (ca[i].ca_table == EF_BAD) if (ca[i].ca_table == EF_BAD)
continue; continue;
nstr_mksymval(&val, &ca[i], j); nstr_mksymval(&val, &ca[i], j);
nstr_exec_val(&val, 0, row_ref, NSC_NOTYPE); nstr_eval(&val, 0, row_ref, NSC_NOTYPE);
if (CANT_HAPPEN(val.val_type != NSC_LONG)) { if (CANT_HAPPEN(val.val_type != NSC_LONG)) {
ret_val = -1; ret_val = -1;
continue; continue;

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1989 * Dave Pare, 1989
* Steve McClure, 1997 * Steve McClure, 1997
* Markus Armbruster, 2004-2008 * Markus Armbruster, 2004-2014
*/ */
#include <config.h> #include <config.h>
@ -59,16 +59,19 @@ nstr_mksymval(struct valstr *val, struct castr *ca, int idx)
/* /*
* Evaluate VAL. * Evaluate VAL.
* If VAL is symbolic, evaluate it into a promoted value type. * If VAL has category NSC_OFF, read the value from the context object
* Translate it for country CNUM (coordinate system and contact * PTR, and translate it for country CNUM (coordinate system and
* status), except when CNUM is NATID_BAD. * contact status). No translation when CNUM is NATID_BAD.
* PTR points to a context object of the type that was used to compile * PTR points to a context object of the type that was used to compile
* the value. * the value.
* Unless WANT is NSC_NOTYPE, coerce the value to promoted value type * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
* WANT. VAL must be coercible. * WANT. VAL must be coercible.
* The result's type is promoted on success, NSC_NOTYPE on error.
* In either case, the category is NSC_VAL.
* Return VAL.
*/ */
struct valstr * struct valstr *
nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want) nstr_eval(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
{ {
char *memb_ptr; char *memb_ptr;
enum nsc_type valtype; enum nsc_type valtype;
@ -82,6 +85,8 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
switch (val->val_cat) { switch (val->val_cat) {
case NSC_VAL: case NSC_VAL:
valtype = val->val_type; valtype = val->val_type;
if (CANT_HAPPEN(!NSC_IS_PROMOTED(valtype)))
valtype = nstr_promote(valtype);
break; break;
case NSC_OFF: case NSC_OFF:
if (val->val_as.sym.get) { if (val->val_as.sym.get) {
@ -168,6 +173,7 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
case NSC_STRING: case NSC_STRING:
val->val_as.str.base = ((char **)memb_ptr)[idx]; val->val_as.str.base = ((char **)memb_ptr)[idx];
val->val_as.str.maxsz = INT_MAX; val->val_as.str.maxsz = INT_MAX;
/* really SIZE_MAX, but that's C99 */
valtype = NSC_STRING; valtype = NSC_STRING;
break; break;
case NSC_TIME: case NSC_TIME:
@ -175,7 +181,7 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
break; break;
default: default:
CANT_REACH(); CANT_REACH();
val->val_as.lng = 0; valtype = NSC_NOTYPE;
} }
val->val_cat = NSC_VAL; val->val_cat = NSC_VAL;
break; break;
@ -194,11 +200,8 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
} }
} }
if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) { if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE))
/* make up an error value */ valtype = NSC_NOTYPE;
valtype = want;
memset(&val->val_as, 0, sizeof(val->val_as));
}
val->val_type = valtype; val->val_type = valtype;
return val; return val;

View file

@ -112,7 +112,7 @@ xdeval(struct valstr *val, struct xdstr *xd,
struct castr *ca, void *ptr, int idx) struct castr *ca, void *ptr, int idx)
{ {
nstr_mksymval(val, ca, idx); nstr_mksymval(val, ca, idx);
return nstr_exec_val(val, xd->cnum, ptr, NSC_NOTYPE); return nstr_eval(val, xd->cnum, ptr, NSC_NOTYPE);
} }
/* /*

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1989 * Dave Pare, 1989
* Steve McClure, 1997 * Steve McClure, 1997
* Markus Armbruster, 2004-2013 * Markus Armbruster, 2004-2014
*/ */
#include <config.h> #include <config.h>
@ -231,7 +231,8 @@ strnncmp(char *s1, size_t sz1, char *s2, size_t sz2)
int int
nstr_exec(struct nscstr *np, int ncond, void *ptr) nstr_exec(struct nscstr *np, int ncond, void *ptr)
{ {
int i, op, optype, cmp; int i, op, cmp;
enum nsc_type optype;
struct valstr lft, rgt; struct valstr lft, rgt;
for (i = 0; i < ncond; ++i) { for (i = 0; i < ncond; ++i) {
@ -240,9 +241,11 @@ nstr_exec(struct nscstr *np, int ncond, void *ptr)
if (np[i].lft.val_cat == NSC_NOCAT || np[i].rgt.val_cat == NSC_NOCAT) if (np[i].lft.val_cat == NSC_NOCAT || np[i].rgt.val_cat == NSC_NOCAT)
return 0; return 0;
lft = np[i].lft; lft = np[i].lft;
nstr_exec_val(&lft, player->cnum, ptr, optype); nstr_eval(&lft, player->cnum, ptr, optype);
rgt = np[i].rgt; rgt = np[i].rgt;
nstr_exec_val(&rgt, player->cnum, ptr, optype); nstr_eval(&rgt, player->cnum, ptr, optype);
if (CANT_HAPPEN(lft.val_type != optype || rgt.val_type != optype))
return 0;
switch (optype) { switch (optype) {
case NSC_LONG: case NSC_LONG:
if (!EVAL(op, lft.val_as.lng, rgt.val_as.lng)) if (!EVAL(op, lft.val_as.lng, rgt.val_as.lng))