Less rigid field separators, support comments:

(skipfs): New.
(xuflds, xundump): Use it.  Update field scanf stop-sets accordingly.
(xuflds): Update test for good field separator.

(xundump): Fail silently if nothing can be read and no specific table
is expected.
This commit is contained in:
Markus Armbruster 2005-12-03 11:04:44 +00:00
parent 8ca219819c
commit 0a7291eb37

View file

@ -85,6 +85,24 @@ gripe(char *fmt, ...)
return -1; return -1;
} }
static int
skipfs(FILE *fp)
{
int ch;
do {
ch = getc(fp);
} while (ch == ' ' || ch == '\t');
if (ch == '#') {
do {
ch = getc(fp);
} while (ch != EOF && ch != '\n');
}
return ch;
}
static char * static char *
xuesc(char *buf) xuesc(char *buf)
{ {
@ -117,7 +135,7 @@ xuflds(FILE *fp, struct value values[])
if (i >= MAX_NUM_COLUMNS) if (i >= MAX_NUM_COLUMNS)
return gripe("Too many columns"); return gripe("Too many columns");
ch = getc(fp); ch = skipfs(fp);
switch (ch) { switch (ch) {
case EOF: case EOF:
return gripe("Unexpected EOF"); return gripe("Unexpected EOF");
@ -132,7 +150,7 @@ xuflds(FILE *fp, struct value values[])
values[i].v_type = VAL_DOUBLE; values[i].v_type = VAL_DOUBLE;
break; break;
case '"': case '"':
if (fscanf(fp, "%1023[^ \n]", buf) != 1 if (fscanf(fp, "%1023[^ \t#\n]", buf) != 1
|| buf[strlen(buf)-1] != '"') || buf[strlen(buf)-1] != '"')
return gripe("Malformed string in field %d", i + 1); return gripe("Malformed string in field %d", i + 1);
buf[strlen(buf)-1] = '\0'; buf[strlen(buf)-1] = '\0';
@ -144,7 +162,7 @@ xuflds(FILE *fp, struct value values[])
break; break;
default: default:
ungetc(ch, fp); ungetc(ch, fp);
if (fscanf(fp, "%1023[^ \n]", buf) != 1 || !isalpha(buf[0])) { if (fscanf(fp, "%1023[^ \t#\n]", buf) != 1 || !isalpha(buf[0])) {
return gripe("Junk in field %d", i + 1); return gripe("Junk in field %d", i + 1);
} }
if (!strcmp(buf, "nil")) { if (!strcmp(buf, "nil")) {
@ -159,7 +177,7 @@ xuflds(FILE *fp, struct value values[])
ch = getc(fp); ch = getc(fp);
if (ch == '\n') if (ch == '\n')
ungetc(ch, fp); ungetc(ch, fp);
else if (ch != ' ') else if (ch != ' ' && ch != '\t')
return gripe("Bad field separator after field %d", i + 1); return gripe("Bad field separator after field %d", i + 1);
} }
} }
@ -406,7 +424,6 @@ int
xundump(FILE *fp, char *file, int expected_table) xundump(FILE *fp, char *file, int expected_table)
{ {
char name[64]; char name[64];
char sep;
struct empfile *ep; struct empfile *ep;
int row, res, rows, ch; int row, res, rows, ch;
struct value values[MAX_NUM_COLUMNS + 1]; struct value values[MAX_NUM_COLUMNS + 1];
@ -419,9 +436,15 @@ xundump(FILE *fp, char *file, int expected_table)
} else } else
lineno++; lineno++;
if (fscanf(fp, "XDUMP%*1[ ]%63[^ \n]%*1[ ]%*[^ \n]%c", name, &sep) != 2) while ((ch = skipfs(fp)) == '\n')
lineno++;
if (ch == EOF && expected_table == EF_BAD)
return -1;
ungetc(ch, fp);
if (fscanf(fp, "XDUMP%*[ \t]%63[^ \t#\n]%*[ \t]%*[^ \t#\n]", name) != 1)
return gripe("Expected XDUMP header"); return gripe("Expected XDUMP header");
if (sep != '\n') if (skipfs(fp) != '\n')
return gripe("Junk after XDUMP header"); return gripe("Junk after XDUMP header");
type = ef_byname(name); type = ef_byname(name);
@ -440,7 +463,7 @@ xundump(FILE *fp, char *file, int expected_table)
for (row = 0; ; row++) { for (row = 0; ; row++) {
lineno++; lineno++;
ch = getc(fp); ch = skipfs(fp);
if (ch == '/') if (ch == '/')
break; break;
ungetc(ch, fp); ungetc(ch, fp);
@ -466,16 +489,16 @@ xundump(FILE *fp, char *file, int expected_table)
ch = getc(fp); ch = getc(fp);
ungetc(ch, fp); ungetc(ch, fp);
if (!isdigit(ch) || fscanf(fp, "%d%c", &rows, &sep) != 2) if (!isdigit(ch) || fscanf(fp, "%d", &rows) != 1)
return gripe("Malformed table footer"); return gripe("Malformed table footer");
if (skipfs(fp) != '\n')
return gripe("Junk after table footer");
if (row != rows) if (row != rows)
return gripe("Read %d rows, which doesn't match footer", return gripe("Read %d rows, which doesn't match footer",
row); row);
if (fixed_rows && row != ep->csize -1) if (fixed_rows && row != ep->csize -1)
return gripe("Table %s requires %d rows, got %d", return gripe("Table %s requires %d rows, got %d",
name, ep->csize - 1, row); name, ep->csize - 1, row);
if (sep != '\n')
return gripe("Junk after table footer");
if (need_sentinel) if (need_sentinel)
xuinitrow(type, row); xuinitrow(type, row);