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