diff --git a/src/lib/common/xundump.c b/src/lib/common/xundump.c index b9fccfdd..65adc9d8 100644 --- a/src/lib/common/xundump.c +++ b/src/lib/common/xundump.c @@ -44,42 +44,29 @@ #include #include -#include "prototypes.h" #include "file.h" -#include "nsc.h" #include "match.h" +#include "nsc.h" +#include "optlist.h" +#include "prototypes.h" -#define MAX_NUM_COLUMNS 256 - -static char *fname = ""; -static int lineno = 0; +static char *fname; +static int lineno; static int human; +static int cur_type; +static void *cur_obj; +static int nxt_sel, nxt_idx; -/* - * TODO - * This structure could be replaced with struct valstr. - */ -enum enum_value { - VAL_NOTUSED, - VAL_STRING, /* uses v_string */ - VAL_SYMBOL, /* uses v_string */ - VAL_SYMBOL_SET, /* uses v_string */ - VAL_INDEX_ID, /* uses v_index_name and v_int */ - VAL_INDEX_SYMBOL, /* uses v_index_name and v_string */ - VAL_DOUBLE /* uses v_double */ -}; - -struct value { - enum enum_value v_type; - union { - char *v_string; - double v_double; - int v_int; - } v_field; - char *v_index_name; -}; - -static int gripe(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2))); +static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2))); +static int deffld(int, char *, int); +static void nxtfld(void); +static int setnum(int, double); +static int setstr(int, char *); +static int xunsymbol1(char *, struct symbol *, struct castr *, int); +static int setsym(int, char *); +static int mtsymset(int, long *); +static int add2symset(int, long *, char *); +static struct symbol *get_symtab(struct castr *); static int gripe(char *fmt, ...) @@ -144,18 +131,19 @@ xuesc(char *buf) } static int -xufldname(FILE *fp, struct value values[], int i) +xufldname(FILE *fp, int i) { - int ch; + int ch, idx; char buf[1024]; - values[i].v_type = VAL_NOTUSED; - ch = skipfs(fp); switch (ch) { case EOF: return gripe("Unexpected EOF"); case '\n': + if (nxt_sel >= 0) + return gripe("Fields missing"); + lineno++; return 0; default: ungetc(ch, fp); @@ -164,14 +152,12 @@ xufldname(FILE *fp, struct value values[], int i) ch = getc(fp); if (ch != '(') { ungetc(ch, fp); - values[i].v_type = VAL_SYMBOL; - values[i].v_field.v_string = strdup(buf); - return 1; + return deffld(i, buf, -1); } ch = getc(fp); ungetc(ch, fp); if (isdigit(ch) || ch == '-' || ch == '+') { - if (fscanf(fp, "%d", &values[i].v_field.v_int) != 1) { + if (fscanf(fp, "%d", &idx) != 1) { return gripe("Malformed number in index field %d", i + 1); } } else { @@ -183,36 +169,34 @@ xufldname(FILE *fp, struct value values[], int i) ch = getc(fp); if (ch != ')') return gripe("Malformed index field %d", i + 1); - values[i].v_index_name = strdup(buf); - values[i].v_type = VAL_INDEX_ID; - return 1; + return deffld(i, buf, idx); } } static int -xufld(FILE *fp, struct value values[], int i) +xufld(FILE *fp, int i) { int ch; char buf[1024]; - char *p; - int len, l1; - - values[i].v_type = VAL_NOTUSED; + double dbl; + long set; ch = skipfs(fp); switch (ch) { case EOF: return gripe("Unexpected EOF"); case '\n': + if (nxt_sel >= 0) + return gripe("Fields missing"); + lineno++; return 0; case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ungetc(ch, fp); - if (fscanf(fp, "%lg", &values[i].v_field.v_double) != 1) + if (fscanf(fp, "%lg", &dbl) != 1) return gripe("Malformed number in field %d", i + 1); - values[i].v_type = VAL_DOUBLE; - return 1; + return setnum(i, dbl); case '"': ch = getc(fp); if (ch == '"') @@ -225,12 +209,10 @@ xufld(FILE *fp, struct value values[], int i) return gripe("Invalid escape sequence in field %d", i + 1); } - values[i].v_type = VAL_STRING; - values[i].v_field.v_string = strdup(buf); - return 1; + return setstr(i, buf); case '(': - p = strdup(""); - len = 0; + if (mtsymset(i, &set) < 0) + return -1; for (;;) { ch = skipfs(fp); if (ch == EOF || ch == '\n') @@ -238,44 +220,30 @@ xufld(FILE *fp, struct value values[], int i) if (ch == ')') break; ungetc(ch, fp); - l1 = getid(fp, buf); - if (l1 < 0) + if (getid(fp, buf) < 0) return gripe("Junk in field %d", i + 1); - p = realloc(p, len + l1 + 2); - strcpy(p + len, buf); - strcpy(p + len + l1, " "); - len += l1 + 1; + if (add2symset(i, &set, buf) < 0) + return -1; } - if (len) - p[len - 1] = 0; - values[i].v_type = VAL_SYMBOL_SET; - values[i].v_field.v_string = p; - return 1; + return setnum(i, set); default: ungetc(ch, fp); if (getid(fp, buf) < 0) return gripe("Junk in field %d", i + 1); - if (!strcmp(buf, "nil")) { - values[i].v_type = VAL_STRING; - values[i].v_field.v_string = NULL; - } else { - values[i].v_type = VAL_SYMBOL; - values[i].v_field.v_string = strdup(buf); - } - return 1; + if (!strcmp(buf, "nil")) + return setstr(i, NULL); + else + return setsym(i, buf); } } static int -xuflds(FILE *fp, struct value values[], - int (*parse)(FILE *, struct value values[], int)) +xuflds(FILE *fp, int (*parse)(FILE *, int)) { int i, ch, res; for (i = 0; ; i++) { - if (i >= MAX_NUM_COLUMNS) - return gripe("Too many columns"); - res = parse(fp, values, i); + res = parse(fp, i); if (res < 0) return -1; if (res == 0) @@ -288,17 +256,171 @@ xuflds(FILE *fp, struct value values[], } } -static void -freeflds(struct value values[]) +static int +deffld(int fldidx, char *name, int idx) { - struct value *vp; + struct castr *ca = ef_cadef(cur_type); + int res; - for (vp = values; vp->v_type != VAL_NOTUSED; vp++) { - if (vp->v_type != VAL_DOUBLE && vp->v_type != VAL_INDEX_ID) - free(vp->v_field.v_string); + if (nxt_sel < 0) + return gripe("Too many fields, expected only %d", fldidx); + + res = stmtch(name, ca, offsetof(struct castr, ca_name), + sizeof(struct castr)); + if (ca[nxt_sel].ca_type != NSC_STRINGY && ca[nxt_sel].ca_len != 0) { + if (res != nxt_sel || idx != nxt_idx) + return gripe("Expected %s(%d) in field %d", + ca[nxt_sel].ca_name, nxt_idx, fldidx + 1); + } else { + if (res != nxt_sel || idx >= 0) + return gripe("Expected %s in field %d", + ca[nxt_sel].ca_name, fldidx + 1); } - free(vp->v_index_name); - vp->v_index_name = NULL; + + nxtfld(); + return 1; +} + +static void +nxtfld(void) +{ + struct castr *ca = ef_cadef(cur_type); + unsigned len = ca[nxt_sel].ca_type == NSC_STRINGY ? 0 : ca[nxt_sel].ca_len; /* FIXME ugly */ + + nxt_idx++; + if ((unsigned)nxt_idx >= len) { + nxt_idx = 0; + for (;;) { + nxt_sel++; + if (!ca[nxt_sel].ca_name) { + nxt_sel = -1; + break; + } + if (!(ca[nxt_sel].ca_flags & NSC_EXTRA)) + break; + } + } +} + +static struct castr * +ca4fld(int fldidx) +{ + struct castr *ca = ef_cadef(cur_type); + unsigned len = ca[nxt_sel].ca_type == NSC_STRINGY ? 0 : ca[nxt_sel].ca_len; /* FIXME ugly */ + + if (nxt_sel < 0 || CANT_HAPPEN(nxt_idx && (unsigned)nxt_idx >= len)) { + gripe("Too many fields, expected only %d", fldidx); + return NULL; + } + return &ca[nxt_sel]; +} + +static int +setnum(int fldidx, double dbl) +{ + struct castr *ca = ca4fld(fldidx); + char *memb_ptr; + double old; + + if (!ca) + return -1; + + memb_ptr = cur_obj; + memb_ptr += ca->ca_off; + switch (ca->ca_type) { + case NSC_CHAR: + case NSC_TYPEID: + old = ((signed char *)memb_ptr)[nxt_idx]; + ((signed char *)memb_ptr)[nxt_idx] = (signed char)dbl; + break; + case NSC_UCHAR: + old = ((unsigned char *)memb_ptr)[nxt_idx]; + ((unsigned char *)memb_ptr)[nxt_idx] = (unsigned char)dbl; + break; + case NSC_SHORT: + old = ((short *)memb_ptr)[nxt_idx]; + ((short *)memb_ptr)[nxt_idx] = (short)dbl; + break; + case NSC_USHORT: + old = ((unsigned short *)memb_ptr)[nxt_idx]; + ((unsigned short *)memb_ptr)[nxt_idx] = (unsigned short)dbl; + break; + case NSC_INT: + old = ((int *)memb_ptr)[nxt_idx]; + ((int *)memb_ptr)[nxt_idx] = (int)dbl; + break; + case NSC_LONG: + old = ((long *)memb_ptr)[nxt_idx]; + ((long *)memb_ptr)[nxt_idx] = (long)dbl; + break; + case NSC_XCOORD: + old = ((coord *)memb_ptr)[nxt_idx]; + ((coord *)memb_ptr)[nxt_idx] = XNORM((coord)dbl); + break; + case NSC_YCOORD: + old = ((coord *)memb_ptr)[nxt_idx]; + ((coord *)memb_ptr)[nxt_idx] = YNORM((coord)dbl); + break; + case NSC_FLOAT: + old = ((float *)memb_ptr)[nxt_idx]; + ((float *)memb_ptr)[nxt_idx] = (float)dbl; + break; + case NSC_DOUBLE: + old = ((double *)memb_ptr)[nxt_idx]; + ((double *)memb_ptr)[nxt_idx] = dbl; + break; + case NSC_TIME: + old = ((time_t *)memb_ptr)[nxt_idx]; + ((time_t *)memb_ptr)[nxt_idx] = (time_t)dbl; + break; + default: + return gripe("Field %d doesn't take numbers", fldidx + 1); + } + + if ((ca->ca_flags & NSC_CONST) && old != dbl) + return gripe("Value for field %d must be %g", fldidx + 1, old); + + nxtfld(); + return 1; +} + +static int +setstr(int fldidx, char *str) +{ + struct castr *ca = ca4fld(fldidx); + char *memb_ptr, *old; + + if (!ca) + return -1; + + memb_ptr = cur_obj; + memb_ptr += ca->ca_off; + switch (ca->ca_type) { + case NSC_STRING: + old = ((char **)memb_ptr)[nxt_idx]; + if (!(ca->ca_flags & NSC_CONST)) + ((char **)memb_ptr)[nxt_idx] = str ? strdup(str) : NULL; + break; + case NSC_STRINGY: + CANT_HAPPEN(nxt_idx); + if (!str) + return gripe("Field doesn't take nil"); + if (strlen(str) > ca->ca_len) + return gripe("Field %d takes at most %d characters", + fldidx + 1, ca->ca_len); + old = memb_ptr; + if (!(ca->ca_flags & NSC_CONST)) + strncpy(memb_ptr, str, ca->ca_len); + break; + default: + return gripe("Field %d doesn't take strings", fldidx + 1); + } + + if ((ca->ca_flags & NSC_CONST) && strcmp(old, str)) + return gripe("Value for field %d must be %s", fldidx + 1, old); + + nxtfld(); + return 1; } static int @@ -314,43 +436,23 @@ xunsymbol1(char *id, struct symbol *symtab, struct castr *ca, int n) } static int -xunsymbol(struct castr *ca, struct value *vp, int n) +setsym(int fldidx, char *sym) { - struct symbol *symtab = (struct symbol *)empfile[ca->ca_table].cache; - char *buf = vp->v_field.v_string; + struct castr *ca = ca4fld(fldidx); + struct symbol *symtab; int i; - int value; - char *token; - if (ca->ca_table == EF_BAD || ef_cadef(ca->ca_table) != symbol_ca) - return gripe("%s doesn't take a symbol or symbol set in field %d", - ca->ca_name, n); + if (!ca) + return -1; - if (vp->v_type == VAL_SYMBOL_SET) { - if (!(ca->ca_flags & NSC_BITS)) - return gripe("%s doesn't take a symbol set in field %d", - ca->ca_name, n); - value = 0; - for (token = strtok(buf, " "); token; token = strtok(NULL, " ")) { - i = xunsymbol1(token, symtab, ca, n); - if (i < 0) - return -1; - value |= symtab[i].value; - } - } else if (vp->v_type == VAL_SYMBOL) { - if (ca->ca_flags & NSC_BITS) - return gripe("%s doesn't take a symbol in field %d", - ca->ca_name, n); - i = xunsymbol1(buf, symtab, ca, n); - if (i < 0) - return -1; - value = symtab[i].value; - } else - return 0; + symtab = get_symtab(ca); + if (!symtab || (ca->ca_flags & NSC_BITS)) + return gripe("Field %d doesn't take symbols", fldidx + 1); - vp->v_type = VAL_DOUBLE; - vp->v_field.v_double = value; - return 0; + i = xunsymbol1(sym, symtab, ca, fldidx); + if (i < 0) + return -1; + return setnum(fldidx, symtab[i].value); } static int @@ -365,202 +467,56 @@ has_const(struct castr ca[]) return 0; } -static void -xuinitrow(int type, int row) +static int +mtsymset(int fldidx, long *set) { - struct empfile *ep = &empfile[type]; - char *ptr = ep->cache + ep->size * row; + struct castr *ca = ca4fld(fldidx); + struct symbol *symtab; + int i; - memset(ptr, 0, ep->size); + if (!ca) + return -1; - if (ep->init) - ep->init(row, ptr); + symtab = get_symtab(ca); + if (!symtab || !(ca->ca_flags & NSC_BITS)) { + return gripe("Field %d doesn't take symbol sets", fldidx + 1); + } + *set = 0; + return 0; } static int -xuloadrow(int type, int row, struct value values[]) +add2symset(int fldidx, long *set, char *sym) { - int i,j,k; - struct empfile *ep = &empfile[type]; - char *ptr = ep->cache + ep->size * row; - struct castr *ca = ep->cadef; - void *row_ref; + struct castr *ca = ca4fld(fldidx); + struct symbol *symtab; + int i; - i = 0; - j = 0; - while (ca[i].ca_type != NSC_NOTYPE && - values[j].v_type != VAL_NOTUSED) { - if (ca[i].ca_flags & NSC_EXTRA) { - i++; - continue; - } - row_ref = (char *)ptr + ca[i].ca_off; - k = 0; - do { - /* - * TODO - * factor out NSC_CONST comparsion - */ - switch (values[j].v_type) { - case VAL_SYMBOL: - case VAL_SYMBOL_SET: - if (xunsymbol(&ca[i], &values[j], j) < 0) - return -1; - /* fall through */ - case VAL_DOUBLE: - switch (ca[i].ca_type) { - case NSC_INT: - if (ca[i].ca_flags & NSC_CONST) { - if (((int *)row_ref)[k] != (int) - values[j].v_field.v_double) - gripe("Field %s must be same, " - "read %d != expected %d", - ca[i].ca_name, - ((int *)row_ref)[k], - (int)values[j].v_field.v_double); + if (!ca) + return -1; - } else - ((int *)row_ref)[k] = - (int)values[j].v_field.v_double; - break; - case NSC_LONG: - if (ca[i].ca_flags & NSC_CONST) { - if (((long *)row_ref)[k] != (long) - values[j].v_field.v_double) - gripe("Field %s must be same, " - "read %ld != expected %ld", - ca[i].ca_name, - ((long *)row_ref)[k], - (long)values[j].v_field.v_double); - } else - ((long *)row_ref)[k] = (long) - values[j].v_field.v_double; - break; - case NSC_SHORT: - if (ca[i].ca_flags & NSC_CONST) { - if (((short *)row_ref)[k] != - (short)values[j].v_field.v_double) - gripe("Field %s must be same, " - "read %d != expected %d", - ca[i].ca_name, - ((short *)row_ref)[k], - (short)values[j].v_field.v_double); - } else - ((short *)row_ref)[k] = (short) - values[j].v_field.v_double; - break; - case NSC_USHORT: - if (ca[i].ca_flags & NSC_CONST) { - if (((unsigned short *)row_ref)[k] != - (unsigned short)values[j].v_field.v_double) - gripe("Field %s must be same, " - "read %d != expected %d", - ca[i].ca_name, - ((unsigned short *)row_ref)[k], - (unsigned short)values[j].v_field.v_double); - } else - ((unsigned short *)row_ref)[k] = (unsigned short) - values[j].v_field.v_double; - break; - case NSC_UCHAR: - if (ca[i].ca_flags & NSC_CONST) { - if (((unsigned char *)row_ref)[k] != (unsigned char) - values[j].v_field.v_double) - gripe("Field %s must be same, " - "read %d != expected %d", - ca[i].ca_name, - ((unsigned char *)row_ref)[k], - (unsigned char)values[j].v_field.v_double); - } else - ((unsigned char *)row_ref)[k] = (unsigned char) - values[j].v_field.v_double; - break; - case NSC_FLOAT: - if (ca[i].ca_flags & NSC_CONST) { - if (((float *)row_ref)[k] != (float) - values[j].v_field.v_double) - gripe("Field %s must be same, " - "read %g != expected %g", - ca[i].ca_name, - ((float *)row_ref)[k], - (float)values[j].v_field.v_double); - } else - ((float *)row_ref)[k] = (float) - values[j].v_field.v_double; - break; - case NSC_STRING: - return gripe("Field %s is a string type, " - "but %lg was read which is a number", - ca[i].ca_name, values[j].v_field.v_double); - default: - return gripe("Field %s's type %d is not supported", - ca[i].ca_name, ca[i].ca_type); - } - break; - case VAL_STRING: - switch(ca[i].ca_type) { - case NSC_STRING: - if (ca[i].ca_flags & NSC_CONST) { - if (strcmp(((char **)row_ref)[k], - values[j].v_field.v_string) != 0) - gripe("Field %s must be same, " - "read %s != expected %s", - ca[i].ca_name, - ((char **)row_ref)[k], - values[j].v_field.v_string); - } else - ((char **)row_ref)[k] - = strdup(values[j].v_field.v_string); - break; - case NSC_INT: - case NSC_LONG: - case NSC_SHORT: - case NSC_USHORT: - case NSC_UCHAR: - case NSC_FLOAT: - return gripe("Field %s is a number type %d, " - "but %s was read which is a string", - ca[i].ca_name, ca[i].ca_type, - values[j].v_field.v_string); - default: - return gripe("Field %s's type %d is not supported", - ca[i].ca_name, ca[i].ca_type); - } - break; - case VAL_NOTUSED: - return gripe("Missing column %s in file", ca[i].ca_name); - case VAL_INDEX_ID: - case VAL_INDEX_SYMBOL: - return gripe("Index fields not supported in data rows in %s file", - ca[i].ca_name); - default: - return gripe("Unknown value type %d", values[j].v_type); - } - k++; - j++; - } while (k < ca[i].ca_len); - i++; - } - if (ca[i].ca_type != NSC_NOTYPE) - return gripe("Missing column %s in file", ca[i].ca_name); - switch (values[j].v_type) { - case VAL_NOTUSED: - break; - case VAL_STRING: - case VAL_SYMBOL: - case VAL_SYMBOL_SET: - return gripe("Extra junk after the last column, read %s", - values[j].v_field.v_string); - case VAL_DOUBLE: - return gripe("Extra junk after the last column, read %lg", - values[j].v_field.v_double); - default: - return gripe("Extra junk after the last column, " - "unknown value type %d", values[j].v_type); - } + symtab = get_symtab(ca); + i = xunsymbol1(sym, symtab, ca, fldidx); + if (i < 0) + return -1; + *set |= symtab[i].value; return 0; } +static struct symbol * +get_symtab(struct castr *ca) +{ + int symtype = ca->ca_table; + struct symbol *symtab; + + if (symtype == EF_BAD || ef_cadef(symtype) != symbol_ca) + return NULL; + + symtab = ef_ptr(symtype, 0); + CANT_HAPPEN(!symtab); + return symtab; +} + static int xuheader(FILE *fp, int expected_table) { @@ -582,9 +538,6 @@ xuheader(FILE *fp, int expected_table) name, &res) != 1) || res < 0) return gripe("Expected xdump header"); - if (skipfs(fp) != '\n') - return gripe("Junk after xdump header"); - type = ef_byname(name); if (type < 0) return gripe("Unknown table `%s'", name); @@ -595,95 +548,11 @@ xuheader(FILE *fp, int expected_table) if (CANT_HAPPEN(!(ef_flags(type) & EFF_MEM))) return -1; - return type; -} - -static int -xucolumnheader(FILE *fp, int type, struct value values[]) -{ - char ch; - struct empfile *ep = &empfile[type]; - struct castr *ca = ep->cadef; - int i, j, k; - - if (!human) - return 0; - - while ((ch = skipfs(fp)) == '\n'); - ungetc(ch, fp); - - /* FIXME parse column header */ - if (xuflds(fp, values, xufldname) <= 0) { - freeflds(values); - return -1; - } - /* TODO - * check column count form xuflds() - */ - - j = 0; - for (i = 0; ca[i].ca_name; i++) { - if (ca[i].ca_flags & NSC_EXTRA) - continue; - k = 0; - do { - if (values[j].v_type == VAL_NOTUSED) { - freeflds(values); - return gripe("Not enough columns in the header for table %s", - ef_nameof(type)); - } - switch(values[j].v_type) { - case VAL_SYMBOL: - if (ca[i].ca_len != 0) { - freeflds(values); - return gripe("Column %s is a not index format for table %s", - ca[i].ca_name, ef_nameof(type)); - } - if (strcmp(values[j].v_field.v_string, ca[i].ca_name) != 0) { - gripe("Column name (%s) does not match header name (%s)", - ca[i].ca_name, values[j].v_field.v_string); - freeflds(values); - return -1; - } - break; - case VAL_INDEX_SYMBOL: - return gripe("Column %s is does not currently support index symbol format for table %s", - ca[i].ca_name, ef_nameof(type)); - case VAL_INDEX_ID: - if (ca[i].ca_len == 0) { - freeflds(values); - return gripe("Column %s is in index format and should not be for table %s", - ca[i].ca_name, ef_nameof(type)); - } - if (values[j].v_field.v_int != k) { - freeflds(values); - return gripe("Column Array index %d does not match %d", - values[j].v_field.v_int, k); - } - if (strcmp(values[j].v_index_name, ca[i].ca_name) != 0) { - gripe("Column name (%s) does not match header name (%s)", - ca[i].ca_name, values[j].v_field.v_string); - freeflds(values); - return -1; - } - break; - default: - freeflds(values); - return gripe("Column %s is a not string for table %s", - ca[i].ca_name, ef_nameof(type)); - } - j++; - k++; - } while (k < ca[i].ca_len); - } - if (values[j].v_type != VAL_NOTUSED) { - freeflds(values); - return gripe("Too many columns in the header for table %s", - ef_nameof(type)); - } + if (skipfs(fp) != '\n') + return gripe("Junk after xdump header"); lineno++; - freeflds(values); - return 0; + + return type; } static int @@ -712,68 +581,72 @@ xutrailer(FILE *fp, int type, int row) int xundump(FILE *fp, char *file, int expected_table) { - int row, res, ch; struct empfile *ep; - int need_sentinel; - struct value values[MAX_NUM_COLUMNS + 1]; - int type; - int fixed_rows; + int type, fixed_rows, need_sentinel; + int row, res, ch; - memset(values, 0, sizeof(values)); - - if (strcmp(fname, file) != 0) { + if (fname != file) { fname = file; lineno = 1; - } else - lineno++; + } - if ((type = xuheader(fp, expected_table)) == -1) + if ((type = xuheader(fp, expected_table)) < 0) return -1; - + ep = &empfile[type]; fixed_rows = has_const(ef_cadef(type)); need_sentinel = !EF_IS_GAME_STATE(type); - if (xucolumnheader(fp, type, values) == -1) - return -1; + cur_type = type; + if (human) { + nxt_sel = nxt_idx = 0; + if (xuflds(fp, xufldname) < 0) + return -1; + } - row = 0; - for (;;) { - lineno++; + for (row = 0;; ++row) { ch = skipfs(fp); if (ch == '/') break; ungetc(ch, fp); - /* - * TODO - * Add column count check to the return value of xuflds() - */ - res = xuflds(fp, values, xufld); - if (res > 0 && row >= ep->csize - 1) { - /* TODO grow cache unless EFF_STATIC */ - gripe("Too many rows for table %s", ef_nameof(type)); - res = -1; + /* TODO ability to skip records */ + if (!fixed_rows) { + if (row >= ep->csize - !!need_sentinel) + /* TODO grow cache unless EFF_STATIC */ + return gripe("Too many rows for table %s", ef_nameof(type)); + if (row >= ep->cids) + /* TODO grow file */ + ep->cids = ep->fids = row + 1; } - if (res > 0) { - if (!fixed_rows) - xuinitrow(type, row); - res = xuloadrow(type, row, values); - row++; - } - freeflds(values); + cur_obj = ef_ptr(type, row); + if (!cur_obj) + return gripe("Too many rows for table %s", ef_nameof(type)); + nxt_sel = nxt_idx = 0; + res = xuflds(fp, xufld); if (res < 0) return -1; } - if (fixed_rows && row != ep->csize -1) - return gripe("Table %s requires %d rows, got %d", - ef_nameof(type), ep->csize - 1, row); + if (row != ep->fids) { + if (fixed_rows) + return gripe("Table %s requires %d rows, got %d", + ef_nameof(type), ep->fids, row); + else { + ep->cids = ep->fids = row; + if (EF_IS_GAME_STATE(type) && row != ep->csize) + /* TODO truncate file */ + gripe("Warning: should resize table %s from %d to %d, not implemented", + ef_nameof(type), ep->csize, row); + } + } - if (need_sentinel) - xuinitrow(type, row); + if (need_sentinel) { + if (CANT_HAPPEN(row >= ep->csize)) + return gripe("No space for sentinel"); + memset(ep->cache + ep->size * row, 0, ep->size); + } - if (xutrailer(fp, type, row) == -1) + if (xutrailer(fp, type, row) < 0) return -1; - ep->fids = ep->cids = row; return type; }