Support vertically split configuration tables (human-readable only):
(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.
This commit is contained in:
parent
46fcc27c6f
commit
fc676cb53a
1 changed files with 87 additions and 9 deletions
|
@ -53,6 +53,7 @@
|
||||||
static char *fname;
|
static char *fname;
|
||||||
static int lineno;
|
static int lineno;
|
||||||
static int human;
|
static int human;
|
||||||
|
static int ellipsis;
|
||||||
static int cur_type, cur_id;
|
static int cur_type, cur_id;
|
||||||
static void *cur_obj;
|
static void *cur_obj;
|
||||||
static int nflds;
|
static int nflds;
|
||||||
|
@ -62,6 +63,8 @@ static int *caflds;
|
||||||
|
|
||||||
static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
|
static int gripe(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
|
||||||
static int deffld(int, char *, int);
|
static int deffld(int, char *, int);
|
||||||
|
static int defellipsis(int fldno);
|
||||||
|
static int chkflds(void);
|
||||||
static int setnum(int, double);
|
static int setnum(int, double);
|
||||||
static int setstr(int, char *);
|
static int setstr(int, char *);
|
||||||
static int xunsymbol1(char *, struct symbol *, struct castr *, int);
|
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 int add2symset(int, long *, char *);
|
||||||
static struct symbol *get_symtab(struct castr *);
|
static struct symbol *get_symtab(struct castr *);
|
||||||
static int xundump1(FILE *, int, struct castr *);
|
static int xundump1(FILE *, int, struct castr *);
|
||||||
|
static int xundump2(FILE *, int, struct castr *);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gripe(char *fmt, ...)
|
gripe(char *fmt, ...)
|
||||||
|
@ -144,10 +148,22 @@ xufldname(FILE *fp, int i)
|
||||||
case EOF:
|
case EOF:
|
||||||
return gripe("Unexpected EOF");
|
return gripe("Unexpected EOF");
|
||||||
case '\n':
|
case '\n':
|
||||||
if (i != nflds)
|
if (chkflds() < 0)
|
||||||
return gripe("Header fields missing"); /* TODO which? */
|
return -1;
|
||||||
lineno++;
|
lineno++;
|
||||||
return 0;
|
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:
|
default:
|
||||||
ungetc(ch, fp);
|
ungetc(ch, fp);
|
||||||
if (getid(fp, buf) < 0)
|
if (getid(fp, buf) < 0)
|
||||||
|
@ -301,6 +317,46 @@ deffld(int fldno, char *name, int idx)
|
||||||
return 1;
|
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 *
|
static struct castr *
|
||||||
getfld(int fldno, int *idx)
|
getfld(int fldno, int *idx)
|
||||||
{
|
{
|
||||||
|
@ -602,11 +658,16 @@ xuheader1(FILE *fp, int type, struct castr ca[])
|
||||||
int ch, i, j, n;
|
int ch, i, j, n;
|
||||||
|
|
||||||
if (human) {
|
if (human) {
|
||||||
|
/* Allow repetition of the index field in continued table: */
|
||||||
|
caflds[0] = 0;
|
||||||
while ((ch = skipfs(fp)) == '\n')
|
while ((ch = skipfs(fp)) == '\n')
|
||||||
lineno++;
|
lineno++;
|
||||||
ungetc(ch, fp);
|
ungetc(ch, fp);
|
||||||
if (xuflds(fp, xufldname) < 0)
|
ellipsis = 0;
|
||||||
|
nflds = xuflds(fp, xufldname);
|
||||||
|
if (nflds < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
nflds -= ellipsis != 0;
|
||||||
} else {
|
} else {
|
||||||
fca = fldca;
|
fca = fldca;
|
||||||
fidx = fldidx;
|
fidx = fldidx;
|
||||||
|
@ -621,6 +682,8 @@ xuheader1(FILE *fp, int type, struct castr ca[])
|
||||||
*fidx++ = j;
|
*fidx++ = j;
|
||||||
} while (++j < n);
|
} while (++j < n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nflds = fidx - fldidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -653,7 +716,7 @@ int
|
||||||
xundump(FILE *fp, char *file, int expected_table)
|
xundump(FILE *fp, char *file, int expected_table)
|
||||||
{
|
{
|
||||||
struct castr *ca;
|
struct castr *ca;
|
||||||
int type, nca, i, ch;
|
int type, nca, nf, i, ch;
|
||||||
|
|
||||||
if (fname != file) {
|
if (fname != file) {
|
||||||
fname = file;
|
fname = file;
|
||||||
|
@ -667,18 +730,18 @@ xundump(FILE *fp, char *file, int expected_table)
|
||||||
if (CANT_HAPPEN(!ca))
|
if (CANT_HAPPEN(!ca))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
nca = nflds = 0;
|
nca = nf = 0;
|
||||||
for (i = 0; ca[i].ca_name; i++) {
|
for (i = 0; ca[i].ca_name; i++) {
|
||||||
nca++;
|
nca++;
|
||||||
if (!(ca[i].ca_flags & NSC_EXTRA))
|
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));
|
fldca = calloc(nf, sizeof(*fldca));
|
||||||
fldidx = calloc(nflds, sizeof(*fldidx));
|
fldidx = calloc(nf, sizeof(*fldidx));
|
||||||
caflds = calloc(nca, sizeof(*caflds));
|
caflds = calloc(nca, sizeof(*caflds));
|
||||||
cur_type = type;
|
cur_type = type;
|
||||||
|
|
||||||
if (xuheader1(fp, type, ca) < 0 || xundump1(fp, type, ca) < 0)
|
if (xundump2(fp, type, ca) < 0)
|
||||||
type = EF_BAD;
|
type = EF_BAD;
|
||||||
|
|
||||||
free(caflds);
|
free(caflds);
|
||||||
|
@ -693,6 +756,21 @@ xundump(FILE *fp, char *file, int expected_table)
|
||||||
return type;
|
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
|
static int
|
||||||
xundump1(FILE *fp, int type, struct castr *ca)
|
xundump1(FILE *fp, int type, struct castr *ca)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue