00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include <config.h>
00055
00056 #include <ctype.h>
00057 #include <stdarg.h>
00058 #include <stdio.h>
00059 #include <time.h>
00060 #include "file.h"
00061 #include "match.h"
00062 #include "nsc.h"
00063 #include "optlist.h"
00064 #include "prototypes.h"
00065
00066 static char *fname;
00067 static int lineno;
00068 static int human;
00069 static int ellipsis;
00070 static int is_partial;
00071 static int cur_type;
00072 static void *cur_obj;
00073 static int cur_id;
00074 static int cur_obj_is_blank;
00075 static int nflds;
00076 static struct castr **fldca;
00077 static int *fldidx;
00078 static int *caflds;
00079 static int *cafldspp;
00080
00081 static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
00082 static int deffld(int, char *, int);
00083 static int defellipsis(void);
00084 static int chkflds(void);
00085 static int setnum(int, double);
00086 static int setstr(int, char *);
00087 static int xunsymbol(char *, struct castr *, int);
00088 static int setsym(int, char *);
00089 static int mtsymset(int, long *);
00090 static int add2symset(int, long *, char *);
00091 static int xubody(FILE *);
00092 static int xutail(FILE *, struct castr *);
00093
00094
00095
00096
00097 static int
00098 gripe(char *fmt, ...)
00099 {
00100 va_list ap;
00101
00102 fprintf(stderr, "%s:%d: ", fname, lineno);
00103 va_start(ap, fmt);
00104 vfprintf(stderr, fmt, ap);
00105 va_end(ap);
00106 putc('\n', stderr);
00107
00108 return -1;
00109 }
00110
00111
00112
00113
00114
00115 static int
00116 skipfs(FILE *fp)
00117 {
00118 int ch;
00119
00120 do {
00121 ch = getc(fp);
00122 } while (ch == ' ' || ch == '\t');
00123
00124 if (ch == '#') {
00125 do {
00126 ch = getc(fp);
00127 } while (ch != EOF && ch != '\n');
00128 }
00129
00130 return ch;
00131 }
00132
00133
00134
00135
00136
00137
00138 static int
00139 getid(FILE *fp, char *buf)
00140 {
00141 int n;
00142 if (fscanf(fp, "%1023[^#()<>=#\" \t\n]%n", buf, &n) != 1
00143 || !isalpha(buf[0]))
00144 return -1;
00145 return n;
00146 }
00147
00148
00149
00150
00151
00152 static char *
00153 xuesc(char *buf)
00154 {
00155 char *src, *dst;
00156 int octal_chr, n;
00157
00158 dst = buf;
00159 src = buf;
00160 while (*src) {
00161 if (*src == '\\') {
00162 if (sscanf(++src, "%3o%n", &octal_chr, &n) != 1 || n != 3)
00163 return NULL;
00164 *dst++ = (char)octal_chr;
00165 src += 3;
00166 } else
00167 *dst++ = *src++;
00168 }
00169 *dst = '\0';
00170 return buf;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180 static int
00181 xufldname(FILE *fp, int i)
00182 {
00183 int ch, idx;
00184 char buf[1024];
00185
00186 ch = skipfs(fp);
00187 switch (ch) {
00188 case EOF:
00189 return gripe("Unexpected EOF");
00190 case '\n':
00191 if (chkflds() < 0)
00192 return -1;
00193 lineno++;
00194 return 0;
00195 case '.':
00196 if (getc(fp) != '.' || getc(fp) != '.')
00197 return gripe("Junk in header field %d", i + 1);
00198 if (defellipsis() < 0)
00199 return -1;
00200 ch = skipfs(fp);
00201 if (ch != EOF && ch != '\n')
00202 return gripe("Junk after ...");
00203 ungetc(ch, fp);
00204 return 1;
00205 default:
00206 ungetc(ch, fp);
00207 if (getid(fp, buf) < 0)
00208 return gripe("Junk in header field %d", i + 1);
00209 ch = getc(fp);
00210 if (ch != '(') {
00211 ungetc(ch, fp);
00212 return deffld(i, buf, -1);
00213 }
00214 ch = getc(fp);
00215 ungetc(ch, fp);
00216 if (isdigit(ch) || ch == '-' || ch == '+') {
00217 if (fscanf(fp, "%d", &idx) != 1)
00218 return gripe("Malformed number in index of header field %d",
00219 i + 1);
00220 if (idx < 0)
00221 return gripe("Index must not be negative in header field %d",
00222 i + 1);
00223 } else {
00224 if (getid(fp, buf) < 0)
00225 return gripe("Malformed index in header field %d", i + 1);
00226 return gripe("Symbolic index in header field %d not yet implemented",
00227 i + 1);
00228 }
00229 ch = getc(fp);
00230 if (ch != ')')
00231 return gripe("Malformed index in header field %d", i + 1);
00232 return deffld(i, buf, idx);
00233 }
00234 }
00235
00236
00237
00238
00239
00240
00241 static int
00242 xufld(FILE *fp, int i)
00243 {
00244 int ch;
00245 char buf[1024];
00246 double dbl;
00247 long set;
00248
00249 ch = skipfs(fp);
00250 switch (ch) {
00251 case EOF:
00252 return gripe("Unexpected EOF");
00253 case '\n':
00254 CANT_HAPPEN(i > nflds);
00255 if (i < nflds) {
00256 if (fldca[i]->ca_type != NSC_STRINGY && fldca[i]->ca_len)
00257 return gripe("Field %s(%d) missing",
00258 fldca[i]->ca_name, fldidx[i]);
00259 return gripe("Field %s missing", fldca[i]->ca_name);
00260 }
00261 lineno++;
00262 return 0;
00263 case '+': case '-': case '.':
00264 case '0': case '1': case '2': case '3': case '4':
00265 case '5': case '6': case '7': case '8': case '9':
00266 ungetc(ch, fp);
00267 if (fscanf(fp, "%lg", &dbl) != 1)
00268 return gripe("Malformed number in field %d", i + 1);
00269 return setnum(i, dbl);
00270 case '"':
00271 ch = getc(fp);
00272 if (ch == '"')
00273 buf[0] = 0;
00274 else {
00275 ungetc(ch, fp);
00276 if (fscanf(fp, "%1023[^\"\n]", buf) != 1 || getc(fp) != '"')
00277 return gripe("Malformed string in field %d", i + 1);
00278 if (!xuesc(buf))
00279 return gripe("Invalid escape sequence in field %d",
00280 i + 1);
00281 }
00282 return setstr(i, buf);
00283 case '(':
00284 if (mtsymset(i, &set) < 0)
00285 return -1;
00286 for (;;) {
00287 ch = skipfs(fp);
00288 if (ch == EOF || ch == '\n')
00289 return gripe("Unmatched '(' in field %d", i + 1);
00290 if (ch == ')')
00291 break;
00292 ungetc(ch, fp);
00293 if (getid(fp, buf) < 0)
00294 return gripe("Junk in field %d", i + 1);
00295 if (add2symset(i, &set, buf) < 0)
00296 return -1;
00297 }
00298 return setnum(i, set);
00299 default:
00300 ungetc(ch, fp);
00301 if (getid(fp, buf) < 0)
00302 return gripe("Junk in field %d", i + 1);
00303 if (!strcmp(buf, "nil"))
00304 return setstr(i, NULL);
00305 else
00306 return setsym(i, buf);
00307 }
00308 }
00309
00310
00311
00312
00313
00314
00315 static int
00316 xuflds(FILE *fp, int (*parse)(FILE *, int))
00317 {
00318 int i, ch, res;
00319
00320 for (i = 0; ; i++) {
00321 res = parse(fp, i);
00322 if (res < 0)
00323 return -1;
00324 if (res == 0)
00325 return i;
00326 ch = getc(fp);
00327 if (ch == '\n')
00328 ungetc(ch, fp);
00329 else if (ch != ' ' && ch != '\t')
00330 return gripe("Bad field separator after field %d", i + 1);
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 static int
00342 deffld(int fldno, char *name, int idx)
00343 {
00344 struct castr *ca = ef_cadef(cur_type);
00345 int res;
00346
00347 res = stmtch(name, ca, offsetof(struct castr, ca_name),
00348 sizeof(struct castr));
00349 if (res < 0)
00350 return gripe("Header %s of field %d is %s", name, fldno + 1,
00351 res == M_NOTUNIQUE ? "ambiguous" : "unknown");
00352 if (ca[res].ca_type != NSC_STRINGY && ca[res].ca_len != 0) {
00353 if (idx < 0)
00354 return gripe("Header %s requires an index in field %d",
00355 ca[res].ca_name, fldno + 1);
00356 if (idx >= ca[res].ca_len)
00357 return gripe("Header %s(%d) index out of bounds in field %d",
00358 ca[res].ca_name, idx, fldno + 1);
00359 if (idx < caflds[res])
00360 return gripe("Duplicate header %s(%d) in field %d",
00361 ca[res].ca_name, idx, fldno + 1);
00362 if (idx > caflds[res])
00363 return gripe("Expected header %s(%d) in field %d",
00364 ca[res].ca_name, caflds[res], fldno + 1);
00365 } else {
00366 if (idx >= 0)
00367 return gripe("Header %s doesn't take an index in field %d",
00368 ca[res].ca_name, fldno + 1);
00369 idx = 0;
00370 if (caflds[res])
00371 return gripe("Duplicate header %s in field %d",
00372 ca[res].ca_name, fldno + 1);
00373 }
00374 fldca[fldno] = &ca[res];
00375 fldidx[fldno] = idx;
00376 caflds[res]++;
00377 return 1;
00378 }
00379
00380
00381
00382
00383
00384
00385 static int
00386 defellipsis(void)
00387 {
00388 struct castr *ca = ef_cadef(cur_type);
00389
00390 if (ca[0].ca_table != cur_type)
00391 return gripe("Table %s doesn't support ...", ef_nameof(cur_type));
00392 ellipsis = is_partial = 1;
00393 return 0;
00394 }
00395
00396
00397
00398
00399
00400 static int
00401 chkflds(void)
00402 {
00403 struct castr *ca = ef_cadef(cur_type);
00404 int i, len, cafldsmax, res = 0;
00405
00406 if (is_partial) {
00407
00408 if (!caflds[0])
00409 return gripe("Header field %s required with ...", ca[0].ca_name);
00410 }
00411
00412 if (ellipsis)
00413 return 0;
00414
00415 for (i = 0; ca[i].ca_name; i++) {
00416 cafldsmax = MAX(caflds[i], cafldspp[i]);
00417 if (ca[i].ca_flags & NSC_EXTRA)
00418 continue;
00419 len = ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0;
00420 if (!len && !cafldsmax)
00421 res = gripe("Header field %s missing", ca[i].ca_name);
00422 else if (len && cafldsmax == len - 1)
00423 res = gripe("Header field %s(%d) missing",
00424 ca[i].ca_name, len - 1);
00425 else if (len && cafldsmax < len - 1)
00426 res = gripe("Header fields %s(%d) ... %s(%d) missing",
00427 ca[i].ca_name, cafldsmax, ca[i].ca_name, len - 1);
00428 }
00429
00430 return res;
00431 }
00432
00433
00434
00435
00436
00437
00438 static struct castr *
00439 getfld(int fldno, int *idx)
00440 {
00441 if (fldno >= nflds) {
00442 gripe("Too many fields, expected only %d", nflds);
00443 return NULL;
00444 }
00445 if (CANT_HAPPEN(fldno < 0))
00446 return NULL;
00447 if (idx)
00448 *idx = fldidx[fldno];
00449 return fldca[fldno];
00450 }
00451
00452
00453
00454
00455 static int
00456 fldval_must_match(int fldno)
00457 {
00458 struct castr *ca = ef_cadef(cur_type);
00459 int i = fldca[fldno] - ca;
00460
00461
00462
00463
00464
00465
00466 return (!cur_obj_is_blank && (fldca[fldno]->ca_flags & NSC_CONST))
00467 || fldidx[fldno] < cafldspp[i];
00468 }
00469
00470
00471
00472
00473
00474
00475 static void *
00476 getobj(void)
00477 {
00478 struct empfile *ep = &empfile[cur_type];
00479 int need_sentinel = !EF_IS_GAME_STATE(cur_type);
00480
00481 if (!cur_obj) {
00482 cur_obj_is_blank = cur_id >= ep->fids;
00483 if (cur_obj_is_blank) {
00484
00485 if (cur_id < ep->csize - !!need_sentinel)
00486 ep->cids = ep->fids = cur_id + 1;
00487
00488 }
00489 cur_obj = ef_ptr(cur_type, cur_id);
00490 if (!cur_obj)
00491 gripe("Can't put ID %d into table %s, it holds only 0..%d.",
00492 cur_id, ep->name, ep->fids - 1);
00493 }
00494
00495 return cur_obj;
00496 }
00497
00498
00499
00500
00501
00502 static int
00503 setnum(int fldno, double dbl)
00504 {
00505 struct castr *ca;
00506 int idx;
00507 char *memb_ptr;
00508 double old;
00509
00510 ca = getfld(fldno, &idx);
00511 if (!ca)
00512 return -1;
00513
00514
00515
00516
00517 if (fldno == 0 && ca->ca_table == cur_type)
00518 cur_id = (int)dbl;
00519
00520 memb_ptr = getobj();
00521 if (!memb_ptr)
00522 return -1;
00523 memb_ptr += ca->ca_off;
00524
00525
00526 switch (ca->ca_type) {
00527 case NSC_CHAR:
00528 old = ((signed char *)memb_ptr)[idx];
00529 ((signed char *)memb_ptr)[idx] = (signed char)dbl;
00530 break;
00531 case NSC_UCHAR:
00532 case NSC_HIDDEN:
00533 old = ((unsigned char *)memb_ptr)[idx];
00534 ((unsigned char *)memb_ptr)[idx] = (unsigned char)dbl;
00535 break;
00536 case NSC_SHORT:
00537 old = ((short *)memb_ptr)[idx];
00538 ((short *)memb_ptr)[idx] = (short)dbl;
00539 break;
00540 case NSC_USHORT:
00541 old = ((unsigned short *)memb_ptr)[idx];
00542 ((unsigned short *)memb_ptr)[idx] = (unsigned short)dbl;
00543 break;
00544 case NSC_INT:
00545 old = ((int *)memb_ptr)[idx];
00546 ((int *)memb_ptr)[idx] = (int)dbl;
00547 break;
00548 case NSC_LONG:
00549 old = ((long *)memb_ptr)[idx];
00550 ((long *)memb_ptr)[idx] = (long)dbl;
00551 break;
00552 case NSC_XCOORD:
00553 old = ((coord *)memb_ptr)[idx];
00554
00555 if (old >= WORLD_X / 2)
00556 old -= WORLD_X;
00557 ((coord *)memb_ptr)[idx] = XNORM((coord)dbl);
00558 break;
00559 case NSC_YCOORD:
00560 old = ((coord *)memb_ptr)[idx];
00561
00562 if (old >= WORLD_Y / 2)
00563 old -= WORLD_Y;
00564 ((coord *)memb_ptr)[idx] = YNORM((coord)dbl);
00565 break;
00566 case NSC_FLOAT:
00567 old = ((float *)memb_ptr)[idx];
00568 ((float *)memb_ptr)[idx] = (float)dbl;
00569 break;
00570 case NSC_DOUBLE:
00571 old = ((double *)memb_ptr)[idx];
00572 ((double *)memb_ptr)[idx] = dbl;
00573 break;
00574 case NSC_TIME:
00575 old = ((time_t *)memb_ptr)[idx];
00576 ((time_t *)memb_ptr)[idx] = (time_t)dbl;
00577 break;
00578 default:
00579 return gripe("Field %d doesn't take numbers", fldno + 1);
00580 }
00581
00582 if (fldval_must_match(fldno) && old != dbl)
00583 return gripe("Value for field %d must be %g", fldno + 1, old);
00584
00585 return 1;
00586 }
00587
00588
00589
00590
00591
00592 static int
00593 setstr(int fldno, char *str)
00594 {
00595 struct castr *ca;
00596 int must_match, idx;
00597 size_t len;
00598 char *memb_ptr, *old;
00599
00600 ca = getfld(fldno, &idx);
00601 if (!ca)
00602 return -1;
00603
00604 memb_ptr = getobj();
00605 if (!memb_ptr)
00606 return -1;
00607 memb_ptr += ca->ca_off;
00608 must_match = fldval_must_match(fldno);
00609
00610 switch (ca->ca_type) {
00611 case NSC_STRING:
00612 old = ((char **)memb_ptr)[idx];
00613 if (!must_match)
00614 ((char **)memb_ptr)[idx] = str ? strdup(str) : NULL;
00615 len = 65535;
00616 break;
00617 case NSC_STRINGY:
00618 if (CANT_HAPPEN(idx))
00619 return -1;
00620 if (!str)
00621 return gripe("Field %d doesn't take nil", fldno + 1);
00622 len = ca->ca_len;
00623 if (strlen(str) > len)
00624 return gripe("Field %d takes at most %d characters",
00625 fldno + 1, (int)len);
00626 old = memb_ptr;
00627 if (!must_match)
00628 strncpy(memb_ptr, str, len);
00629 break;
00630 default:
00631 return gripe("Field %d doesn't take strings", fldno + 1);
00632 }
00633
00634 if (must_match) {
00635 if (old && (!str || strncmp(old, str, len)))
00636 return gripe("Value for field %d must be \"%.*s\"",
00637 fldno + 1, (int)len, old);
00638 if (!old && str)
00639 return gripe("Value for field %d must be nil", fldno + 1);
00640 }
00641
00642 return 1;
00643 }
00644
00645
00646
00647
00648
00649
00650 static int
00651 xunsymbol(char *id, struct castr *ca, int n)
00652 {
00653 int i = ef_elt_byname(ca->ca_table, id);
00654 if (i < 0)
00655 return gripe("%s %s symbol `%s' in field %d",
00656 i == M_NOTUNIQUE ? "Ambiguous" : "Unknown",
00657 ca->ca_name, id, n + 1);
00658 return i;
00659 }
00660
00661
00662
00663
00664
00665 static int
00666 symval(struct castr *ca, int i)
00667 {
00668 int type = ca->ca_table;
00669
00670 if (ef_check(type) < 0)
00671 return -1;
00672 if (ef_cadef(type) == symbol_ca)
00673
00674 return ((struct symbol *)ef_ptr(type, i))->value;
00675
00676 return i;
00677 }
00678
00679
00680
00681
00682
00683 static int
00684 setsym(int fldno, char *sym)
00685 {
00686 struct castr *ca;
00687 int i;
00688
00689 ca = getfld(fldno, NULL);
00690 if (!ca)
00691 return -1;
00692
00693 if (ca->ca_table == EF_BAD || (ca->ca_flags & NSC_BITS))
00694 return gripe("Field %d doesn't take symbols", fldno + 1);
00695
00696 i = xunsymbol(sym, ca, fldno);
00697 if (i < 0)
00698 return -1;
00699 return setnum(fldno, symval(ca, i));
00700 }
00701
00702
00703
00704
00705
00706 static int
00707 mtsymset(int fldno, long *set)
00708 {
00709 struct castr *ca;
00710
00711 ca = getfld(fldno, NULL);
00712 if (!ca)
00713 return -1;
00714
00715 if (ca->ca_table == EF_BAD || ef_cadef(ca->ca_table) != symbol_ca
00716 || !(ca->ca_flags & NSC_BITS))
00717 return gripe("Field %d doesn't take symbol sets", fldno + 1);
00718 *set = 0;
00719 return 0;
00720 }
00721
00722
00723
00724
00725
00726
00727 static int
00728 add2symset(int fldno, long *set, char *sym)
00729 {
00730 struct castr *ca;
00731 int i;
00732
00733 ca = getfld(fldno, NULL);
00734 if (!ca)
00735 return -1;
00736
00737 i = xunsymbol(sym, ca, fldno);
00738 if (i < 0)
00739 return -1;
00740 *set |= symval(ca, i);
00741 return 0;
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751 static int
00752 xuheader(FILE *fp, int expected_table)
00753 {
00754 char name[64];
00755 int res, ch;
00756 int type;
00757
00758 while ((ch = skipfs(fp)) == '\n')
00759 lineno++;
00760 if (ch == EOF && expected_table == EF_BAD)
00761 return -2;
00762 ungetc(ch, fp);
00763
00764 human = ch == 'c';
00765 res = -1;
00766 if ((human
00767 ? fscanf(fp, "config%*[ \t]%63[^ \t#\n]%n", name, &res) != 1
00768 : fscanf(fp, "XDUMP%*[ \t]%63[^ \t#\n]%*[ \t]%*[^ \t#\n]%n",
00769 name, &res) != 1) || res < 0)
00770 return gripe("Expected xdump header");
00771
00772 type = ef_byname(name);
00773 if (type < 0)
00774 return gripe("Unknown table `%s'", name);
00775 if (expected_table != EF_BAD && expected_table != type)
00776 return gripe("Expected table `%s', not `%s'",
00777 ef_nameof(expected_table), name);
00778
00779 if (!ef_cadef(type) || !(ef_flags(type) & EFF_MEM)) {
00780 CANT_HAPPEN(expected_table != EF_BAD);
00781 return gripe("Table `%s' is not permitted here", name);
00782 }
00783
00784 if (skipfs(fp) != '\n')
00785 return gripe("Junk after xdump header");
00786 lineno++;
00787
00788 return type;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798 static int
00799 xufldhdr(FILE *fp, struct castr ca[])
00800 {
00801 struct castr **fca;
00802 int *fidx;
00803 int ch, i, j, n;
00804
00805 for (i = 0; ca[i].ca_name; i++)
00806 caflds[i] = 0;
00807 ellipsis = 0;
00808
00809 if (human) {
00810 while ((ch = skipfs(fp)) == '\n')
00811 lineno++;
00812 ungetc(ch, fp);
00813 nflds = xuflds(fp, xufldname);
00814 if (nflds < 0)
00815 return -1;
00816 nflds -= ellipsis != 0;
00817 } else {
00818 fca = fldca;
00819 fidx = fldidx;
00820
00821 for (i = 0; ca[i].ca_name; i++) {
00822 if ((ca[i].ca_flags & NSC_EXTRA))
00823 continue;
00824 n = ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0;
00825 j = 0;
00826 do {
00827 *fca++ = &ca[i];
00828 *fidx++ = j;
00829 } while (++j < n);
00830 }
00831
00832 nflds = fidx - fldidx;
00833 }
00834
00835 return 0;
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845 static int
00846 xufooter(FILE *fp, struct castr ca[], int recs)
00847 {
00848 int res, n, i;
00849
00850 res = -1;
00851 if (human) {
00852 if (fscanf(fp, "config%n", &res) != 0 || res < 0)
00853 return gripe("Malformed table footer");
00854 } else {
00855 if (fscanf(fp, "%d", &n) != 1)
00856 return gripe("Malformed table footer");
00857 if (recs != n)
00858 return gripe("Read %d rows, which doesn't match footer "
00859 "%d rows", recs, n);
00860 }
00861 if (skipfs(fp) != '\n')
00862 return gripe("Junk after table footer");
00863 lineno++;
00864
00865 for (i = 0; ca[i].ca_name; i++) {
00866 if (cafldspp[i] < caflds[i])
00867 cafldspp[i] = caflds[i];
00868 }
00869
00870 return 0;
00871 }
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 int
00883 xundump(FILE *fp, char *file, int *plno, int expected_table)
00884 {
00885 struct castr *ca;
00886 int type, nca, nf, i, ch;
00887
00888 fname = file;
00889 lineno = *plno;
00890
00891 if ((type = xuheader(fp, expected_table)) < 0)
00892 return type;
00893
00894 ca = ef_cadef(type);
00895 if (CANT_HAPPEN(!ca))
00896 return -1;
00897
00898 nca = nf = 0;
00899 for (i = 0; ca[i].ca_name; i++) {
00900 nca++;
00901 if (!(ca[i].ca_flags & NSC_EXTRA))
00902 nf += MAX(1, ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0);
00903 }
00904 fldca = malloc(nf * sizeof(*fldca));
00905 fldidx = malloc(nf * sizeof(*fldidx));
00906 caflds = malloc(nca * sizeof(*caflds));
00907 cafldspp = calloc(nca, sizeof(*cafldspp));
00908 cur_type = type;
00909
00910 if (xutail(fp, ca) < 0)
00911 type = EF_BAD;
00912
00913 free(cafldspp);
00914 free(caflds);
00915 free(fldidx);
00916 free(fldca);
00917
00918
00919 while ((ch = skipfs(fp)) == '\n')
00920 lineno++;
00921 ungetc(ch, fp);
00922
00923 *plno = lineno;
00924 return type;
00925 }
00926
00927
00928
00929
00930
00931
00932 static int
00933 xutail(FILE *fp, struct castr *ca)
00934 {
00935 int recs;
00936
00937 is_partial = 0;
00938 for (;;) {
00939 if (xufldhdr(fp, ca) < 0)
00940 return -1;
00941 if ((recs = xubody(fp)) < 0)
00942 return -1;
00943 if (xufooter(fp, ca, recs) < 0)
00944 return -1;
00945 if (!ellipsis)
00946 return 0;
00947 if (xuheader(fp, cur_type) < 0)
00948 return -1;
00949 }
00950 }
00951
00952
00953
00954
00955
00956 static int
00957 xubody(FILE *fp)
00958 {
00959 struct empfile *ep = &empfile[cur_type];
00960 int need_sentinel = !EF_IS_GAME_STATE(cur_type);
00961 int i, maxid, ch;
00962
00963 maxid = 0;
00964 for (i = 0;; ++i) {
00965 while ((ch = skipfs(fp)) == '\n')
00966 lineno++;
00967 if (ch == '/')
00968 break;
00969 ungetc(ch, fp);
00970 cur_obj = NULL;
00971 cur_id = i;
00972 if (xuflds(fp, xufld) < 0)
00973 return -1;
00974 maxid = MAX(maxid, cur_id + 1);
00975 }
00976
00977 if (CANT_HAPPEN(maxid > ep->fids))
00978 maxid = ep->fids;
00979 if (maxid < ep->fids) {
00980 if (EF_IS_GAME_STATE(cur_type) && maxid != ep->csize)
00981
00982 gripe("Warning: should resize table %s from %d to %d, not implemented",
00983 ef_nameof(cur_type), ep->csize, maxid);
00984 else if (cur_type >= EF_SHIP_CHR && cur_type <= EF_NUKE_CHR)
00985 ep->cids = ep->fids = maxid;
00986 else
00987 return gripe("Table %s requires %d rows, got %d",
00988 ef_nameof(cur_type), ep->fids, maxid);
00989 }
00990
00991 if (need_sentinel) {
00992 if (CANT_HAPPEN(maxid >= ep->csize))
00993 return gripe("No space for sentinel");
00994 memset(ep->cache + ep->size * maxid, 0, ep->size);
00995 }
00996
00997 return i;
00998 }