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