2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See files README, COPYING and CREDITS in the root of the source
23 * tree for related information and legal notices. It is expected
24 * that future projects/authors will amend these files as needed.
28 * xundump.c: Load back xdump output
30 * Known contributors to this file:
31 * Ron Koenderink, 2005
32 * Markus Armbruster, 2005
35 /* FIXME normalize terminology: table/rows/columns or file/records/fields */
51 #include "prototypes.h"
58 static int nxt_sel, nxt_idx;
60 static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
61 static int deffld(int, char *, int);
62 static void nxtfld(void);
63 static int setnum(int, double);
64 static int setstr(int, char *);
65 static int xunsymbol1(char *, struct symbol *, struct castr *, int);
66 static int setsym(int, char *);
67 static int mtsymset(int, long *);
68 static int add2symset(int, long *, char *);
69 static struct symbol *get_symtab(struct castr *);
76 fprintf(stderr, "%s:%d: ", fname, lineno);
78 vfprintf(stderr, fmt, ap);
92 } while (ch == ' ' || ch == '\t');
97 } while (ch != EOF && ch != '\n');
104 getid(FILE *fp, char *buf)
107 if (fscanf(fp, "%1023[^#() \t\n]%n", buf, &n) != 1 || !isalpha(buf[0]))
122 if (sscanf(++src, "%3o%n", &octal_chr, &n) != 1 || n != 3)
124 *dst++ = (char)octal_chr;
134 xufldname(FILE *fp, int i)
142 return gripe("Unexpected EOF");
145 return gripe("Fields missing");
150 if (getid(fp, buf) < 0)
151 return gripe("Junk in field %d", i + 1);
155 return deffld(i, buf, -1);
159 if (isdigit(ch) || ch == '-' || ch == '+') {
160 if (fscanf(fp, "%d", &idx) != 1) {
161 return gripe("Malformed number in index field %d", i + 1);
164 if (getid(fp, buf) < 0)
165 return gripe("Malformed string in index field %d", i + 1);
166 return gripe("Symbolic index in field %d not yet implemented",
171 return gripe("Malformed index field %d", i + 1);
172 return deffld(i, buf, idx);
177 xufld(FILE *fp, int i)
187 return gripe("Unexpected EOF");
190 return gripe("Fields missing");
193 case '+': case '-': case '.':
194 case '0': case '1': case '2': case '3': case '4':
195 case '5': case '6': case '7': case '8': case '9':
197 if (fscanf(fp, "%lg", &dbl) != 1)
198 return gripe("Malformed number in field %d", i + 1);
199 return setnum(i, dbl);
206 if (fscanf(fp, "%1023[^\"\n]", buf) != 1 || getc(fp) != '"')
207 return gripe("Malformed string in field %d", i + 1);
209 return gripe("Invalid escape sequence in field %d",
212 return setstr(i, buf);
214 if (mtsymset(i, &set) < 0)
218 if (ch == EOF || ch == '\n')
219 return gripe("Unmatched '(' in field %d", i + 1);
223 if (getid(fp, buf) < 0)
224 return gripe("Junk in field %d", i + 1);
225 if (add2symset(i, &set, buf) < 0)
228 return setnum(i, set);
231 if (getid(fp, buf) < 0)
232 return gripe("Junk in field %d", i + 1);
233 if (!strcmp(buf, "nil"))
234 return setstr(i, NULL);
236 return setsym(i, buf);
241 xuflds(FILE *fp, int (*parse)(FILE *, int))
254 else if (ch != ' ' && ch != '\t')
255 return gripe("Bad field separator after field %d", i + 1);
260 deffld(int fldidx, char *name, int idx)
262 struct castr *ca = ef_cadef(cur_type);
266 return gripe("Too many fields, expected only %d", fldidx);
268 res = stmtch(name, ca, offsetof(struct castr, ca_name),
269 sizeof(struct castr));
270 if (ca[nxt_sel].ca_type != NSC_STRINGY && ca[nxt_sel].ca_len != 0) {
271 if (res != nxt_sel || idx != nxt_idx)
272 return gripe("Expected %s(%d) in field %d",
273 ca[nxt_sel].ca_name, nxt_idx, fldidx + 1);
275 if (res != nxt_sel || idx >= 0)
276 return gripe("Expected %s in field %d",
277 ca[nxt_sel].ca_name, fldidx + 1);
287 struct castr *ca = ef_cadef(cur_type);
288 unsigned len = ca[nxt_sel].ca_type == NSC_STRINGY ? 0 : ca[nxt_sel].ca_len; /* FIXME ugly */
291 if ((unsigned)nxt_idx >= len) {
295 if (!ca[nxt_sel].ca_name) {
299 if (!(ca[nxt_sel].ca_flags & NSC_EXTRA))
305 static struct castr *
308 struct castr *ca = ef_cadef(cur_type);
309 unsigned len = ca[nxt_sel].ca_type == NSC_STRINGY ? 0 : ca[nxt_sel].ca_len; /* FIXME ugly */
311 if (nxt_sel < 0 || CANT_HAPPEN(nxt_idx && (unsigned)nxt_idx >= len)) {
312 gripe("Too many fields, expected only %d", fldidx);
319 setnum(int fldidx, double dbl)
321 struct castr *ca = ca4fld(fldidx);
329 memb_ptr += ca->ca_off;
330 switch (ca->ca_type) {
333 old = ((signed char *)memb_ptr)[nxt_idx];
334 ((signed char *)memb_ptr)[nxt_idx] = (signed char)dbl;
337 old = ((unsigned char *)memb_ptr)[nxt_idx];
338 ((unsigned char *)memb_ptr)[nxt_idx] = (unsigned char)dbl;
341 old = ((short *)memb_ptr)[nxt_idx];
342 ((short *)memb_ptr)[nxt_idx] = (short)dbl;
345 old = ((unsigned short *)memb_ptr)[nxt_idx];
346 ((unsigned short *)memb_ptr)[nxt_idx] = (unsigned short)dbl;
349 old = ((int *)memb_ptr)[nxt_idx];
350 ((int *)memb_ptr)[nxt_idx] = (int)dbl;
353 old = ((long *)memb_ptr)[nxt_idx];
354 ((long *)memb_ptr)[nxt_idx] = (long)dbl;
357 old = ((coord *)memb_ptr)[nxt_idx];
358 ((coord *)memb_ptr)[nxt_idx] = XNORM((coord)dbl);
361 old = ((coord *)memb_ptr)[nxt_idx];
362 ((coord *)memb_ptr)[nxt_idx] = YNORM((coord)dbl);
365 old = ((float *)memb_ptr)[nxt_idx];
366 ((float *)memb_ptr)[nxt_idx] = (float)dbl;
369 old = ((double *)memb_ptr)[nxt_idx];
370 ((double *)memb_ptr)[nxt_idx] = dbl;
373 old = ((time_t *)memb_ptr)[nxt_idx];
374 ((time_t *)memb_ptr)[nxt_idx] = (time_t)dbl;
377 return gripe("Field %d doesn't take numbers", fldidx + 1);
380 if ((ca->ca_flags & NSC_CONST) && old != dbl)
381 return gripe("Value for field %d must be %g", fldidx + 1, old);
388 setstr(int fldidx, char *str)
390 struct castr *ca = ca4fld(fldidx);
391 char *memb_ptr, *old;
397 memb_ptr += ca->ca_off;
398 switch (ca->ca_type) {
400 old = ((char **)memb_ptr)[nxt_idx];
401 if (!(ca->ca_flags & NSC_CONST))
402 ((char **)memb_ptr)[nxt_idx] = str ? strdup(str) : NULL;
405 CANT_HAPPEN(nxt_idx);
407 return gripe("Field doesn't take nil");
408 if (strlen(str) > ca->ca_len)
409 return gripe("Field %d takes at most %d characters",
410 fldidx + 1, ca->ca_len);
412 if (!(ca->ca_flags & NSC_CONST))
413 strncpy(memb_ptr, str, ca->ca_len);
416 return gripe("Field %d doesn't take strings", fldidx + 1);
419 if ((ca->ca_flags & NSC_CONST) && strcmp(old, str))
420 return gripe("Value for field %d must be %s", fldidx + 1, old);
427 xunsymbol1(char *id, struct symbol *symtab, struct castr *ca, int n)
429 int i = stmtch(id, symtab, offsetof(struct symbol, name),
430 sizeof(struct symbol));
432 return gripe("%s %s symbol `%s' in field %d",
433 i == M_NOTUNIQUE ? "Ambiguous" : "Unknown",
439 setsym(int fldidx, char *sym)
441 struct castr *ca = ca4fld(fldidx);
442 struct symbol *symtab;
448 symtab = get_symtab(ca);
449 if (!symtab || (ca->ca_flags & NSC_BITS))
450 return gripe("Field %d doesn't take symbols", fldidx + 1);
452 i = xunsymbol1(sym, symtab, ca, fldidx);
455 return setnum(fldidx, symtab[i].value);
459 has_const(struct castr ca[])
463 for (i = 0; ca[i].ca_name; i++) {
464 if (ca[i].ca_flags & NSC_CONST)
471 mtsymset(int fldidx, long *set)
473 struct castr *ca = ca4fld(fldidx);
474 struct symbol *symtab;
480 symtab = get_symtab(ca);
481 if (!symtab || !(ca->ca_flags & NSC_BITS)) {
482 return gripe("Field %d doesn't take symbol sets", fldidx + 1);
489 add2symset(int fldidx, long *set, char *sym)
491 struct castr *ca = ca4fld(fldidx);
492 struct symbol *symtab;
498 symtab = get_symtab(ca);
499 i = xunsymbol1(sym, symtab, ca, fldidx);
502 *set |= symtab[i].value;
506 static struct symbol *
507 get_symtab(struct castr *ca)
509 int symtype = ca->ca_table;
510 struct symbol *symtab;
512 if (symtype == EF_BAD || ef_cadef(symtype) != symbol_ca)
515 symtab = ef_ptr(symtype, 0);
516 CANT_HAPPEN(!symtab);
521 xuheader(FILE *fp, int expected_table)
527 while ((ch = skipfs(fp)) == '\n')
529 if (ch == EOF && expected_table == EF_BAD)
536 ? fscanf(fp, "config%*[ \t]%63[^ \t#\n]%n", name, &res) != 1
537 : fscanf(fp, "XDUMP%*[ \t]%63[^ \t#\n]%*[ \t]%*[^ \t#\n]%n",
538 name, &res) != 1) || res < 0)
539 return gripe("Expected xdump header");
541 type = ef_byname(name);
543 return gripe("Unknown table `%s'", name);
544 if (expected_table != EF_BAD && expected_table != type)
545 return gripe("Expected table `%s', not `%s'",
546 ef_nameof(expected_table), name);
548 if (CANT_HAPPEN(!(ef_flags(type) & EFF_MEM)))
551 if (skipfs(fp) != '\n')
552 return gripe("Junk after xdump header");
559 xutrailer(FILE *fp, int type, int row)
565 if (fscanf(fp, "config%n", &res) != 0 || res < 0)
566 return gripe("Malformed table footer");
568 if (fscanf(fp, "%d", &rows) != 1)
569 return gripe("Malformed table footer");
571 return gripe("Read %d rows, which doesn't match footer "
572 "%d rows", row, rows);
574 if (skipfs(fp) != '\n')
575 return gripe("Junk after table footer");
582 xundump(FILE *fp, char *file, int expected_table)
585 int type, fixed_rows, need_sentinel;
593 if ((type = xuheader(fp, expected_table)) < 0)
597 fixed_rows = has_const(ef_cadef(type));
598 need_sentinel = !EF_IS_GAME_STATE(type);
602 nxt_sel = nxt_idx = 0;
603 if (xuflds(fp, xufldname) < 0)
607 for (row = 0;; ++row) {
612 /* TODO ability to skip records */
614 if (row >= ep->csize - !!need_sentinel)
615 /* TODO grow cache unless EFF_STATIC */
616 return gripe("Too many rows for table %s", ef_nameof(type));
619 ep->cids = ep->fids = row + 1;
621 cur_obj = ef_ptr(type, row);
623 return gripe("Too many rows for table %s", ef_nameof(type));
624 nxt_sel = nxt_idx = 0;
625 res = xuflds(fp, xufld);
629 if (row != ep->fids) {
631 return gripe("Table %s requires %d rows, got %d",
632 ef_nameof(type), ep->fids, row);
634 ep->cids = ep->fids = row;
635 if (EF_IS_GAME_STATE(type) && row != ep->csize)
636 /* TODO truncate file */
637 gripe("Warning: should resize table %s from %d to %d, not implemented",
638 ef_nameof(type), ep->csize, row);
643 if (CANT_HAPPEN(row >= ep->csize))
644 return gripe("No space for sentinel");
645 memset(ep->cache + ep->size * row, 0, ep->size);
648 if (xutrailer(fp, type, row) < 0)