]> git.pond.sub.org Git - empserver/blob - src/lib/common/xundump.c
xundump: Pass unsigned * for scanf directive %3o, not int *
[empserver] / src / lib / common / xundump.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  xundump.c: Load back xdump output
28  *
29  *  Known contributors to this file:
30  *     Ron Koenderink, 2005
31  *     Markus Armbruster, 2005-2014
32  */
33
34 /*
35  * See doc/xdump!  And keep it up-to-date.
36  *
37  * Parsing of machine-readable xdump is not precise: it recognizes
38  * comments, accepts whitespace in place of single space, and accepts
39  * the full human-readable field syntax instead of its machine-
40  * readable subset.
41  *
42  * FIXME:
43  * - Normalize terminology: table/rows/columns or file/records/fields
44  * - Loading tables with NSC_STRING elements more than once leaks memory
45  * TODO:
46  * - Symbolic array indexes
47  * - Option to treat missing and unknown fields as warning, not error
48  * TODO, but hardly worth the effort:
49  * - Permit reordering of array elements
50  */
51
52 #include <config.h>
53
54 #include <ctype.h>
55 #include <limits.h>
56 #include <stdarg.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <time.h>
61 #include "file.h"
62 #include "match.h"
63 #include "nat.h"
64 #include "nsc.h"
65 #include "optlist.h"
66 #include "xdump.h"
67
68 static char *fname;             /* Name of file being read */
69 static int lineno;              /* Current line number */
70
71 static int cur_type;            /* Current table's file type */
72 static int partno;              /* Counts from 0..#parts-1 */
73 static int cur_id;              /* and its index in the table */
74 static int old_nelem;
75 static unsigned char *idgap;    /* idgap && idgap[ID] iff part#0 lacks ID */
76 static int idgap_len;           /* #elements in idgap[] */
77
78 static int human;               /* Reading human-readable syntax? */
79 static int ellipsis;            /* Header ended with ...? */
80 static int nflds;               /* #fields in input records */
81 static struct castr **fldca;    /* Map field number to selector */
82 static int *fldidx;             /* Map field number to index */
83 static struct valstr *fldval;   /* Map field number to value */
84 static int *caflds;             /* Map selector number to #fields seen */
85 static int *cafldspp;           /* ditto, in previous parts */
86
87 static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
88 static int deffld(int, char *, int);
89 static int chkflds(void);
90 static int setnum(int, double);
91 static int setstr(int, char *);
92 static int setsym(int, char *);
93 static int mtsymset(int, long *);
94 static int add2symset(int, long *, char *);
95 static int xubody(FILE *);
96 static int xutail(FILE *, struct castr *);
97
98 /*
99  * Does the code hardcode indexes for table TYPE?
100  */
101 static int
102 have_hardcoded_indexes(int type)
103 {
104     return type == EF_ITEM || type == EF_SECTOR_CHR
105         || type == EF_INFRASTRUCTURE;
106 }
107
108 /*
109  * Okay to truncate table TYPE?
110  */
111 static int
112 may_truncate(int type)
113 {
114     return empfile[type].nent < 0 && !have_hardcoded_indexes(type);
115 }
116
117 /*
118  * Is TYPE's 0-th selector a usable ID?
119  */
120 static int
121 ca0_is_id(int type)
122 {
123     struct castr *ca = ef_cadef(type);
124
125     return ca[0].ca_table == type && !(ca[0].ca_flags & NSC_EXTRA);
126 }
127
128 /*
129  * Can we fill in gaps in table TYPE?
130  */
131 static int
132 can_fill_gaps(int type)
133 {
134     return (ca0_is_id(type) || type == EF_SECTOR || type == EF_REALM)
135         && !have_hardcoded_indexes(type);
136 }
137
138 /*
139  * Is table TYPE's ID-th record OBJ redundant for xundump()
140  */
141 int
142 xundump_redundant(int type, int id, void *obj)
143 {
144     char buf[EF_WITH_CADEF_MAX_ENTRY_SIZE];
145
146     if (!can_fill_gaps(type))
147         return 0;
148
149     if (may_truncate(type) && id == ef_nelem(type) - 1)
150         return 0;
151
152     ef_blank(type, id, buf);
153     if (ef_flags(type) & EFF_TYPED)
154         return ef_typedstr_eq((struct ef_typedstr *)buf,
155                               (struct ef_typedstr *)obj);
156     return !memcmp(obj, buf, empfile[type].size);
157 }
158
159 /*
160  * Gripe about the current line to stderr, return -1.
161  */
162 static int
163 gripe(char *fmt, ...)
164 {
165     va_list ap;
166
167     fprintf(stderr, "%s:%d: ", fname, lineno);
168     va_start(ap, fmt);
169     vfprintf(stderr, fmt, ap);
170     va_end(ap);
171     putc('\n', stderr);
172
173     return -1;
174 }
175
176 /* Make TYPE the current table.  */
177 static void
178 tbl_start(int type)
179 {
180     cur_type = type;
181     partno = 0;
182     cur_id = -1;
183     old_nelem = type == EF_BAD ? 0 : ef_nelem(type);
184     idgap = NULL;
185     idgap_len = 0;
186 }
187
188 /* End the current table.  */
189 static void
190 tbl_end(void)
191 {
192     free(idgap);
193     tbl_start(EF_BAD);
194 }
195
196 /*
197  * Seek to current table's ID-th object.
198  * Extend the table if necessary.
199  * Save ID in cur_id.
200  * Return the object on success, NULL on failure.
201  */
202 static void *
203 tbl_seek(int id)
204 {
205     void *obj;
206
207     if (id >= ef_nelem(cur_type)) {
208         if (!ef_ensure_space(cur_type, id, 1)) {
209             gripe("can't grow table to hold this row");
210             return NULL;
211         }
212     }
213
214     obj = ef_ptr(cur_type, id);
215     if (CANT_HAPPEN(!obj))
216         return NULL;
217     cur_id = id;
218     return obj;
219 }
220
221 /*
222  * Omit ID1..ID2-1.
223  * Reset the omitted objects to default state.
224  */
225 static void
226 omit_ids(int id1, int id2)
227 {
228     int i;
229
230     if (id1 >= id2)
231         return;
232
233     idgap = realloc(idgap, id2 * sizeof(*idgap));
234     for (i = idgap_len; i < id1; i++)
235         idgap[i] = 0;
236     for (i = id1; i < id2; i++) {
237         ef_blank(cur_type, i, ef_ptr(cur_type, i));
238         idgap[i] = 1;
239     }
240     idgap_len = id2;
241 }
242
243 /*
244  * Return the smallest non-omitted ID in ID1..ID2-1 if any, else -1.
245  */
246 static int
247 expected_id(int id1, int id2)
248 {
249     int i;
250
251     for (i = id1; i < id2; i++) {
252         if (i >= idgap_len || !idgap[i])
253             return i;
254     }
255     return -1;
256 }
257
258 /*
259  * Finish table part.
260  * If the table has variable length, truncate it.
261  * Else ensure we're omitting the same objects as the previous parts.
262  * Reset any omitted objects to default state.
263  * Return 0 on success, -1 on failure.
264  */
265 static int
266 tbl_part_done(void)
267 {
268     struct empfile *ep = &empfile[cur_type];
269
270     if (cur_id + 1 < ep->fids) {
271         if (partno == 0) {
272             if (may_truncate(cur_type)) {
273                 if (!ef_truncate(cur_type, cur_id + 1))
274                     return -1;
275             } else {
276                 if (!can_fill_gaps(cur_type))
277                     return gripe("expected %d more rows",
278                                  ep->fids - (cur_id + 1));
279                 omit_ids(cur_id + 1, ep->fids);
280             }
281         } else {
282             if (expected_id(cur_id + 1, ep->fids) >= 0)
283                 return gripe("table's first part has more rows");
284         }
285     }
286
287     partno++;
288     cur_id = -1;
289     return 0;
290 }
291
292 /*
293  * Get selector for field FLDNO.
294  * Assign the field's selector index to *IDX, unless it is null.
295  * Return the selector on success, null pointer on error.
296  */
297 static struct castr *
298 getfld(int fldno, int *idx)
299 {
300     if (fldno >= nflds) {
301         gripe("too many fields, expected only %d", nflds);
302         return NULL;
303     }
304     if (CANT_HAPPEN(fldno < 0))
305         return NULL;
306     if (idx)
307         *idx = fldidx[fldno];
308     return fldca[fldno];
309 }
310
311 /*
312  * Find the field for selector CA with index IDX.
313  * Return the field number if it exists, else -1.
314  */
315 static int
316 fld_find(struct castr *ca, int idx)
317 {
318     int i;
319
320     for (i = 0; i < nflds; i++) {
321         if (fldca[i] == ca && fldidx[i] == idx)
322             return i;
323     }
324     return -1;
325 }
326
327 /*
328  * Get the current row's ID.
329  * Current table's 0-th selector must be a usable ID.
330  * Return ID on success, -1 on failure.
331  */
332 static int
333 rowid(void)
334 {
335     struct castr *ca = ef_cadef(cur_type);
336     int fldno, id, max_id;
337
338     if (CANT_HAPPEN(partno != 0 || !ca0_is_id(cur_type)))
339         return -1;
340
341     fldno = fld_find(ca, 0);
342     if (fldno < 0)
343         return cur_id + 1;      /* ID not specified */
344     /*
345      * Field values not representable as int will be rejected by
346      * putnum() or putstr().  Leave the error reporting to them, and
347      * simply pick the next ID here.
348      */
349     if (fldval[fldno].val_type != NSC_DOUBLE)
350         return cur_id + 1;
351     id = fldval[fldno].val_as.dbl;
352     if (id != fldval[fldno].val_as.dbl)
353         return cur_id + 1;
354
355     if (id != cur_id + 1 && !can_fill_gaps(cur_type))
356         return gripe("expected %d in field %d",
357                      cur_id + 1, fldno + 1);
358     if (id <= cur_id)
359         return gripe("field %d must be > %d", fldno + 1, cur_id);
360     max_id = ef_id_limit(cur_type);
361     if (id > max_id)
362         return gripe("field %d must be <= %d", fldno + 1, max_id);
363
364     return id;
365 }
366
367 /*
368  * Find the field NAME with index IDX and value representable as long.
369  * Return the field number if it exists, else -1.
370  */
371 static int
372 fld_find_long_by_name(char *name, int idx)
373 {
374     int i;
375
376     for (i = 0; i < nflds; i++) {
377         if (!strcmp(fldca[i]->ca_name, name) && fldidx[i] == idx)
378             break;
379     }
380
381     if (i == nflds || fldval[i].val_type != NSC_DOUBLE
382         || (long)fldval[i].val_as.dbl != fldval[i].val_as.dbl)
383         return -1;
384     return i;
385 }
386
387 /*
388  * Get the current row's ID.
389  * Current table's type must be EF_SECTOR.
390  * Return ID on success, -1 on failure.
391  */
392 static int
393 rowid_sect(void)
394 {
395     int fldno_x, fldno_y, id;
396     coord x, y;
397
398     if (CANT_HAPPEN(partno != 0 || cur_type != EF_SECTOR))
399         return -1;
400
401     fldno_x = fld_find_long_by_name("xloc", 0);
402     fldno_y = fld_find_long_by_name("yloc", 0);
403     if (fldno_x < 0 || fldno_y < 0)
404         return cur_id + 1;
405
406     id = sctoff((long)fldval[fldno_x].val_as.dbl,
407                 (long)fldval[fldno_y].val_as.dbl);
408     /* Note: reporting values out of range left to putnum() */
409     if (id <= cur_id) {
410         sctoff2xy(&x, &y, cur_id);
411         return gripe("coordinates in fields %d,%d must be > %d,%d",
412                      fldno_x + 1, fldno_y + 1, x, y);
413     }
414     return id;
415 }
416
417 /*
418  * Get the current row's ID.
419  * Current table's type must be EF_REALM.
420  * Return ID on success, -1 on failure.
421  */
422 static int
423 rowid_realm(void)
424 {
425     int fldno_cnum, fldno_realm, id;
426     long realm, cnum;
427
428     if (CANT_HAPPEN(partno != 0 || cur_type != EF_REALM))
429         return -1;
430
431     fldno_cnum = fld_find_long_by_name("cnum", 0);
432     fldno_realm = fld_find_long_by_name("realm", 0);
433     if (fldno_cnum < 0 || fldno_realm < 0)
434         return cur_id + 1;
435
436     realm = (long)fldval[fldno_realm].val_as.dbl;
437     cnum = (long)fldval[fldno_cnum].val_as.dbl;
438     if (cnum < 0 || cnum >= MAXNOC)
439         return gripe("field %d must be between 0 and %d",
440                      fldno_cnum, MAXNOC);
441     if (realm < 0 || realm >= MAXNOR)
442         return gripe("field %d must be between 0 and %d",
443                      fldno_realm, MAXNOR);
444     id = realm + cnum * MAXNOR;
445     if (id <= cur_id)
446         return gripe("fields %d,%d must be > (%d,%d)",
447                      fldno_cnum + 1, fldno_realm + 1,
448                      cur_id / MAXNOR, cur_id % MAXNOR);
449     return id;
450 }
451 /*
452  * Get the current row's object.
453  * Extend the table if necessary.
454  * Save ID in cur_id.
455  * Return the object on success, NULL on failure.
456  */
457 static void *
458 rowobj(void)
459 {
460     int last_id = cur_id;
461     int id;
462     void *obj;
463
464     if (partno) {
465         id = expected_id(cur_id + 1, empfile[cur_type].fids);
466         if (id < 0) {
467             gripe("table's first part doesn't have this row");
468             return NULL;
469         }
470     } else if (ca0_is_id(cur_type)) {
471         id = rowid();
472         if (id < 0)
473             return NULL;
474     } else if (cur_type == EF_SECTOR) {
475         id = rowid_sect();
476         if (id < 0)
477             return NULL;
478     } else if (cur_type == EF_REALM) {
479         id = rowid_realm();
480         if (id < 0)
481             return NULL;
482     } else
483         id = last_id + 1;
484     if (id > ef_id_limit(cur_type)) {
485         gripe("too many rows");
486         return NULL;
487     }
488
489     obj = tbl_seek(id);
490     if (obj && !partno)
491         omit_ids(last_id + 1, id);
492     return obj;
493 }
494
495 /*
496  * Is a new value for field FLDNO required to match the old one?
497  */
498 static int
499 fldval_must_match(int fldno)
500 {
501     struct castr *ca = ef_cadef(cur_type);
502     int i = fldca[fldno] - ca;
503
504     /*
505      * Value must match if:
506      * it's for a const selector, unless the object is still blank, or
507      * it was already given in a previous part of a split table.
508      */
509     return (cur_id < old_nelem && (fldca[fldno]->ca_flags & NSC_CONST))
510         || fldidx[fldno] < cafldspp[i];
511 }
512
513 /*
514  * Set OBJ's field FLDNO to DBL.
515  * Return 0 on success, -1 on error.
516  */
517 static int
518 putnum(void *obj, int fldno, double dbl)
519 {
520     struct castr *ca = fldca[fldno];
521     int idx = fldidx[fldno];
522     char *memb_ptr;
523     double old, new;
524
525     memb_ptr = (char *)obj + ca->ca_off;
526
527     switch (ca->ca_type) {
528     case NSC_CHAR:
529         old = ((signed char *)memb_ptr)[idx];
530         new = ((signed char *)memb_ptr)[idx] = (signed char)dbl;
531         break;
532     case NSC_UCHAR:
533         old = ((unsigned char *)memb_ptr)[idx];
534         new = ((unsigned char *)memb_ptr)[idx] = (unsigned char)dbl;
535         break;
536     case NSC_SHORT:
537         old = ((short *)memb_ptr)[idx];
538         new = ((short *)memb_ptr)[idx] = (short)dbl;
539         break;
540     case NSC_USHORT:
541         old = ((unsigned short *)memb_ptr)[idx];
542         new = ((unsigned short *)memb_ptr)[idx] = (unsigned short)dbl;
543         break;
544     case NSC_INT:
545         old = ((int *)memb_ptr)[idx];
546         new = ((int *)memb_ptr)[idx] = (int)dbl;
547         break;
548     case NSC_LONG:
549         old = ((long *)memb_ptr)[idx];
550         new = ((long *)memb_ptr)[idx] = (long)dbl;
551         break;
552     case NSC_XCOORD:
553         old = ((coord *)memb_ptr)[idx];
554         /* FIXME use variant of xrel() that takes orig instead of nation */
555         if (old >= WORLD_X / 2)
556             old -= WORLD_X;
557         new = ((coord *)memb_ptr)[idx] = XNORM((coord)dbl);
558         if (new >= WORLD_X / 2)
559             new -= WORLD_X;
560         break;
561     case NSC_YCOORD:
562         old = ((coord *)memb_ptr)[idx];
563         /* FIXME use variant of yrel() that takes orig instead of nation */
564         if (old >= WORLD_Y / 2)
565             old -= WORLD_Y;
566         new = ((coord *)memb_ptr)[idx] = YNORM((coord)dbl);
567         if (new >= WORLD_Y / 2)
568             new -= WORLD_Y;
569         break;
570     case NSC_FLOAT:
571         old = ((float *)memb_ptr)[idx];
572         ((float *)memb_ptr)[idx] = (float)dbl;
573         new = dbl;              /* suppress new != dbl check */
574         break;
575     case NSC_DOUBLE:
576         old = ((double *)memb_ptr)[idx];
577         ((double *)memb_ptr)[idx] = dbl;
578         new = dbl;              /* suppress new != dbl check */
579         break;
580     case NSC_TIME:
581         old = ((time_t *)memb_ptr)[idx];
582         new = ((time_t *)memb_ptr)[idx] = (time_t)dbl;
583         break;
584     default:
585         return gripe("field %d doesn't take numbers", fldno + 1);
586     }
587
588     if (fldval_must_match(fldno) && old != dbl)
589         return gripe("value for field %d must be %g", fldno + 1, old);
590     if (new != dbl)
591         return gripe("field %d can't hold this value", fldno + 1);
592
593     return 0;
594 }
595
596 /*
597  * Set obj's field FLDNO to STR.
598  * Return 0 on success, -1 on error.
599  */
600 static int
601 putstr(void *obj, int fldno, char *str)
602 {
603     struct castr *ca = fldca[fldno];
604     int idx = fldidx[fldno];
605     int must_match, mismatch;
606     size_t sz, len;
607     char *memb_ptr, *old;
608
609     memb_ptr = (char *)obj + ca->ca_off;
610     must_match = fldval_must_match(fldno);
611     mismatch = 0;
612
613     switch (ca->ca_type) {
614     case NSC_STRING:
615         old = ((char **)memb_ptr)[idx];
616         if (must_match)
617             mismatch = old ? !str || strcmp(old, str) : !!str;
618         else
619             /* FIXME may leak old value */
620             ((char **)memb_ptr)[idx] = str ? strdup(str) : NULL;
621         len = -1;               /* unlimited */
622         break;
623     case NSC_STRINGY:
624         if (CANT_HAPPEN(idx))
625             return -1;
626         if (!str)
627             return gripe("field %d doesn't take nil", fldno + 1);
628         /* Wart: if ca_len <= 1, the terminating null may be omitted */
629         sz = ca->ca_len;
630         len = sz > 1 ? sz - 1 : sz;
631         if (strlen(str) > len)
632             return gripe("field %d takes at most %d characters",
633                          fldno + 1, (int)len);
634         old = memb_ptr;
635         if (must_match)
636             mismatch = !str || strncmp(old, str, len);
637         else
638             strncpy(memb_ptr, str, sz);
639         break;
640     default:
641         return gripe("field %d doesn't take strings", fldno + 1);
642     }
643
644     if (mismatch) {
645         if (old)
646             return gripe("value for field %d must be \"%.*s\"",
647                          fldno + 1, (int)len, old);
648         else
649             return gripe("value for field %d must be nil", fldno + 1);
650     }
651
652     return 0;
653 }
654
655 /*
656  * Save the current row's fields in its object.
657  * Return 0 on success, -1 on failure.
658  */
659 static int
660 putrow(void)
661 {
662     int i, ret = 0;
663     void *obj;
664
665     obj = rowobj();
666     if (!obj)
667         return -1;
668
669     for (i = 0; i < nflds; i++) {
670         switch (fldval[i].val_type) {
671         case NSC_DOUBLE:
672             ret |= putnum(obj, i, fldval[i].val_as.dbl);
673             break;
674         case NSC_STRING:
675             ret |= putstr(obj, i, fldval[i].val_as.str.base);
676             free(fldval[i].val_as.str.base);
677             break;
678         default:
679             CANT_REACH();
680             ret = -1;
681         }
682     }
683
684     return ret;
685 }
686
687 /*
688  * Read and ignore field separators from FP.
689  * Return first character that is not a field separator.
690  */
691 static int
692 skipfs(FILE *fp)
693 {
694     int ch;
695
696     do {
697         ch = getc(fp);
698     } while (ch == ' ' || ch == '\t');
699
700     if (ch == '#') {
701         do {
702             ch = getc(fp);
703         } while (ch != EOF && ch != '\n');
704     }
705
706     return ch;
707 }
708
709 /*
710  * Decode escape sequences in BUF.
711  * Return BUF on success, null pointer on failure.
712  */
713 static char *
714 xuesc(char *buf)
715 {
716     char *src, *dst;
717     unsigned octal_chr;
718     int n;
719
720     dst = buf;
721     src = buf;
722     while (*src) {
723         if (*src == '\\') {
724             if (sscanf(++src, "%3o%n", &octal_chr, &n) != 1 || n != 3)
725                 return NULL;
726             *dst++ = (char)octal_chr;
727             src += 3;
728         } else
729             *dst++ = *src++;
730     }
731     *dst = '\0';
732     return buf;
733 }
734
735 /*
736  * Read an identifier from FP into BUF.
737  * BUF must have space for 1024 characters.
738  * Return number of characters read on success, -1 on failure.
739  */
740 static int
741 getid(FILE *fp, char *buf)
742 {
743     int n;
744     if (fscanf(fp, "%1023[^\"#()<>= \t\n]%n", buf, &n) != 1
745         || !isalpha(buf[0]))
746         return -1;
747     xuesc(buf);
748     return n;
749 }
750
751 /*
752  * Try to read a field name from FP.
753  * I is the field number, counting from zero.
754  * If a name is read, set fldca[I] and fldidx[I] for it, and update
755  * caflds[].
756  * Return 1 if a name or ... was read, 0 on end of line, -1 on error.
757  */
758 static int
759 xufldname(FILE *fp, int i)
760 {
761     int ch, idx;
762     char buf[1024];
763
764     ch = skipfs(fp);
765     switch (ch) {
766     case EOF:
767         return gripe("unexpected EOF");
768     case '\n':
769         nflds = i - (ellipsis != 0);
770         if (chkflds() < 0)
771             return -1;
772         lineno++;
773         return 0;
774     case '.':
775         if (getc(fp) != '.' || getc(fp) != '.')
776             return gripe("junk in header field %d", i + 1);
777         if (i == 0)
778             return gripe("header fields expected");
779         ellipsis = 1;
780         ch = skipfs(fp);
781         if (ch != EOF && ch != '\n')
782             return gripe("junk after ...");
783         ungetc(ch, fp);
784         return 1;
785     default:
786         ungetc(ch, fp);
787         if (getid(fp, buf) < 0)
788             return gripe("junk in header field %d", i + 1);
789         ch = getc(fp);
790         if (ch != '(') {
791             ungetc(ch, fp);
792             return deffld(i, buf, -1);
793         }
794         ch = getc(fp);
795         ungetc(ch, fp);
796         if (isdigit(ch) || ch == '-' || ch == '+') {
797             if (fscanf(fp, "%d", &idx) != 1)
798                 return gripe("malformed number in index of header field %d",
799                              i + 1);
800             if (idx < 0)
801                 return gripe("index must not be negative in header field %d",
802                              i + 1);
803         } else {
804             if (getid(fp, buf) < 0)
805                 return gripe("malformed index in header field %d", i + 1);
806             return gripe("symbolic index in header field %d not yet implemented",
807                          i + 1);
808         }
809         ch = getc(fp);
810         if (ch != ')')
811             return gripe("malformed index in header field %d", i + 1);
812         return deffld(i, buf, idx);
813     }
814 }
815
816 /*
817  * Try to read a field value from FP.
818  * I is the field number, counting from zero.
819  * Return 1 if a value was read, 0 on end of line, -1 on error.
820  */
821 static int
822 xufld(FILE *fp, int i)
823 {
824     int ch, j;
825     char buf[1024];
826     double dbl;
827     long set;
828
829     ch = skipfs(fp);
830     switch (ch) {
831     case EOF:
832         return gripe("unexpected EOF");
833     case '\n':
834         CANT_HAPPEN(i > nflds);
835         for (j = i; j < nflds; j++) {
836             if (CA_IS_ARRAY(fldca[j]))
837                 gripe("field '%s(%d)' missing",
838                       fldca[j]->ca_name, fldidx[j]);
839             else
840                 gripe("field '%s' missing", fldca[j]->ca_name);
841         }
842         if (i != nflds || putrow() < 0)
843             return -1;
844         lineno++;
845         return i < nflds ? -1 : 0;
846     case '+': case '-': case '.':
847     case '0': case '1': case '2': case '3': case '4':
848     case '5': case '6': case '7': case '8': case '9':
849         ungetc(ch, fp);
850         if (fscanf(fp, "%lg", &dbl) != 1)
851             return gripe("malformed number in field %d", i + 1);
852         return setnum(i, dbl);
853     case '"':
854         ch = getc(fp);
855         if (ch == '"')
856             buf[0] = 0;
857         else {
858             ungetc(ch, fp);
859             if (fscanf(fp, "%1023[^\"\n]", buf) != 1 || getc(fp) != '"')
860                 return gripe("malformed string in field %d", i + 1);
861             if (!xuesc(buf))
862                 return gripe("invalid escape sequence in field %d",
863                              i + 1);
864         }
865         return setstr(i, buf);
866     case '(':
867         if (mtsymset(i, &set) < 0)
868             return -1;
869         for (;;) {
870             ch = skipfs(fp);
871             if (ch == EOF || ch == '\n')
872                 return gripe("unmatched '(' in field %d", i + 1);
873             if (ch == ')')
874                 break;
875             ungetc(ch, fp);
876             if (getid(fp, buf) < 0)
877                 return gripe("junk in field %d", i + 1);
878             if (add2symset(i, &set, buf) < 0)
879                 return -1;
880         }
881         return setnum(i, set);
882     default:
883         ungetc(ch, fp);
884         if (getid(fp, buf) < 0)
885             return gripe("junk in field %d", i + 1);
886         if (!strcmp(buf, "nil"))
887             return setstr(i, NULL);
888         else
889             return setsym(i, buf);
890     }
891 }
892
893 /*
894  * Read fields from FP.
895  * Use PARSE() to read each field.
896  * Return number of fields read on success, -1 on error.
897  */
898 static int
899 xuflds(FILE *fp, int (*parse)(FILE *, int))
900 {
901     int i, ch, res;
902
903     for (i = 0; ; i++) {
904         res = parse(fp, i);
905         if (res < 0)
906             return -1;
907         if (res == 0)
908             return i;
909         ch = getc(fp);
910         if (ch == '\n')
911             ungetc(ch, fp);
912         else if (ch != ' ' && ch != '\t')
913             return gripe("bad field separator after field %d", i + 1);
914     }
915 }
916
917 /*
918  * Define the FLDNO-th field.
919  * If IDX is negative, define as selector NAME, else as NAME(IDX).
920  * Set fldca[FLDNO] and fldidx[FLDNO] accordingly.
921  * Update caflds[].
922  * Return 1 on success, -1 on error.
923  */
924 static int
925 deffld(int fldno, char *name, int idx)
926 {
927     struct castr *ca = ef_cadef(cur_type);
928     int res;
929
930     res = stmtch(name, ca, offsetof(struct castr, ca_name),
931                  sizeof(struct castr));
932     if (res < 0)
933         return gripe("%s header '%s' in field %d",
934                      res == M_NOTUNIQUE ? "ambiguous" : "unknown",
935                      name, fldno + 1);
936     if ((ca[res].ca_flags & NSC_EXTRA) || CANT_HAPPEN(ca[res].ca_get))
937         return gripe("extraneous header '%s' in field %d", name, fldno + 1);
938     if (CA_IS_ARRAY(&ca[res])) {
939         if (idx < 0)
940             return gripe("header '%s' requires an index in field %d",
941                          ca[res].ca_name, fldno + 1);
942         if (idx != caflds[res] && idx < ca[res].ca_len)
943             return gripe("expected header '%s(%d)' in field %d",
944                          ca[res].ca_name, caflds[res], fldno + 1);
945         if (idx >= ca[res].ca_len)
946             return gripe("unexpected header '%s(%d)' in field %d",
947                          ca[res].ca_name, idx, fldno + 1);
948     } else {
949         if (idx >= 0)
950             return gripe("header '%s' doesn't take an index in field %d",
951                          ca[res].ca_name, fldno + 1);
952         idx = 0;
953         if (caflds[res])
954             return gripe("duplicate header '%s' in field %d",
955                          ca[res].ca_name, fldno + 1);
956     }
957     fldca[fldno] = &ca[res];
958     fldidx[fldno] = idx;
959     caflds[res]++;
960     return 1;
961 }
962
963 /*
964  * Check fields in xdump are sane.
965  * Return 0 on success, -1 on error.
966  */
967 static int
968 chkflds(void)
969 {
970     struct castr *ca = ef_cadef(cur_type);
971     int i, len, cafldsmax, res = 0;
972
973     if (ellipsis)
974         return res;             /* table is split, another part expected */
975
976     /* Check for missing fields */
977     for (i = 0; ca[i].ca_name; i++) {
978         cafldsmax = MAX(caflds[i], cafldspp[i]);
979         if (ca[i].ca_flags & NSC_EXTRA)
980             continue;
981         len = CA_ARRAY_LEN(&ca[i]);
982         if (!len && !cafldsmax)
983             res = gripe("header '%s' missing", ca[i].ca_name);
984         else if (len && cafldsmax == len - 1)
985             res = gripe("header '%s(%d)' missing",
986                         ca[i].ca_name, len - 1);
987         else if (len && cafldsmax < len - 1)
988             res = gripe("header '%s(%d)' ... '%s(%d)' missing",
989                         ca[i].ca_name, cafldsmax, ca[i].ca_name, len - 1);
990     }
991
992     return res;
993 }
994
995 /*
996  * Set value of field FLDNO in current row to DBL.
997  * Return 1 on success, -1 on error.
998  */
999 static int
1000 setnum(int fldno, double dbl)
1001 {
1002     if (!getfld(fldno, NULL))
1003         return -1;
1004     fldval[fldno].val_cat = NSC_VAL;
1005     fldval[fldno].val_type = NSC_DOUBLE;
1006     fldval[fldno].val_as.dbl = dbl;
1007     return 1;
1008 }
1009
1010 /*
1011  * Set value of field FLDNO in current row to STR.
1012  * Return 1 on success, -1 on error.
1013  */
1014 static int
1015 setstr(int fldno, char *str)
1016 {
1017     if (!getfld(fldno, NULL))
1018         return -1;
1019     fldval[fldno].val_cat = NSC_VAL;
1020     fldval[fldno].val_type = NSC_STRING;
1021     fldval[fldno].val_as.str.base = str ? strdup(str) : NULL;
1022     fldval[fldno].val_as.str.maxsz = INT_MAX;
1023                                 /* really SIZE_MAX, but that's C99 */
1024     return 1;
1025 }
1026
1027 /*
1028  * Resolve symbol name ID in table referred to by CA.
1029  * Use field number N for error messages.
1030  * Return index in referred table on success, -1 on failure.
1031  */
1032 static int
1033 xunsymbol(char *id, struct castr *ca, int n)
1034 {
1035     int i = ef_elt_byname(ca->ca_table, id);
1036     if (i < 0)
1037         return gripe("%s %s symbol '%s' in field %d",
1038                      i == M_NOTUNIQUE ? "ambiguous" : "unknown",
1039                      ca->ca_name, id, n + 1);
1040     return i;
1041 }
1042
1043 /*
1044  * Map symbol index to symbol value.
1045  * CA is the table, and I is the index in it.
1046  */
1047 static int
1048 symval(struct castr *ca, int i)
1049 {
1050     int type = ca->ca_table;
1051
1052     if (type != EF_BAD && ef_cadef(type) == symbol_ca)
1053         /* symbol table, value is in the table */
1054         return ((struct symbol *)ef_ptr(type, i))->value;
1055     /* value is the table index */
1056     return i;
1057 }
1058
1059 /*
1060  * Set value of field FLDNO in current object to value of symbol SYM.
1061  * Return 1 on success, -1 on error.
1062  */
1063 static int
1064 setsym(int fldno, char *sym)
1065 {
1066     struct castr *ca;
1067     int i;
1068
1069     ca = getfld(fldno, NULL);
1070     if (!ca)
1071         return -1;
1072
1073     if (ca->ca_table == EF_BAD || (ca->ca_flags & NSC_BITS))
1074         return gripe("field %d doesn't take symbols", fldno + 1);
1075
1076     i = xunsymbol(sym, ca, fldno);
1077     if (i < 0)
1078         return -1;
1079     return setnum(fldno, symval(ca, i));
1080 }
1081
1082 /*
1083  * Create an empty symbol set for field FLDNO in *SET.
1084  * Return 1 on success, -1 on error.
1085  */
1086 static int
1087 mtsymset(int fldno, long *set)
1088 {
1089     struct castr *ca;
1090
1091     ca = getfld(fldno, NULL);
1092     if (!ca)
1093         return -1;
1094
1095     if (ca->ca_table == EF_BAD || ef_cadef(ca->ca_table) != symbol_ca
1096         || !(ca->ca_flags & NSC_BITS))
1097         return gripe("field %d doesn't take symbol sets", fldno + 1);
1098     *set = 0;
1099     return 0;
1100 }
1101
1102 /*
1103  * Add a symbol to a symbol set for field FLDNO in *SET.
1104  * SYM is the name of the symbol to add.
1105  * Return 1 on success, -1 on error.
1106  */
1107 static int
1108 add2symset(int fldno, long *set, char *sym)
1109 {
1110     struct castr *ca;
1111     int i;
1112
1113     ca = getfld(fldno, NULL);
1114     if (!ca)
1115         return -1;
1116
1117     i = xunsymbol(sym, ca, fldno);
1118     if (i < 0)
1119         return -1;
1120     *set |= symval(ca, i);
1121     return 0;
1122 }
1123
1124 /*
1125  * Read an xdump table header line from FP.
1126  * Expect header for EXPECTED_TABLE, unless it is EF_BAD.
1127  * Recognize header for machine- and human-readable syntax, and set
1128  * human accordingly.
1129  * Return table type on success, -2 on EOF before header, -1 on failure.
1130  */
1131 static int
1132 xuheader(FILE *fp, int expected_table)
1133 {
1134     char name[64];
1135     int res, ch;
1136     int type;
1137
1138     while ((ch = skipfs(fp)) == '\n')
1139         lineno++;
1140     if (ch == EOF && expected_table == EF_BAD)
1141         return -2;
1142     ungetc(ch, fp);
1143
1144     human = ch == 'c';
1145     res = -1;
1146     if ((human
1147          ? fscanf(fp, "config%*[ \t]%63[^ \t#\n]%n", name, &res) != 1
1148          : fscanf(fp, "XDUMP%*[ \t]%63[^ \t#\n]%*[ \t]%*[^ \t#\n]%n",
1149                   name, &res) != 1) || res < 0)
1150         return gripe("expected xdump header");
1151
1152     type = ef_byname(name);
1153     if (type < 0)
1154         return gripe("unknown table '%s'", name);
1155     if (expected_table != EF_BAD && expected_table != type)
1156         return gripe("expected table '%s', not '%s'",
1157                      ef_nameof(expected_table), name);
1158
1159     if (!empfile[type].file
1160         || !ef_cadef(type) || !(ef_flags(type) & EFF_MEM)) {
1161         CANT_HAPPEN(expected_table != EF_BAD);
1162         return gripe("table '%s' is not permitted here", name);
1163     }
1164
1165     if (skipfs(fp) != '\n')
1166         return gripe("junk after xdump header");
1167     lineno++;
1168
1169     return type;
1170 }
1171
1172 /*
1173  * Find fields in this xdump.
1174  * If reading human-readable syntax, read a field header line from FP.
1175  * Else take fields from the table's selectors in CA[].
1176  * Set ellipsis, nflds, fldca[], fldidx[] and caflds[] accordingly.
1177  * Return 0 on success, -1 on failure.
1178  */
1179 static int
1180 xufldhdr(FILE *fp, struct castr ca[])
1181 {
1182     struct castr **fca;
1183     int *fidx;
1184     int ch, i, j, n;
1185
1186     for (i = 0; ca[i].ca_name; i++)
1187         caflds[i] = 0;
1188     ellipsis = 0;
1189
1190     if (human) {
1191         while ((ch = skipfs(fp)) == '\n')
1192             lineno++;
1193         ungetc(ch, fp);
1194         if (xuflds(fp, xufldname) < 0)
1195             return -1;
1196     } else {
1197         fca = fldca;
1198         fidx = fldidx;
1199
1200         for (i = 0; ca[i].ca_name; i++) {
1201             if ((ca[i].ca_flags & NSC_EXTRA))
1202                 continue;
1203             n = CA_ARRAY_LEN(&ca[i]);
1204             j = 0;
1205             do {
1206                 *fca++ = &ca[i];
1207                 *fidx++ = j;
1208             } while (++j < n);
1209         }
1210
1211         nflds = fidx - fldidx;
1212     }
1213
1214     return 0;
1215 }
1216
1217 /*
1218  * Read xdump footer from FP.
1219  * CA[] contains the table's selectors.
1220  * The body had RECS records.
1221  * Update cafldspp[] from caflds[].
1222  * Return 0 on success, -1 on failure.
1223  */
1224 static int
1225 xufooter(FILE *fp, struct castr ca[], int recs)
1226 {
1227     int res, n, i;
1228
1229     res = -1;
1230     if (human) {
1231         if (fscanf(fp, "config%n", &res) != 0 || res < 0)
1232             return gripe("malformed table footer");
1233     } else {
1234         if (fscanf(fp, "%d", &n) != 1)
1235             return gripe("malformed table footer");
1236         if (recs != n)
1237             return gripe("expected footer /%d", recs);
1238     }
1239     if (skipfs(fp) != '\n')
1240         return gripe("junk after table footer");
1241     if (tbl_part_done() < 0)
1242         return -1;
1243     lineno++;
1244
1245     for (i = 0; ca[i].ca_name; i++) {
1246         if (cafldspp[i] < caflds[i])
1247             cafldspp[i] = caflds[i];
1248     }
1249
1250     return 0;
1251 }
1252
1253 /*
1254  * Read an xdump table from FP.
1255  * Both machine- and human-readable xdump syntax are recognized.
1256  * Expect table EXPECTED_TABLE, unless it is EF_BAD.
1257  * Report errors to stderr.
1258  * Messages assume FP starts in the file FILE at line *PLNO.
1259  * Update *PLNO to reflect lines read from FP.
1260  * Return table type on success, -2 on EOF before header, -1 on failure.
1261  */
1262 int
1263 xundump(FILE *fp, char *file, int *plno, int expected_table)
1264 {
1265     struct castr *ca;
1266     int type, nca, nf, i, ch;
1267
1268     fname = file;
1269     lineno = *plno;
1270
1271     if ((type = xuheader(fp, expected_table)) < 0)
1272         return type;
1273
1274     ca = ef_cadef(type);
1275     if (CANT_HAPPEN(!ca))
1276         return -1;
1277
1278     nca = nf = 0;
1279     for (i = 0; ca[i].ca_name; i++) {
1280         nca++;
1281         if (!(ca[i].ca_flags & NSC_EXTRA))
1282             nf += MAX(1, CA_ARRAY_LEN(&ca[i]));
1283     }
1284     fldca = malloc(nf * sizeof(*fldca));
1285     fldidx = malloc(nf * sizeof(*fldidx));
1286     fldval = malloc(nf * sizeof(*fldval));
1287     caflds = malloc(nca * sizeof(*caflds));
1288     cafldspp = calloc(nca, sizeof(*cafldspp));
1289
1290     tbl_start(type);
1291     if (xutail(fp, ca) < 0)
1292         type = EF_BAD;
1293     tbl_end();
1294
1295     free(cafldspp);
1296     free(caflds);
1297     free(fldval);
1298     free(fldidx);
1299     free(fldca);
1300
1301     /* Skip empty lines so that callers can easily check for EOF */
1302     while ((ch = skipfs(fp)) == '\n')
1303         lineno++;
1304     ungetc(ch, fp);
1305
1306     *plno = lineno;
1307     return type;
1308 }
1309
1310 /*
1311  * Read the remainder of an xdump after the table header line from FP.
1312  * CA[] contains the table's selectors.
1313  * Return 0 on success, -1 on failure.
1314  */
1315 static int
1316 xutail(FILE *fp, struct castr *ca)
1317 {
1318     int recs;
1319
1320     for (;;) {
1321         if (xufldhdr(fp, ca) < 0)
1322             return -1;
1323         if ((recs = xubody(fp)) < 0)
1324             return -1;
1325         if (xufooter(fp, ca, recs) < 0)
1326             return -1;
1327         if (!ellipsis)
1328             return 0;
1329         if (xuheader(fp, cur_type) < 0)
1330             return -1;
1331     }
1332 }
1333
1334 /*
1335  * Read the body of an xdump table from FP.
1336  * Return number of rows read on success, -1 on failure.
1337  */
1338 static int
1339 xubody(FILE *fp)
1340 {
1341     int i, ch;
1342
1343     for (i = 0;; ++i) {
1344         while ((ch = skipfs(fp)) == '\n')
1345             lineno++;
1346         if (ch == '/')
1347             break;
1348         ungetc(ch, fp);
1349         if (xuflds(fp, xufld) < 0)
1350             return -1;
1351     }
1352     return i;
1353 }