strings with length limit instead of zero termination.
(ship_ca, land_ca): New selectors rflags, rpath. The latter is such a
string.
union {
struct { /* cat NSC_OFF */
ptrdiff_t off;
+ int len;
int idx;
} sym;
double dbl; /* cat NSC_VAL, type NSC_DOUBLE */
- char *str; /* cat NSC_VAL, type NSC_STRING */
- long lng; /* cat NSC_VAL, type NSC_LONG */
+ struct { /* cat NSC_VAL, type NSC_STRING */
+ char *base;
+ size_t maxsz;
+ } str;
+ long lng; /* cat NSC_VAL, type NSC_LONG, NSC_TYPEID */
} val_as;
};
static char *
xdprval(struct valstr *val, char *sep)
{
- unsigned char *s, *e;
+ unsigned char *s, *e, *l;
switch (val->val_type) {
case NSC_TYPEID:
pr("%s%#g", sep, val->val_as.dbl);
break;
case NSC_STRING:
- s = (unsigned char *)val->val_as.str;
+ s = (unsigned char *)val->val_as.str.base;
if (s) {
pr("%s\"", sep);
- while (*s) {
- for (e = s; *e != '"' && *e != '\\' && isgraph(*e); ++e) ;
+ l = s + val->val_as.str.maxsz;
+ for (;;) {
+ for (e=s; e<l && *e != '"' && *e != '\\' && isgraph(*e); ++e) ;
pr("%.*s", (int)(e-s), s);
- if (*e)
+ if (e < l && *e)
pr("\\%03o", *e++);
+ else
+ break;
s = e;
}
prnf("\"");
val.val_as.sym.off = cm->ca[0].ca_off;
val.val_as.sym.idx = 0;
nstr_exec_val(&val, player->cnum, p, NSC_STRING);
- if (!val.val_as.str || !*val.val_as.str)
+ if (!val.val_as.str.base || !*val.val_as.str.base)
break;
++n;
xdflds(cm->ca, p);
{NSC_XCOORD, NSC_DEITY, 0, fldoff(shpstr, shp_orig_x), "xbuilt"},
{NSC_YCOORD, NSC_DEITY, 0, fldoff(shpstr, shp_orig_y), "ybuilt"},
{NSC_NATID, NSC_DEITY, 0, fldoff(shpstr, shp_orig_own), "builder"},
- /* FIXME retreat stuff missing */
+ {NSC_INT, 0, 0, fldoff(shpstr, shp_rflags), "rflags"},
+ {NSC_STRINGY, 0, RET_LEN, fldoff(shpstr, shp_rpath), "rpath"},
{NSC_NOTYPE, 0, 0, 0, NULL}
};
{NSC_SHORT, 0, 0, fldoff(lndstr, lnd_retreat), "retreat"},
{NSC_UCHAR, 0, 0, fldoff(lndstr, lnd_fuel), "fuel"},
{NSC_UCHAR, 0, 0, fldoff(lndstr, lnd_nxlight), "nxlight"},
- /* FIXME retreat stuff missing */
+ {NSC_INT, 0, 0, fldoff(lndstr, lnd_rflags), "rflags"},
+ {NSC_STRINGY, 0, RET_LEN, fldoff(lndstr, lnd_rpath), "rpath"},
{NSC_UCHAR, 0, 0, fldoff(lndstr, lnd_rad_max), "react"},
NSC_IVEC(fldoff(lndstr, lnd_item), ""),
{NSC_USHORT, NSC_DEITY, 0, fldoff(lndstr, lnd_pstage), "pstage"},
* Markus Armbruster, 2004
*/
+#include <limits.h>
#include "misc.h"
#include "file.h"
#include "match.h"
return i + 1;
}
+static int
+strnncmp(char *s1, size_t sz1, char *s2, size_t sz2)
+{
+ if (sz1 == sz2) return strncmp(s1, s2, sz2);
+ if (sz1 < sz2) return -strnncmp(s2, sz2, s1, sz1);
+ int res = strncmp(s1, s2, sz2);
+ return res ? res : s1[sz2];
+}
+
#define EVAL(op, lft, rgt) \
((op) == '<' ? (lft) < (rgt) \
: (op) == '=' ? (lft) == (rgt) \
return 0;
break;
case NSC_STRING:
- cmp = strcmp(lft.val_as.str, rgt.val_as.str);
+ cmp = strnncmp(lft.val_as.str.base, lft.val_as.str.maxsz,
+ rgt.val_as.str.base, rgt.val_as.str.maxsz);
if (!EVAL(op, cmp, 0))
return 0;
break;
val->val_type = cap[j].ca_type;
val->val_cat = NSC_OFF;
val->val_as.sym.off = cap[j].ca_off;
+ val->val_as.sym.len = cap[j].ca_len;
val->val_as.sym.idx = 0;
}
}
nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
{
char *memb_ptr;
- nsc_type valtype = NSC_LONG;
+ nsc_type valtype;
int idx;
switch (val->val_cat) {
valtype = val->val_type;
break;
case NSC_OFF:
+ valtype = NSC_LONG;
memb_ptr = ptr;
memb_ptr += val->val_as.sym.off;
idx = val->val_as.sym.idx;
break;
case NSC_STRINGY:
CANT_HAPPEN(idx);
- val->val_as.str = (char *)memb_ptr;
+ val->val_as.str.maxsz = val->val_as.sym.len;
+ val->val_as.str.base = (char *)memb_ptr;
valtype = NSC_STRING;
break;
case NSC_STRING:
- val->val_as.str = ((char **)memb_ptr)[idx];
+ val->val_as.str.base = ((char **)memb_ptr)[idx];
+ val->val_as.str.maxsz = INT_MAX;
valtype = NSC_STRING;
break;
case NSC_TIME:
}
} else if (want == NSC_STRING)
CANT_HAPPEN("unimplemented WANT"); /* FIXME */
+
if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
valtype = want;
switch (want) {
case NSC_TYPEID:
case NSC_LONG: val->val_as.lng = 0; break;
case NSC_DOUBLE: val->val_as.dbl = 0.0; break;
- case NSC_STRING: val->val_as.str = ""; break;
+ case NSC_STRING: val->val_as.str.base = NULL; break;
default:
CANT_HAPPEN("bad WANT argument");
}