From 143a4e4e6fa2fe641aebe679e77a650782d0b0fc Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 2 Feb 2014 09:39:35 +0100 Subject: [PATCH] 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 --- include/nsc.h | 4 ++-- src/lib/commands/surv.c | 5 ++++- src/lib/common/ef_verify.c | 2 +- src/lib/common/nstreval.c | 25 ++++++++++++++----------- src/lib/common/xdump.c | 2 +- src/lib/subs/nstr.c | 11 +++++++---- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/include/nsc.h b/include/nsc.h index 3b7fc35f..e2b4b33c 100644 --- a/include/nsc.h +++ b/include/nsc.h @@ -286,8 +286,8 @@ extern struct symbol sector_navigation[]; /* src/lib/common/nstreval.c */ extern struct valstr *nstr_mksymval(struct valstr *, struct castr *, int); -extern struct valstr *nstr_exec_val(struct valstr *, natid, void *, - enum nsc_type); +extern struct valstr *nstr_eval(struct valstr *, natid, void *, + enum nsc_type); extern int nstr_promote(int); extern char *symbol_by_value(int, struct symbol *); /* src/lib/global/nsc.c */ diff --git a/src/lib/commands/surv.c b/src/lib/commands/surv.c index c5a5987a..1be364c3 100644 --- a/src/lib/commands/surv.c +++ b/src/lib/commands/surv.c @@ -28,6 +28,7 @@ * * Known contributors to this file: * Dave Pare, 1986 + * Markus Armbruster, 2004-2014 */ #include @@ -135,7 +136,9 @@ code_char(struct valstr val, struct sctstr *sp) int n; 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; if (amt <= 0) return ' '; diff --git a/src/lib/common/ef_verify.c b/src/lib/common/ef_verify.c index bc675f4e..17057c59 100644 --- a/src/lib/common/ef_verify.c +++ b/src/lib/common/ef_verify.c @@ -169,7 +169,7 @@ verify_row(int type, int row) if (ca[i].ca_table == EF_BAD) continue; 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)) { ret_val = -1; continue; diff --git a/src/lib/common/nstreval.c b/src/lib/common/nstreval.c index 074dfd1f..1d7f2b38 100644 --- a/src/lib/common/nstreval.c +++ b/src/lib/common/nstreval.c @@ -29,7 +29,7 @@ * Known contributors to this file: * Dave Pare, 1989 * Steve McClure, 1997 - * Markus Armbruster, 2004-2008 + * Markus Armbruster, 2004-2014 */ #include @@ -59,16 +59,19 @@ nstr_mksymval(struct valstr *val, struct castr *ca, int idx) /* * Evaluate VAL. - * If VAL is symbolic, evaluate it into a promoted value type. - * Translate it for country CNUM (coordinate system and contact - * status), except when CNUM is NATID_BAD. + * If VAL has category NSC_OFF, read the value from the context object + * PTR, and translate it for country CNUM (coordinate system and + * contact status). No translation when CNUM is NATID_BAD. * PTR points to a context object of the type that was used to compile * the value. * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type * 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 * -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; 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) { case NSC_VAL: valtype = val->val_type; + if (CANT_HAPPEN(!NSC_IS_PROMOTED(valtype))) + valtype = nstr_promote(valtype); break; case NSC_OFF: 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: val->val_as.str.base = ((char **)memb_ptr)[idx]; val->val_as.str.maxsz = INT_MAX; + /* really SIZE_MAX, but that's C99 */ valtype = NSC_STRING; break; case NSC_TIME: @@ -175,7 +181,7 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want) break; default: CANT_REACH(); - val->val_as.lng = 0; + valtype = NSC_NOTYPE; } val->val_cat = NSC_VAL; 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)) { - /* make up an error value */ - valtype = want; - memset(&val->val_as, 0, sizeof(val->val_as)); - } + if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) + valtype = NSC_NOTYPE; val->val_type = valtype; return val; diff --git a/src/lib/common/xdump.c b/src/lib/common/xdump.c index 0809d084..ff1ee6de 100644 --- a/src/lib/common/xdump.c +++ b/src/lib/common/xdump.c @@ -112,7 +112,7 @@ xdeval(struct valstr *val, struct xdstr *xd, struct castr *ca, void *ptr, int 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); } /* diff --git a/src/lib/subs/nstr.c b/src/lib/subs/nstr.c index eca8f7c4..f9987e78 100644 --- a/src/lib/subs/nstr.c +++ b/src/lib/subs/nstr.c @@ -29,7 +29,7 @@ * Known contributors to this file: * Dave Pare, 1989 * Steve McClure, 1997 - * Markus Armbruster, 2004-2013 + * Markus Armbruster, 2004-2014 */ #include @@ -231,7 +231,8 @@ strnncmp(char *s1, size_t sz1, char *s2, size_t sz2) int 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; 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) return 0; lft = np[i].lft; - nstr_exec_val(&lft, player->cnum, ptr, optype); + nstr_eval(&lft, player->cnum, ptr, optype); 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) { case NSC_LONG: if (!EVAL(op, lft.val_as.lng, rgt.val_as.lng))