static int verify_tabref(int type, int row, struct castr *ca, int idx, long val) { int tabno = ca->ca_table; struct castr *ca_sym = ef_cadef(tabno); int i; if (ca->ca_flags & NSC_BITS) { /* symbol set */ if (CANT_HAPPEN(ca_sym != symbol_ca)) return -1; for (i = 0; i < (int)sizeof(long) * 8; i++) { if (val & (1UL << i)) { if (!symbol_by_value(1L << i, ef_ptr(tabno, 0))) { verify_fail(type, row, ca, idx, "bit %d is not in symbol table %s", i, ef_nameof(tabno)); return -1; } } } } else if (ca_sym == symbol_ca) { /* symbol */ if (!symbol_by_value(val, ef_ptr(tabno, 0))) { verify_fail(type, row, ca, idx, "value %ld is not in symbol table %s", val, ef_nameof(tabno)); return -1; } } else { /* table index */ if (val >= ef_nelem(tabno) || val < -1) { verify_fail(type, row, ca, idx, "value %ld indexes table %s out of bounds 0..%d", val, ef_nameof(tabno), ef_nelem(tabno)); return -1; } /* laziness: assumes TABNO is EFF_MEM */ if (val >= 0 && !empobj_in_use(tabno, ef_ptr(tabno, val))) { verify_fail(type, row, ca, idx, "value %ld refers to missing element of table %s", val, ef_nameof(tabno)); return -1; } } return 0; }
/* * Dump symbol with value @key from symbol table @type to @xd. * Prefix with @sep, return " ". */ static char * xdprsym(struct xdstr *xd, int key, int type, char *sep) { char *sym = symbol_by_value(key, ef_ptr(type, 0)); if (!sym) { CANT_HAPPEN(!xd->sloppy); xd->pr("%s%d", sep, key); } else { xd->pr("%s", sep); xdpresc(xd, sym, INT_MAX); } return " "; }
static int verify_row(int type, int row) { struct castr *ca = ef_cadef(type); struct empobj *row_ref; int i, j, n; struct valstr val; int ret_val = 0; int flags = ef_flags(type); if (flags & EFF_MEM) row_ref = ef_ptr(type, row); else { row_ref = malloc(empfile[type].size); ef_read(type, row, row_ref); } if ((flags & EFF_TYPED) && !EF_IS_VIEW(type)) { if (row_ref->ef_type != type || row_ref->uid != row) { verify_fail(type, row, NULL, 0, "header corrupt"); ret_val = -1; } } if (!empobj_in_use(type, row_ref)) goto out; for (i = 0; ca[i].ca_name; ++i) { if (ca[i].ca_get) continue; /* virtual */ n = CA_ARRAY_LEN(&ca[i]); j = 0; do { if (ca[i].ca_table == EF_BAD) continue; nstr_mksymval(&val, &ca[i], j); nstr_eval(&val, 0, row_ref, NSC_NOTYPE); if (CANT_HAPPEN(val.val_type != NSC_LONG)) { ret_val = -1; continue; } if (ca[i].ca_table == type && i == 0) { /* uid */ if (val.val_as.lng != row) { verify_fail(type, row, &ca[i], j, "value is %ld instead of %d", val.val_as.lng, row); ret_val = -1; } } else { if (verify_tabref(type, row, &ca[i], j, val.val_as.lng) < 0) ret_val = -1; } } while (++j < n); } out: if (!(flags & EFF_MEM)) free(row_ref); return ret_val; }