]> git.pond.sub.org Git - empserver/commitdiff
Support vertically split configuration tables (human-readable only):
authorMarkus Armbruster <armbru@pond.sub.org>
Tue, 14 Feb 2006 07:30:06 +0000 (07:30 +0000)
committerMarkus Armbruster <armbru@pond.sub.org>
Tue, 14 Feb 2006 07:30:06 +0000 (07:30 +0000)
(ellipsis): New.
(xuheader1): Initialize it.  Compute nflds.  Allow repetition of index
field in continued tables.
(xundump): Don't set nflds.
(xufldname, defellipsis): Accept ... and call new defellipsis().
(xufldname, chkflds): Update and elaborate check for missing fields,
move it to new chkflds().  Require repetition of index field in
continued tables.
(xundump2): New, factored out of xundump().  Parse continued tables.

src/lib/common/xundump.c

index c0edf93ea4619ec7198329aa0f100c23ac94d6af..6ee1b5196c70636c64dd3dae6b23d766e4e59c4e 100644 (file)
@@ -53,6 +53,7 @@
 static char *fname;
 static int lineno;
 static int human;
+static int ellipsis;
 static int cur_type, cur_id;
 static void *cur_obj;
 static int nflds;
@@ -62,6 +63,8 @@ static int *caflds;
 
 static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
 static int deffld(int, char *, int);
+static int defellipsis(int fldno);
+static int chkflds(void);
 static int setnum(int, double);
 static int setstr(int, char *);
 static int xunsymbol1(char *, struct symbol *, struct castr *, int);
@@ -70,6 +73,7 @@ static int mtsymset(int, long *);
 static int add2symset(int, long *, char *);
 static struct symbol *get_symtab(struct castr *);
 static int xundump1(FILE *, int, struct castr *);
+static int xundump2(FILE *, int, struct castr *);
 
 static int
 gripe(char *fmt, ...)
@@ -144,10 +148,22 @@ xufldname(FILE *fp, int i)
     case EOF:
        return gripe("Unexpected EOF");
     case '\n':
-       if (i != nflds)
-           return gripe("Header fields missing"); /* TODO which? */
+       if (chkflds() < 0)
+           return -1;
        lineno++;
        return 0;
+    case '.':
+       if (getc(fp) != '.' || getc(fp) != '.')
+           return gripe("Junk in header field %d", i + 1);
+       if (i == 0)
+           return gripe("... not allowed in field 1");
+       if (defellipsis(i) < 0)
+           return -1;
+       ch = skipfs(fp);
+       if (ch != EOF && ch != '\n')
+           return gripe("Junk after ...");
+       ungetc(ch, fp);
+       return 1;
     default:
        ungetc(ch, fp);
        if (getid(fp, buf) < 0)
@@ -301,6 +317,46 @@ deffld(int fldno, char *name, int idx)
     return 1;
 }
 
+static int
+defellipsis(int fldno)
+{
+    struct castr *ca = ef_cadef(cur_type);
+
+    if (ca[0].ca_table != cur_type)
+       return gripe("Table %s doesn't support ...", ef_nameof(cur_type));
+    ellipsis = fldno;
+    return 0;
+}
+
+static int
+chkflds(void)
+{
+    struct castr *ca = ef_cadef(cur_type);
+    int i, len, res = 0;
+
+    if (ellipsis) {
+       if (!caflds[0])
+           return gripe("Header field %s required with ...", ca[0].ca_name);
+       return 0;
+    }
+
+    for (i = 0; ca[i].ca_name; i++) {
+       if (ca[i].ca_flags & NSC_EXTRA)
+           continue;
+       len = ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0;
+       if (!len && !caflds[i])
+           res = gripe("Header field %s missing", ca[i].ca_name);
+       else if (len && caflds[i] == len - 1)
+           res = gripe("Header field %s(%d) missing",
+                       ca[i].ca_name, len - 1);
+       else if (len && caflds[i] < len - 1)
+           res = gripe("Header fields %s(%d) ... %s(%d) missing",
+                       ca[i].ca_name, caflds[i], ca[i].ca_name, len - 1);
+    }
+
+    return res;
+}
+
 static struct castr *
 getfld(int fldno, int *idx)
 {
@@ -602,11 +658,16 @@ xuheader1(FILE *fp, int type, struct castr ca[])
     int ch, i, j, n;
 
     if (human) {
+       /* Allow repetition of the index field in continued table: */
+       caflds[0] = 0;
        while ((ch = skipfs(fp)) == '\n')
            lineno++;
        ungetc(ch, fp);
-       if (xuflds(fp, xufldname) < 0)
+       ellipsis = 0;
+       nflds = xuflds(fp, xufldname);
+       if (nflds < 0)
            return -1;
+       nflds -= ellipsis != 0;
     } else {
        fca = fldca;
        fidx = fldidx;
@@ -621,6 +682,8 @@ xuheader1(FILE *fp, int type, struct castr ca[])
                *fidx++ = j;
            } while (++j < n);
        }
+
+       nflds = fidx - fldidx;
     }
 
     return 0;
@@ -653,7 +716,7 @@ int
 xundump(FILE *fp, char *file, int expected_table)
 {
     struct castr *ca;
-    int type, nca, i, ch;
+    int type, nca, nf, i, ch;
 
     if (fname != file) {
         fname = file;
@@ -667,18 +730,18 @@ xundump(FILE *fp, char *file, int expected_table)
     if (CANT_HAPPEN(!ca))
        return -1;
 
-    nca = nflds = 0;
+    nca = nf = 0;
     for (i = 0; ca[i].ca_name; i++) {
        nca++;
        if (!(ca[i].ca_flags & NSC_EXTRA))
-           nflds += MAX(1, ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0);
+           nf += MAX(1, ca[i].ca_type != NSC_STRINGY ? ca[i].ca_len : 0);
     }
-    fldca = calloc(nflds, sizeof(*fldca));
-    fldidx = calloc(nflds, sizeof(*fldidx));
+    fldca = calloc(nf, sizeof(*fldca));
+    fldidx = calloc(nf, sizeof(*fldidx));
     caflds = calloc(nca, sizeof(*caflds));
     cur_type = type;
 
-    if (xuheader1(fp, type, ca) < 0 || xundump1(fp, type, ca) < 0)
+    if (xundump2(fp, type, ca) < 0)
        type = EF_BAD;
 
     free(caflds);
@@ -693,6 +756,21 @@ xundump(FILE *fp, char *file, int expected_table)
     return type;
 }
 
+static int
+xundump2(FILE *fp, int type, struct castr *ca)
+{
+    for (;;) {
+       if (xuheader1(fp, type, ca) < 0)
+           return -1;
+       if (xundump1(fp, type, ca) < 0)
+           return -1;
+       if (!ellipsis)
+           return 0;
+       if (xuheader(fp, type) < 0)
+           return -1;
+    }
+}
+
 static int
 xundump1(FILE *fp, int type, struct castr *ca)
 {