/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
- * Ken Stevens, Steve McClure
+ * Copyright (C) 1986-2018, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Ken Stevens, Steve McClure, Markus Armbruster
*
- * This program is free software; you can redistribute it and/or modify
+ * Empire is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ---
*
* ---
*
* nstreval.c: evaluate compiled values
- *
+ *
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 1997
- * Markus Armbruster, 2004-2008
+ * Markus Armbruster, 2004-2016
*/
#include <config.h>
#include <limits.h>
+#include <stdio.h>
#include <string.h>
-#include "file.h"
#include "nat.h"
#include "nsc.h"
#include "optlist.h"
/*
- * Initialize VAL to symbolic value for selector CA with index IDX.
- * Return VAL.
+ * Initialize @val to symbolic value for selector @ca with index @idx.
+ * Return @val.
*/
struct valstr *
nstr_mksymval(struct valstr *val, struct castr *ca, int idx)
val->val_as.sym.len = ca->ca_len;
val->val_as.sym.idx = idx;
val->val_as.sym.get = ca->ca_get;
+ val->val_as.sym.hidden = ca->ca_flags & NSC_HIDDEN;
return val;
}
/*
- * 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.
- * PTR points to a context object of the type that was used to compile
+ * Evaluate @val.
+ * 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. That's the case if a previous
- * nstr_coerce_val(VAL, WANT, STR) succeeded.
+ * 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;
- int idx;
+ int idx, hidden;
coord c;
struct natstr *natp;
+ struct relatstr *relp;
if (CANT_HAPPEN(want != NSC_NOTYPE && !NSC_IS_PROMOTED(want)))
want = nstr_promote(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) {
+ natp = getnatp(cnum);
do {
- ptr = val->val_as.sym.get(val, cnum, ptr);
+ ptr = val->val_as.sym.get(val, natp, ptr);
} while (ptr && val->val_as.sym.get);
if (!ptr) {
valtype = val->val_type;
memb_ptr = ptr;
memb_ptr += val->val_as.sym.off;
idx = val->val_as.sym.idx;
+ hidden = val->val_as.sym.hidden;
+ val->val_cat = NSC_VAL;
switch (val->val_type) {
case NSC_CHAR:
val->val_as.lng = ((signed char *)memb_ptr)[idx];
c = yrel(getnatp(cnum), c);
val->val_as.lng = c;
break;
- case NSC_HIDDEN:
- val->val_as.lng = -1;
- if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION))
- break;
- if (!opt_HIDDEN && cnum != NATID_BAD) {
- natp = getnatp(cnum);
- if (natp->nat_stat != STAT_GOD
- && !(getcontact(natp, idx) && getcontact(ptr, idx)))
- break;
- }
- val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
- break;
case NSC_FLOAT:
val->val_as.dbl = ((float *)memb_ptr)[idx];
valtype = NSC_DOUBLE;
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:
break;
default:
CANT_REACH();
- val->val_as.lng = 0;
+ valtype = NSC_NOTYPE;
+ }
+
+ if (hidden) {
+ if (CANT_HAPPEN(hidden && valtype != NSC_LONG))
+ break; /* not implemented */
+ relp = ptr;
+ if (CANT_HAPPEN(relp->ef_type != EF_RELAT))
+ break; /* only defined for nation selectors */
+ if (!opt_HIDDEN || cnum == NATID_BAD
+ || getnatp(cnum)->nat_stat == STAT_GOD)
+ break;
+ if (!in_contact(cnum, idx) || !in_contact(relp->rel_uid, idx))
+ val->val_as.lng = -1;
}
- val->val_cat = NSC_VAL;
break;
default:
CANT_REACH();
valtype = NSC_NOTYPE;
}
+ /* coerce */
if (valtype == want)
;
else if (want == NSC_DOUBLE) {
valtype = want;
val->val_as.dbl = val->val_as.lng;
}
- } else if (want == NSC_STRING)
- CANT_REACH(); /* FIXME implement */
-
- 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;
}
/*
- * Promote VALTYPE.
- * If VALTYPE is an integer type, return NSC_LONG.
- * If VALTYPE is a floating-point type, return NSC_DOUBLE.
- * If VALTYPE is a string type, return NSC_STRING.
+ * Promote @valtype.
+ * If @valtype is an integer type, return NSC_LONG.
+ * If @valtype is a floating-point type, return NSC_DOUBLE.
+ * If @valtype is a string type, return NSC_STRING.
*/
int
nstr_promote(int valtype)
case NSC_INT:
case NSC_XCOORD:
case NSC_YCOORD:
- case NSC_HIDDEN:
case NSC_TIME:
valtype = NSC_LONG;
break;
return NULL;
}
+
+int
+symbol_set_fmt(char *buf, size_t sz, int flags, struct symbol symtab[],
+ char *sep, int all)
+{
+ char *pfx = "";
+ int n, i;
+ char *p;
+
+ if (buf && sz)
+ buf[0] = 0;
+ n = 0;
+ for (i = 0; i < 32; i++) {
+ if (!(flags & bit(i)))
+ continue;
+ p = symbol_by_value(bit(i), symtab);
+ if (p)
+ n += snprintf(buf + n, sz - n, "%s%s", pfx, p);
+ else if (all)
+ n += snprintf(buf + n, sz - n, "%s#%d", pfx, i);
+ if ((size_t)n >= sz)
+ sz = n;
+ pfx = sep;
+ }
+
+ CANT_HAPPEN((size_t)n >= sz && buf);
+ return n;
+}