/*
* Value, possibly symbolic.
* If type is NSC_NOTYPE, it's an error value.
- * If category is NSC_OFF, the value is at offset val_as.off in the
- * context object.
+ * If category is NSC_OFF, the value is in a context object at offset
+ * val_as.sym.off + val_as.sym.idx * S, where S is the size of the
+ * value.
* If category is NSC_VAL, the value is in val_as, and the type is a
* promoted type.
- * Some values can also be interpreted as an object type. The values
+ * Some values can also be interpreted as an object type. The value's
* consumer chooses how to interpret it, depending on context.
*/
struct valstr {
packed_nsc_cat val_cat; /* category of value */
signed char val_as_type; /* value interpreted as object type */
union {
- ptrdiff_t off; /* cat NSC_OFF */
- double dbl; /* cat NSC_VAL, types NSC_DOUBLE */
+ struct { /* cat NSC_OFF */
+ ptrdiff_t off;
+ 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 */
} val_as;
* Return a pointer to the first character after the value on success,
* NULL on error.
* TYPE is the context type, a file type.
+ * If STR names an array, VAL simply refers to the element with index
+ * zero.
*/
char *
nstr_comp_val(char *str, struct valstr*val, int type)
else {
val->val_type = cap[j].ca_type;
val->val_cat = NSC_OFF;
- val->val_as.off = cap[j].ca_off;
+ val->val_as.sym.off = cap[j].ca_off;
+ val->val_as.sym.idx = 0;
}
}
} else
* Use coordinate system of country CNUM.
* PTR points to a context object of the type that was used to compile
* the value.
- * If WANT is not zero, coerce the value to promoted value type WANT.
- * VAL must be coercible. That's the case if a previous
+ * 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.
*/
void
{
char *memb_ptr;
nsc_type valtype = NSC_LONG;
+ int idx;
switch (val->val_cat) {
default:
break;
case NSC_OFF:
memb_ptr = ptr;
- memb_ptr += val->val_as.off;
+ memb_ptr += val->val_as.sym.off;
+ idx = val->val_as.sym.idx;
switch (val->val_type) {
case NSC_CHAR:
- val->val_as.lng = *(signed char *)memb_ptr;
+ val->val_as.lng = ((signed char *)memb_ptr)[idx];
break;
case NSC_UCHAR:
- val->val_as.lng = *(unsigned char *)memb_ptr;
+ val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
break;
case NSC_SHORT:
- val->val_as.lng = *(short *)memb_ptr;
+ val->val_as.lng = ((short *)memb_ptr)[idx];
break;
case NSC_USHORT:
- val->val_as.lng = *(unsigned short *)memb_ptr;
+ val->val_as.lng = ((unsigned short *)memb_ptr)[idx];
break;
case NSC_INT:
- val->val_as.lng = *(int *)memb_ptr;
+ val->val_as.lng = ((int *)memb_ptr)[idx];
break;
case NSC_LONG:
- val->val_as.lng = *(long *)memb_ptr;
+ val->val_as.lng = ((long *)memb_ptr)[idx];
break;
case NSC_XCOORD:
- val->val_as.lng = xrel(getnatp(cnum), *(short *)memb_ptr);
+ val->val_as.lng = xrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
break;
case NSC_YCOORD:
- val->val_as.lng = yrel(getnatp(cnum), *(short *)memb_ptr);
+ val->val_as.lng = yrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
break;
case NSC_FLOAT:
- val->val_as.dbl = *(float *)memb_ptr;
+ val->val_as.dbl = ((float *)memb_ptr)[idx];
valtype = NSC_DOUBLE;
break;
case NSC_DOUBLE:
- val->val_as.dbl = *(double *)memb_ptr;
+ val->val_as.dbl = ((double *)memb_ptr)[idx];
valtype = NSC_DOUBLE;
break;
case NSC_STRING:
valtype = NSC_STRING;
break;
case NSC_TIME:
- val->val_as.lng = *(time_t *)memb_ptr;
+ val->val_as.lng = ((time_t *)memb_ptr)[idx];
break;
case NSC_TYPEID:
- val->val_as.lng = *(signed char *)memb_ptr;
+ val->val_as.lng = ((signed char *)memb_ptr)[idx];
valtype = NSC_TYPEID;
break;
default:
}
}
- if (want) {
- if (valtype == want)
- ;
- else if (want == NSC_DOUBLE) {
- if (valtype == NSC_LONG) {
- valtype = want;
- val->val_as.dbl = val->val_as.lng;
- }
- } else if (want == NSC_STRING)
- CANT_HAPPEN("unimplemented WANT"); /* FIXME */
- if (CANT_HAPPEN(valtype != want)) {
+ if (valtype == want)
+ ;
+ else if (want == NSC_DOUBLE) {
+ if (valtype == NSC_LONG) {
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;
- default:
- CANT_HAPPEN("bad WANT argument");
- }
+ val->val_as.dbl = val->val_as.lng;
+ }
+ } 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;
+ default:
+ CANT_HAPPEN("bad WANT argument");
}
}