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