xundump: Support splitting any table
Each part of a split table needs to supply rows for the same objects.
We currently require each part to name its objects explicitly, with an
object ID field, and don't support splitting tables that don't have
such IDs. These restrictions became arbitrary when commit 4e23c45
implemented checking each partial table supplies the same rows. Relax
them.
Affects tables sect, news, lost, realm, game, infrastructure.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
This commit is contained in:
parent
67425a06d9
commit
515beef12e
9 changed files with 41 additions and 94 deletions
|
@ -87,7 +87,6 @@ static int may_trunc; /* Okay to truncate? */
|
||||||
|
|
||||||
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(void);
|
|
||||||
static int chkflds(void);
|
static int chkflds(void);
|
||||||
static int setnum(int, double);
|
static int setnum(int, double);
|
||||||
static int setstr(int, char *);
|
static int setstr(int, char *);
|
||||||
|
@ -158,22 +157,6 @@ tbl_seek(int id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the next object.
|
|
||||||
* Must not have a record index.
|
|
||||||
* Store it in cur_obj, and set cur_id accordingly.
|
|
||||||
* Return 0 on success, -1 on failure.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
tbl_next_obj(void)
|
|
||||||
{
|
|
||||||
int max_id = ef_id_limit(cur_type);
|
|
||||||
|
|
||||||
if (cur_id >= max_id)
|
|
||||||
return gripe("Too many rows");
|
|
||||||
return tbl_seek(cur_id + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Omit ID1..ID2-1.
|
* Omit ID1..ID2-1.
|
||||||
* Reset the omitted objects to default state.
|
* Reset the omitted objects to default state.
|
||||||
|
@ -214,18 +197,17 @@ expected_id(int id1, int id2)
|
||||||
/*
|
/*
|
||||||
* Get the next object, it has record index ID.
|
* Get the next object, it has record index ID.
|
||||||
* Store it in cur_obj, and set cur_id accordingly.
|
* Store it in cur_obj, and set cur_id accordingly.
|
||||||
* Ensure we're omitting the same objects as the previous parts.
|
|
||||||
* Reset any omitted objects to default state.
|
* Reset any omitted objects to default state.
|
||||||
* Return 0 on success, -1 on failure.
|
* Return 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
tbl_skip_to_obj(int id)
|
tbl_skip_to_obj(int id)
|
||||||
{
|
{
|
||||||
struct empfile *ep = &empfile[cur_type];
|
|
||||||
int prev_id = cur_id;
|
int prev_id = cur_id;
|
||||||
int max_id, exp_id;
|
int max_id;
|
||||||
|
|
||||||
if (partno == 0) {
|
if (CANT_HAPPEN(partno != 0))
|
||||||
|
return -1;
|
||||||
if (!may_omit_id && id != cur_id + 1)
|
if (!may_omit_id && id != cur_id + 1)
|
||||||
return gripe("Expected %d in field %d", cur_id + 1, 1);
|
return gripe("Expected %d in field %d", cur_id + 1, 1);
|
||||||
if (id <= cur_id)
|
if (id <= cur_id)
|
||||||
|
@ -233,24 +215,36 @@ tbl_skip_to_obj(int id)
|
||||||
max_id = ef_id_limit(cur_type);
|
max_id = ef_id_limit(cur_type);
|
||||||
if (id > max_id)
|
if (id > max_id)
|
||||||
return gripe("Field %d must be <= %d", 1, max_id);
|
return gripe("Field %d must be <= %d", 1, max_id);
|
||||||
} else {
|
|
||||||
exp_id = expected_id(cur_id + 1, ep->fids);
|
|
||||||
if (exp_id < 0)
|
|
||||||
return gripe("Table's first part doesn't have this row");
|
|
||||||
else if (id != exp_id)
|
|
||||||
return gripe("Expected %d in field %d,"
|
|
||||||
" like in table's first part",
|
|
||||||
exp_id, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tbl_seek(id) < 0)
|
if (tbl_seek(id) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (partno == 0)
|
|
||||||
omit_ids(prev_id + 1, id);
|
omit_ids(prev_id + 1, id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the next object.
|
||||||
|
* Store it in cur_obj, and set cur_id accordingly.
|
||||||
|
* Return 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tbl_next_obj(void)
|
||||||
|
{
|
||||||
|
int next_id;
|
||||||
|
|
||||||
|
if (partno == 0) {
|
||||||
|
if (cur_id >= ef_id_limit(cur_type))
|
||||||
|
return gripe("Too many rows");
|
||||||
|
next_id = cur_id + 1;
|
||||||
|
} else {
|
||||||
|
next_id = expected_id(cur_id + 1, empfile[cur_type].fids);
|
||||||
|
if (next_id < 0)
|
||||||
|
return gripe("Table's first part doesn't have this row");
|
||||||
|
}
|
||||||
|
return tbl_seek(next_id);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish table part.
|
* Finish table part.
|
||||||
* If the table has variable length, truncate it.
|
* If the table has variable length, truncate it.
|
||||||
|
@ -378,8 +372,9 @@ xufldname(FILE *fp, int i)
|
||||||
case '.':
|
case '.':
|
||||||
if (getc(fp) != '.' || getc(fp) != '.')
|
if (getc(fp) != '.' || getc(fp) != '.')
|
||||||
return gripe("Junk in header field %d", i + 1);
|
return gripe("Junk in header field %d", i + 1);
|
||||||
if (defellipsis() < 0)
|
if (i == 0)
|
||||||
return -1;
|
return gripe("Header fields expected");
|
||||||
|
ellipsis = 1;
|
||||||
ch = skipfs(fp);
|
ch = skipfs(fp);
|
||||||
if (ch != EOF && ch != '\n')
|
if (ch != EOF && ch != '\n')
|
||||||
return gripe("Junk after ...");
|
return gripe("Junk after ...");
|
||||||
|
@ -563,29 +558,6 @@ deffld(int fldno, char *name, int idx)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Record that header ends with ...
|
|
||||||
* Set ellipsis and is_partial.
|
|
||||||
* Return 0 on success, -1 on error.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
defellipsis(void)
|
|
||||||
{
|
|
||||||
struct castr *ca = ef_cadef(cur_type);
|
|
||||||
|
|
||||||
if (ca[0].ca_table != cur_type || (ca[0].ca_flags & NSC_EXTRA))
|
|
||||||
return gripe("Table %s doesn't support ...", ef_nameof(cur_type));
|
|
||||||
ellipsis = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is table split into parts? */
|
|
||||||
static int
|
|
||||||
is_partial(void)
|
|
||||||
{
|
|
||||||
return ellipsis || partno;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check fields in xdump are sane.
|
* Check fields in xdump are sane.
|
||||||
* Return 0 on success, -1 on error.
|
* Return 0 on success, -1 on error.
|
||||||
|
@ -600,13 +572,6 @@ chkflds(void)
|
||||||
if (ca[0].ca_table == cur_type && caflds[0] && fldca[0] != &ca[0])
|
if (ca[0].ca_table == cur_type && caflds[0] && fldca[0] != &ca[0])
|
||||||
res = gripe("Header field %s must come first", ca[0].ca_name);
|
res = gripe("Header field %s must come first", ca[0].ca_name);
|
||||||
|
|
||||||
if (is_partial()) {
|
|
||||||
/* Need a join field, use 0-th selector */
|
|
||||||
if (!caflds[0])
|
|
||||||
res = gripe("Header field %s required in each table part",
|
|
||||||
ca[0].ca_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ellipsis)
|
if (ellipsis)
|
||||||
return res; /* table is split, another part expected */
|
return res; /* table is split, another part expected */
|
||||||
|
|
||||||
|
@ -683,7 +648,7 @@ setnum(int fldno, double dbl)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (fldno == 0) {
|
if (fldno == 0) {
|
||||||
if (ca->ca_table == cur_type) {
|
if (partno == 0 && ca->ca_table == cur_type) {
|
||||||
/* Got record index */
|
/* Got record index */
|
||||||
next_id = (int)dbl;
|
next_id = (int)dbl;
|
||||||
if (next_id != dbl)
|
if (next_id != dbl)
|
||||||
|
|
|
@ -2,11 +2,8 @@ tests/empdump/xundump-errors/colhdr-amb:2: Header m of field 3 is ambiguous
|
||||||
tests/empdump/xundump-errors/colhdr-dup:2: Duplicate header name in field 2
|
tests/empdump/xundump-errors/colhdr-dup:2: Duplicate header name in field 2
|
||||||
tests/empdump/xundump-errors/colhdr-dup2:6: Duplicate header name in field 3
|
tests/empdump/xundump-errors/colhdr-dup2:6: Duplicate header name in field 3
|
||||||
tests/empdump/xundump-errors/colhdr-dup3:2: Duplicate header pkg(0) in field 8
|
tests/empdump/xundump-errors/colhdr-dup3:2: Duplicate header pkg(0) in field 8
|
||||||
tests/empdump/xundump-errors/colhdr-ellipsis:2: Header field uid required in each table part
|
tests/empdump/xundump-errors/colhdr-ellipsis:2: Header fields expected
|
||||||
tests/empdump/xundump-errors/colhdr-ellipsis2:2: Junk after ...
|
tests/empdump/xundump-errors/colhdr-ellipsis2:2: Junk after ...
|
||||||
tests/empdump/xundump-errors/colhdr-ellipsis3:2: Table infrastructure doesn't support ...
|
|
||||||
tests/empdump/xundump-errors/colhdr-ellipsis4:2: Header field uid required in each table part
|
|
||||||
tests/empdump/xundump-errors/colhdr-ellipsis5:2: Table sect doesn't support ...
|
|
||||||
tests/empdump/xundump-errors/colhdr-eof:2: Unexpected EOF
|
tests/empdump/xundump-errors/colhdr-eof:2: Unexpected EOF
|
||||||
tests/empdump/xundump-errors/colhdr-first:2: Header field uid must come first
|
tests/empdump/xundump-errors/colhdr-first:2: Header field uid must come first
|
||||||
tests/empdump/xundump-errors/colhdr-idxbig:2: Header pkg(99) index out of bounds in field 7
|
tests/empdump/xundump-errors/colhdr-idxbig:2: Header pkg(99) index out of bounds in field 7
|
||||||
|
@ -22,7 +19,6 @@ tests/empdump/xundump-errors/colhdr-miss:2: Header field uid missing
|
||||||
tests/empdump/xundump-errors/colhdr-miss:2: Header field ctype(2) missing
|
tests/empdump/xundump-errors/colhdr-miss:2: Header field ctype(2) missing
|
||||||
tests/empdump/xundump-errors/colhdr-miss:2: Header fields camt(0) ... camt(2) missing
|
tests/empdump/xundump-errors/colhdr-miss:2: Header fields camt(0) ... camt(2) missing
|
||||||
tests/empdump/xundump-errors/colhdr-miss:2: Header field nllag missing
|
tests/empdump/xundump-errors/colhdr-miss:2: Header field nllag missing
|
||||||
tests/empdump/xundump-errors/colhdr-miss2:21: Header field uid required in each table part
|
|
||||||
tests/empdump/xundump-errors/colhdr-miss2:21: Header fields ctype(0) ... ctype(2) missing
|
tests/empdump/xundump-errors/colhdr-miss2:21: Header fields ctype(0) ... ctype(2) missing
|
||||||
tests/empdump/xundump-errors/colhdr-miss2:21: Header fields camt(0) ... camt(2) missing
|
tests/empdump/xundump-errors/colhdr-miss2:21: Header fields camt(0) ... camt(2) missing
|
||||||
tests/empdump/xundump-errors/colhdr-miss2:21: Header field type missing
|
tests/empdump/xundump-errors/colhdr-miss2:21: Header field type missing
|
||||||
|
@ -75,7 +71,7 @@ tests/empdump/xundump-errors/fld-nosymset:2: Field 1 doesn't take symbol sets
|
||||||
tests/empdump/xundump-errors/fld-sep:2: Bad field separator after field 1
|
tests/empdump/xundump-errors/fld-sep:2: Bad field separator after field 1
|
||||||
tests/empdump/xundump-errors/fld-strbig:3: Field 19 takes at most 9 characters
|
tests/empdump/xundump-errors/fld-strbig:3: Field 19 takes at most 9 characters
|
||||||
tests/empdump/xundump-errors/fld-unexpid:6: Table's first part doesn't have this row
|
tests/empdump/xundump-errors/fld-unexpid:6: Table's first part doesn't have this row
|
||||||
tests/empdump/xundump-errors/fld-unexpid1:7: Expected 2 in field 1, like in table's first part
|
tests/empdump/xundump-errors/fld-unexpid1:7: Value for field 1 must be 2
|
||||||
tests/empdump/xundump-errors/fld-unksym:2: Unknown level symbol `xxx' in field 11
|
tests/empdump/xundump-errors/fld-unksym:2: Unknown level symbol `xxx' in field 11
|
||||||
tests/empdump/xundump-errors/fld-unparen:2: Unmatched '(' in field 19
|
tests/empdump/xundump-errors/fld-unparen:2: Unmatched '(' in field 19
|
||||||
tests/empdump/xundump-errors/ftr-fewrows:2: Expected 1024 more rows
|
tests/empdump/xundump-errors/ftr-fewrows:2: Expected 1024 more rows
|
||||||
|
|
|
@ -69,9 +69,6 @@
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
0
|
0
|
||||||
1
|
1
|
||||||
0
|
0
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
config product
|
config product
|
||||||
...
|
...
|
||||||
# Header field uid required in each table part
|
# Header fields expected
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
config infrastructure
|
|
||||||
name ...
|
|
||||||
# Table infrastructure doesn't support ...
|
|
|
@ -1,3 +0,0 @@
|
||||||
config product
|
|
||||||
sname name ...
|
|
||||||
# Header field uid required in each table part
|
|
|
@ -1,4 +0,0 @@
|
||||||
config sect
|
|
||||||
xloc yloc ...
|
|
||||||
# Table sect doesn't support ...
|
|
||||||
/config
|
|
|
@ -19,7 +19,6 @@ uid sname ...
|
||||||
|
|
||||||
config product
|
config product
|
||||||
name
|
name
|
||||||
# Header field uid required in each table part
|
|
||||||
# Header fields ctype(0) ... ctype(2) missing
|
# Header fields ctype(0) ... ctype(2) missing
|
||||||
# Header fields camt(0) ... camt(2) missing
|
# Header fields camt(0) ... camt(2) missing
|
||||||
# Header field type missing
|
# Header field type missing
|
||||||
|
|
|
@ -5,5 +5,5 @@ uid ...
|
||||||
config ship
|
config ship
|
||||||
uid ...
|
uid ...
|
||||||
1
|
1
|
||||||
# Expected 2 in field 1, like in table's first part
|
# Value for field 1 must be 2
|
||||||
/config
|
/config
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue