Properly parse and validate column headers:
(enum_value, value, xuflds, freeflds): Parse additional syntax: numeric and symbolic index. (xucolumnheader): Use it to parse column header line. Check names and indexes match meta-data. Symbolic indexes not yet implemented. (xuloadrow): Reject the additional syntax.
This commit is contained in:
parent
aaea73a595
commit
426eece569
1 changed files with 123 additions and 12 deletions
|
@ -61,10 +61,12 @@ static int human;
|
||||||
*/
|
*/
|
||||||
enum enum_value {
|
enum enum_value {
|
||||||
VAL_NOTUSED,
|
VAL_NOTUSED,
|
||||||
VAL_STRING,
|
VAL_STRING, /* uses v_string */
|
||||||
VAL_SYMBOL,
|
VAL_SYMBOL, /* uses v_string */
|
||||||
VAL_SYMBOL_SET,
|
VAL_SYMBOL_SET, /* uses v_string */
|
||||||
VAL_DOUBLE
|
VAL_INDEX_ID, /* uses v_index_name and v_int */
|
||||||
|
VAL_INDEX_SYMBOL, /* uses v_index_name and v_string */
|
||||||
|
VAL_DOUBLE /* uses v_double */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct value {
|
struct value {
|
||||||
|
@ -72,7 +74,9 @@ struct value {
|
||||||
union {
|
union {
|
||||||
char *v_string;
|
char *v_string;
|
||||||
double v_double;
|
double v_double;
|
||||||
|
int v_int;
|
||||||
} v_field;
|
} v_field;
|
||||||
|
char *v_index_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int gripe(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2)));
|
static int gripe(char *fmt, ...) ATTRIBUTE((format (printf, 1, 2)));
|
||||||
|
@ -209,11 +213,41 @@ xuflds(FILE *fp, struct value values[])
|
||||||
if (getid(fp, buf) < 0) {
|
if (getid(fp, buf) < 0) {
|
||||||
return gripe("Junk in field %d", i + 1);
|
return gripe("Junk in field %d", i + 1);
|
||||||
}
|
}
|
||||||
if (!strcmp(buf, "nil")) {
|
ch = getc(fp);
|
||||||
|
ungetc(ch, fp);
|
||||||
|
if (ch == '(') {
|
||||||
|
ch = getc(fp);
|
||||||
|
ch = getc(fp);
|
||||||
|
ungetc(ch, fp);
|
||||||
|
if (isdigit(ch) || ch == '-') {
|
||||||
|
if (fscanf(fp, "%d", &values[i].v_field.v_int) != 1) {
|
||||||
|
return gripe("Malformed number in index field %d", i + 1);
|
||||||
|
}
|
||||||
|
values[i].v_index_name = strdup(buf);
|
||||||
|
values[i].v_type = VAL_INDEX_ID;
|
||||||
|
} else {
|
||||||
|
values[i].v_index_name = strdup(buf);
|
||||||
|
if (getid(fp, buf) < 0) {
|
||||||
|
free(values[i].v_index_name);
|
||||||
|
values[i].v_index_name = NULL;
|
||||||
|
return gripe("Malformed string in index field %d", i + 1);
|
||||||
|
}
|
||||||
|
values[i].v_field.v_string = strdup(buf);
|
||||||
|
values[i].v_type = VAL_INDEX_SYMBOL;
|
||||||
|
}
|
||||||
|
ch = getc(fp);
|
||||||
|
if (ch != ')') {
|
||||||
|
free(values[i].v_index_name);
|
||||||
|
values[i].v_index_name = NULL;
|
||||||
|
if (values[i].v_type == VAL_INDEX_SYMBOL)
|
||||||
|
free(values[i].v_field.v_string);
|
||||||
|
values[i].v_type = VAL_NOTUSED;
|
||||||
|
return gripe("Malformed index field %d", i + 1);
|
||||||
|
}
|
||||||
|
} else if (!strcmp(buf, "nil")) {
|
||||||
values[i].v_type = VAL_STRING;
|
values[i].v_type = VAL_STRING;
|
||||||
values[i].v_field.v_string = NULL;
|
values[i].v_field.v_string = NULL;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
values[i].v_type = VAL_SYMBOL;
|
values[i].v_type = VAL_SYMBOL;
|
||||||
values[i].v_field.v_string = strdup(buf);
|
values[i].v_field.v_string = strdup(buf);
|
||||||
}
|
}
|
||||||
|
@ -234,9 +268,11 @@ freeflds(struct value values[])
|
||||||
struct value *vp;
|
struct value *vp;
|
||||||
|
|
||||||
for (vp = values; vp->v_type != VAL_NOTUSED; vp++) {
|
for (vp = values; vp->v_type != VAL_NOTUSED; vp++) {
|
||||||
if (vp->v_type != VAL_DOUBLE)
|
if (vp->v_type != VAL_DOUBLE && vp->v_type != VAL_INDEX_ID)
|
||||||
free(vp->v_field.v_string);
|
free(vp->v_field.v_string);
|
||||||
}
|
}
|
||||||
|
free(vp->v_index_name);
|
||||||
|
vp->v_index_name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -467,6 +503,10 @@ xuloadrow(int type, int row, struct value values[])
|
||||||
break;
|
break;
|
||||||
case VAL_NOTUSED:
|
case VAL_NOTUSED:
|
||||||
return gripe("Missing column %s in file", ca[i].ca_name);
|
return gripe("Missing column %s in file", ca[i].ca_name);
|
||||||
|
case VAL_INDEX_ID:
|
||||||
|
case VAL_INDEX_SYMBOL:
|
||||||
|
return gripe("Index fields not supported in data rows in %s file",
|
||||||
|
ca[i].ca_name);
|
||||||
default:
|
default:
|
||||||
return gripe("Unknown value type %d", values[j].v_type);
|
return gripe("Unknown value type %d", values[j].v_type);
|
||||||
}
|
}
|
||||||
|
@ -534,9 +574,12 @@ xuheader(FILE *fp, int expected_table)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xucolumnheader(FILE *fp, int type)
|
xucolumnheader(FILE *fp, int type, struct value values[])
|
||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
|
struct empfile *ep = &empfile[type];
|
||||||
|
struct castr *ca = ep->cadef;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
if (!human)
|
if (!human)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -545,11 +588,77 @@ xucolumnheader(FILE *fp, int type)
|
||||||
ungetc(ch, fp);
|
ungetc(ch, fp);
|
||||||
|
|
||||||
/* FIXME parse column header */
|
/* FIXME parse column header */
|
||||||
if (fscanf(fp, "%*[^\n]\n") == -1)
|
if (xuflds(fp, values) <= 0) {
|
||||||
|
freeflds(values);
|
||||||
return gripe("Invalid Column Header for table %s",
|
return gripe("Invalid Column Header for table %s",
|
||||||
ef_nameof(type));
|
ef_nameof(type));
|
||||||
lineno++;
|
}
|
||||||
|
/* TODO
|
||||||
|
* check column count form xuflds()
|
||||||
|
*/
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; ca[i].ca_name; i++) {
|
||||||
|
if (ca[i].ca_flags & NSC_EXTRA)
|
||||||
|
continue;
|
||||||
|
k = 0;
|
||||||
|
do {
|
||||||
|
if (values[j].v_type == VAL_NOTUSED) {
|
||||||
|
freeflds(values);
|
||||||
|
return gripe("Not enough columns in the header for table %s",
|
||||||
|
ef_nameof(type));
|
||||||
|
}
|
||||||
|
switch(values[j].v_type) {
|
||||||
|
case VAL_SYMBOL:
|
||||||
|
if (ca[i].ca_len != 0) {
|
||||||
|
freeflds(values);
|
||||||
|
return gripe("Column %s is a not index format for table %s",
|
||||||
|
ca[i].ca_name, ef_nameof(type));
|
||||||
|
}
|
||||||
|
if (strcmp(values[j].v_field.v_string, ca[i].ca_name) != 0) {
|
||||||
|
gripe("Column name (%s) does not match header name (%s)",
|
||||||
|
ca[i].ca_name, values[j].v_field.v_string);
|
||||||
|
freeflds(values);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VAL_INDEX_SYMBOL:
|
||||||
|
return gripe("Column %s is does not currently support index symbol format for table %s",
|
||||||
|
ca[i].ca_name, ef_nameof(type));
|
||||||
|
case VAL_INDEX_ID:
|
||||||
|
if (ca[i].ca_len == 0) {
|
||||||
|
freeflds(values);
|
||||||
|
return gripe("Column %s is in index format and should not be for table %s",
|
||||||
|
ca[i].ca_name, ef_nameof(type));
|
||||||
|
}
|
||||||
|
if (values[j].v_field.v_int != k) {
|
||||||
|
freeflds(values);
|
||||||
|
return gripe("Column Array index %d does not match %d",
|
||||||
|
values[j].v_field.v_int, k);
|
||||||
|
}
|
||||||
|
if (strcmp(values[j].v_index_name, ca[i].ca_name) != 0) {
|
||||||
|
gripe("Column name (%s) does not match header name (%s)",
|
||||||
|
ca[i].ca_name, values[j].v_field.v_string);
|
||||||
|
freeflds(values);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
freeflds(values);
|
||||||
|
return gripe("Column %s is a not string for table %s",
|
||||||
|
ca[i].ca_name, ef_nameof(type));
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
k++;
|
||||||
|
} while (k < ca[i].ca_len);
|
||||||
|
}
|
||||||
|
if (values[j].v_type != VAL_NOTUSED) {
|
||||||
|
freeflds(values);
|
||||||
|
return gripe("Too many columns in the header for table %s",
|
||||||
|
ef_nameof(type));
|
||||||
|
}
|
||||||
|
lineno++;
|
||||||
|
freeflds(values);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,6 +704,8 @@ xundump(FILE *fp, char *file, int expected_table)
|
||||||
int type;
|
int type;
|
||||||
int fixed_rows;
|
int fixed_rows;
|
||||||
|
|
||||||
|
memset(values, 0, sizeof(values));
|
||||||
|
|
||||||
if (strcmp(fname, file) != 0) {
|
if (strcmp(fname, file) != 0) {
|
||||||
fname = file;
|
fname = file;
|
||||||
lineno = 1;
|
lineno = 1;
|
||||||
|
@ -608,7 +719,7 @@ xundump(FILE *fp, char *file, int expected_table)
|
||||||
fixed_rows = has_const(ef_cadef(type));
|
fixed_rows = has_const(ef_cadef(type));
|
||||||
need_sentinel = !fixed_rows; /* FIXME only approximation */
|
need_sentinel = !fixed_rows; /* FIXME only approximation */
|
||||||
|
|
||||||
if (xucolumnheader(fp, type) == -1)
|
if (xucolumnheader(fp, type, values) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
row = 0;
|
row = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue