char rcsid_plank[] = "$Id$"; #include #include #include #include "b.h" #include "fe.h" #define ERROR_VAL 0 int speedflag = 0; Item_Set *sortedStates; static struct stateMapTable smt; int exceptionTolerance = 0; static int plankSize = 32; static Plank newPlank ARGS((void)); static PlankMap newPlankMap ARGS((int)); static StateMap newStateMap ARGS((void)); static Exception newException ARGS((int, int)); static void enterStateMap ARGS((PlankMap, short *, int, int *)); static List assemblePlanks ARGS((void)); static void assignRules ARGS((RuleAST)); static int stateCompare ARGS((Item_Set *, Item_Set *)); static int ruleCompare ARGS((RuleAST *, RuleAST *)); static void renumber ARGS((void)); static short * newVector ARGS((void)); static int width ARGS((int)); static PlankMap mapToPmap ARGS((Dimension)); static void doDimPmaps ARGS((Operator)); static void doNonTermPmaps ARGS((NonTerminal)); static void makePmaps ARGS((void)); static void outPlank ARGS((Plank)); static void purgePlanks ARGS((List)); static void inToEx ARGS((void)); static void makePlankRuleMacros ARGS((void)); static void makePlankRule ARGS((void)); static void exceptionSwitch ARGS((List, const char *, const char *, const char *, int, const char *)); static void doPlankLabel ARGS((Operator)); static void doPlankLabelSafely ARGS((Operator)); static void doPlankLabelMacrosSafely ARGS((Operator)); static void makePlankState ARGS((void)); static Plank newPlank() { Plank p; char buf[50]; static int num = 0; p = (Plank) zalloc(sizeof(struct plank)); sprintf(buf, "%s_plank_%d", prefix, num++); p->name = (char *) zalloc(strlen(buf)+1); strcpy(p->name, buf); return p; } static PlankMap newPlankMap(offset) int offset; { PlankMap im; im = (PlankMap) zalloc(sizeof(struct plankMap)); im->offset = offset; return im; } static StateMap newStateMap() { char buf[50]; static int num = 0; StateMap sm; sm = (StateMap) zalloc(sizeof(struct stateMap)); sprintf(buf, "f%d", num++); sm->fieldname = (char *) zalloc(strlen(buf)+1); strcpy(sm->fieldname, buf); return sm; } static Exception newException(index, value) int index; int value; { Exception e; e = (Exception) zalloc(sizeof(struct except)); e->index = index; e->value = value; return e; } static void enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new; { int i; StateMap sm; List l; int size; assert(im); assert(v); assert(width > 0); size = globalMap->count; for (l = smt.maps; l; l = l->next) { int ecount; sm = (StateMap) l->x; ecount = 0; for (i = 0; i < size; i++) { if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) { if (++ecount > exceptionTolerance) { goto again; } } } for (i = 0; i < size; i++) { assert(v[i] >= 0); assert(sm->value[i] >= 0); if (v[i] == -1) { continue; } if (sm->value[i] == -1) { sm->value[i] = v[i]; } else if (v[i] != sm->value[i]) { im->exceptions = newList(newException(i,v[i]), im->exceptions); } } im->values = sm; if (width > sm->width) { sm->width = width; } *new = 0; return; again: ; } sm = newStateMap(); im->values = sm; sm->value = v; sm->width = width; *new = 1; smt.maps = newList(sm, smt.maps); } static List assemblePlanks() { List planks = 0; Plank pl; List p; List s; for (s = smt.maps; s; s = s->next) { StateMap sm = (StateMap) s->x; for (p = planks; p; p = p->next) { pl = (Plank) p->x; if (sm->width <= plankSize - pl->width) { pl->width += sm->width; pl->fields = newList(sm, pl->fields); sm->plank = pl; goto next; } } pl = newPlank(); pl->width = sm->width; pl->fields = newList(sm, 0); sm->plank = pl; planks = appendList(pl, planks); next: ; } return planks; } RuleAST *sortedRules; static int count; static void assignRules(ast) RuleAST ast; { sortedRules[count++] = ast; } static int stateCompare(s, t) Item_Set *s; Item_Set *t; { return strcmp((*s)->op->name, (*t)->op->name); } static int ruleCompare(s, t) RuleAST *s; RuleAST *t; { return strcmp((*s)->lhs, (*t)->lhs); } void dumpSortedStates() { int i; printf("dump Sorted States: "); for (i = 0; i < globalMap->count; i++) { printf("%d ", sortedStates[i]->num); } printf("\n"); } void dumpSortedRules() { int i; printf("dump Sorted Rules: "); for (i = 0; i < max_ruleAST; i++) { printf("%d ", sortedRules[i]->rule->erulenum); } printf("\n"); } static void renumber() { int i; Operator previousOp; NonTerminal previousLHS; int base_counter; sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set)); for (i = 1; i < globalMap->count; i++) { sortedStates[i-1] = globalMap->set[i]; } qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), (int(*)(const void *, const void *))stateCompare); previousOp = 0; for (i = 0; i < globalMap->count-1; i++) { sortedStates[i]->newNum = i; sortedStates[i]->op->stateCount++; if (previousOp != sortedStates[i]->op) { sortedStates[i]->op->baseNum = i; previousOp = sortedStates[i]->op; } } sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST)); count = 0; foreachList((ListFn) assignRules, ruleASTs); qsort(sortedRules, max_ruleAST, sizeof(RuleAST), (int(*)(const void *, const void *))ruleCompare); previousLHS = 0; base_counter = 0; for (i = 0; i < max_ruleAST; i++) { if (previousLHS != sortedRules[i]->rule->lhs) { sortedRules[i]->rule->lhs->baseNum = base_counter; previousLHS = sortedRules[i]->rule->lhs; base_counter++; /* make space for 0 */ } sortedRules[i]->rule->newNum = base_counter; sortedRules[i]->rule->lhs->ruleCount++; sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */ base_counter++; } } static short * newVector() { short *p; p = (short *) zalloc(globalMap->count* sizeof(short)); return p; } static int width(v) int v; { int c; for (c = 0; v; v >>= 1) { c++; } return c; } static PlankMap mapToPmap(d) Dimension d; { PlankMap im; short *v; int i; int new; if (d->map->count == 1) { return 0; } assert(d->map->count > 1); im = newPlankMap(0); v = newVector(); for (i = 0; i < globalMap->count-1; i++) { int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; assert(index >= 0); v[i+1] = index; } v[0] = 0; enterStateMap(im, v, width(d->map->count), &new); if (!new) { zfree(v); } return im; } static void doDimPmaps(op) Operator op; { int i, j; Dimension d; short *v; PlankMap im; int new; if (!op->table->rules) { return; } switch (op->arity) { case 0: break; case 1: d = op->table->dimen[0]; if (d->map->count > 1) { v = newVector(); im = newPlankMap(op->baseNum); for (i = 0; i < globalMap->count-1; i++) { int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; if (index) { Item_Set *ts = transLval(op->table, index, 0); v[i+1] = (*ts)->newNum - op->baseNum+1; assert(v[i+1] >= 0); } } enterStateMap(im, v, width(d->map->count-1), &new); if (!new) { zfree(v); } d->pmap = im; } break; case 2: if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) { op->table->dimen[0]->pmap = 0; op->table->dimen[1]->pmap = 0; } else if (op->table->dimen[0]->map->count == 1) { v = newVector(); im = newPlankMap(op->baseNum); d = op->table->dimen[1]; for (i = 0; i < globalMap->count-1; i++) { int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; if (index) { Item_Set *ts = transLval(op->table, 1, index); v[i+1] = (*ts)->newNum - op->baseNum+1; assert(v[i+1] >= 0); } } enterStateMap(im, v, width(d->map->count-1), &new); if (!new) { zfree(v); } d->pmap = im; } else if (op->table->dimen[1]->map->count == 1) { v = newVector(); im = newPlankMap(op->baseNum); d = op->table->dimen[0]; for (i = 0; i < globalMap->count-1; i++) { int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; if (index) { Item_Set *ts = transLval(op->table, index, 1); v[i +1] = (*ts)->newNum - op->baseNum +1; assert(v[i +1] >= 0); } } enterStateMap(im, v, width(d->map->count-1), &new); if (!new) { zfree(v); } d->pmap = im; } else { op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]); op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]); /* output table */ fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {", op->stateCount <= 255 ? "char" : "short", prefix, op->name, op->table->dimen[0]->map->count, op->table->dimen[1]->map->count); for (i = 0; i < op->table->dimen[0]->map->count; i++) { if (i > 0) { fprintf(outfile, ","); } fprintf(outfile, "\n{"); for (j = 0; j < op->table->dimen[1]->map->count; j++) { Item_Set *ts = transLval(op->table, i, j); short diff; if (j > 0) { fprintf(outfile, ","); if (j % 10 == 0) { fprintf(outfile, "\t/* row %d, cols %d-%d*/\n", i, j-10, j-1); } } if ((*ts)->num > 0) { diff = (*ts)->newNum - op->baseNum +1; } else { diff = 0; } fprintf(outfile, "%5d", diff); } fprintf(outfile, "}\t/* row %d */", i); } fprintf(outfile, "\n};\n"); } break; default: assert(0); } } static NonTerminal *ntVector; static void doNonTermPmaps(n) NonTerminal n; { short *v; PlankMap im; int new; int i; ntVector[n->num] = n; if (n->num >= last_user_nonterminal) { return; } if (n->ruleCount <= 0) { return; } im = newPlankMap(n->baseNum); v = newVector(); for (i = 0; i < globalMap->count-1; i++) { Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule; if (r) { r->used = 1; v[i+1] = r->newNum - n->baseNum /*safely*/; assert(v[i+1] >= 0); } } enterStateMap(im, v, width(n->ruleCount+1), &new); if (!new) { zfree(v); } n->pmap = im; } static void makePmaps() { foreachList((ListFn) doDimPmaps, operators); ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal)); foreachList((ListFn) doNonTermPmaps, nonterminals); } static void outPlank(p) Plank p; { List f; int i; fprintf(outfile, "static struct {\n"); for (f = p->fields; f; f = f->next) { StateMap sm = (StateMap) f->x; fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width); } fprintf(outfile, "} %s[] = {\n", p->name); for (i = 0; i < globalMap->count; i++) { fprintf(outfile, "\t{"); for (f = p->fields; f; f = f->next) { StateMap sm = (StateMap) f->x; fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]); } fprintf(outfile, "},\t/* row %d */\n", i); } fprintf(outfile, "};\n"); } static void purgePlanks(planks) List planks; { List p; for (p = planks; p; p = p->next) { Plank x = (Plank) p->x; outPlank(x); } } static void inToEx() { int i; int counter; fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix); counter = 0; for (i = 0; i < max_ruleAST; i++) { if (counter > 0) { fprintf(outfile, ","); if (counter % 10 == 0) { fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1); } } if (counter < sortedRules[i]->rule->newNum) { assert(counter == sortedRules[i]->rule->newNum-1); fprintf(outfile, "%5d", 0); counter++; if (counter > 0) { fprintf(outfile, ","); if (counter % 10 == 0) { fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1); } } } fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum); counter++; } fprintf(outfile, "\n};\n"); } static void makePlankRuleMacros() { int i; for (i = 1; i < last_user_nonterminal; i++) { List es; PlankMap im = ntVector[i]->pmap; fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name); if (im) { fprintf(outfile, "%s_eruleMap[", prefix); for (es = im->exceptions; es; es = es->next) { Exception e = (Exception) es->x; fprintf(outfile, "((state) == %d ? %d :", e->index, e->value); } fprintf(outfile, "%s[state].%s", im->values->plank->name, im->values->fieldname); for (es = im->exceptions; es; es = es->next) { fprintf(outfile, ")"); } fprintf(outfile, " +%d]", im->offset); } else { /* nonterminal never appears on LHS. */ assert(ntVector[i] == start); fprintf(outfile, "0"); } fprintf(outfile, "\n"); } fprintf(outfile, "\n"); } static void makePlankRule() { int i; makePlankRuleMacros(); fprintf(outfile, "#ifdef __STDC__\n"); fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix); fprintf(outfile, "#else\n"); fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix); fprintf(outfile, "#endif\n"); fprintf(outfile, "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n", prefix, globalMap->count, prefix, prefix); fprintf(outfile, "\tswitch(goalnt) {\n"); for (i = 1; i < last_user_nonterminal; i++) { fprintf(outfile, "\tcase %d:\n", i); fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name); } fprintf(outfile, "\tdefault:\n"); fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix); fprintf(outfile, "\t\tabort();\n"); fprintf(outfile, "\t\treturn 0;\n"); fprintf(outfile, "\t}\n"); fprintf(outfile, "}\n"); } static void exceptionSwitch(es, sw, pre, post, offset, def) List es; const char *sw; const char *pre; const char *post; int offset; const char *def; { if (es) { fprintf(outfile, "\t\tswitch (%s) {\n", sw); for (; es; es = es->next) { Exception e = (Exception) es->x; fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post); } if (def) { fprintf(outfile, "\t\tdefault: %s;\n", def); } fprintf(outfile, "\t\t}\n"); } else { if (def) { fprintf(outfile, "\t\t%s;\n", def); } } } static void doPlankLabel(op) Operator op; { PlankMap im0; PlankMap im1; char buf[100]; fprintf(outfile, "\tcase %d:\n", op->num); switch (op->arity) { case 0: fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum); break; case 1: im0 = op->table->dimen[0]->pmap; if (im0) { exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0); fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", im0->values->plank->name, im0->values->fieldname, im0->offset); } else { Item_Set *ts = transLval(op->table, 1, 0); if (*ts) { fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum); } else { fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); } } break; case 2: im0 = op->table->dimen[0]->pmap; im1 = op->table->dimen[1]->pmap; if (!im0 && !im1) { Item_Set *ts = transLval(op->table, 1, 1); if (*ts) { fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum); } else { fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); } } else if (!im0) { exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0); fprintf(outfile, "\t\treturn %s[r].%s + %d;\n", im1->values->plank->name, im1->values->fieldname, im1->offset); } else if (!im1) { exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0); fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", im0->values->plank->name, im0->values->fieldname, im0->offset); } else { assert(im0->offset == 0); assert(im1->offset == 0); sprintf(buf, "l = %s[l].%s", im0->values->plank->name, im0->values->fieldname); exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf); sprintf(buf, "r = %s[r].%s", im1->values->plank->name, im1->values->fieldname); exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf); fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n", prefix, op->name, op->baseNum); } break; default: assert(0); } } static void doPlankLabelMacrosSafely(op) Operator op; { PlankMap im0; PlankMap im1; switch (op->arity) { case -1: fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name); break; case 0: fprintf(outfile, "#define %s_%s_state", prefix, op->name); fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1); break; case 1: fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name); im0 = op->table->dimen[0]->pmap; if (im0) { if (im0->exceptions) { List es = im0->exceptions; assert(0); fprintf(outfile, "\t\tswitch (l) {\n"); for (; es; es = es->next) { Exception e = (Exception) es->x; fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0); } fprintf(outfile, "\t\t}\n"); } if (speedflag) { fprintf(outfile, "\t( %s[l].%s + %d )\n", im0->values->plank->name, im0->values->fieldname, im0->offset); } else { fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n", prefix, im0->values->plank->name, im0->values->fieldname, prefix, im0->offset); } } else { Item_Set *ts = transLval(op->table, 1, 0); if (*ts) { fprintf(outfile, "\t%d\n", (*ts)->newNum+1); } else { fprintf(outfile, "\t%d\n", 0); } } break; case 2: fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name); im0 = op->table->dimen[0]->pmap; im1 = op->table->dimen[1]->pmap; if (!im0 && !im1) { Item_Set *ts = transLval(op->table, 1, 1); assert(0); if (*ts) { fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1); } else { fprintf(outfile, "\t\treturn %d;\n", 0); } } else if (!im0) { assert(0); if (im1->exceptions) { List es = im1->exceptions; fprintf(outfile, "\t\tswitch (r) {\n"); for (; es; es = es->next) { Exception e = (Exception) es->x; fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0); } fprintf(outfile, "\t\t}\n"); } fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n", im1->values->plank->name, im1->values->fieldname, im1->offset); fprintf(outfile, "\t\tbreak;\n"); } else if (!im1) { assert(0); if (im0->exceptions) { List es = im0->exceptions; fprintf(outfile, "\t\tswitch (l) {\n"); for (; es; es = es->next) { Exception e = (Exception) es->x; fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0); } fprintf(outfile, "\t\t}\n"); } fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n", im0->values->plank->name, im0->values->fieldname, im0->offset); fprintf(outfile, "\t\tbreak;\n"); } else { assert(im0->offset == 0); assert(im1->offset == 0); /* sprintf(buf, "l = %s[l].%s", im0->values->plank->name, im0->values->fieldname); exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf); sprintf(buf, "r = %s[r].%s", im1->values->plank->name, im1->values->fieldname); exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf); fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n", prefix, op->name, op->baseNum); fprintf(outfile, "\t\tbreak;\n"); */ if (speedflag) { fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n", prefix, op->name, im0->values->plank->name, im0->values->fieldname, im1->values->plank->name, im1->values->fieldname, op->baseNum); } else { fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ", prefix, prefix, op->name, im0->values->plank->name, im0->values->fieldname, im1->values->plank->name, im1->values->fieldname); fprintf(outfile, "%s_TEMP + %d : 0 )\n", prefix, op->baseNum); } } break; default: assert(0); } } static void doPlankLabelSafely(op) Operator op; { fprintf(outfile, "\tcase %d:\n", op->num); switch (op->arity) { case -1: fprintf(outfile, "\t\treturn 0;\n"); break; case 0: fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name); break; case 1: fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name); break; case 2: fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name); break; default: assert(0); } } static void makePlankState() { fprintf(outfile, "\n"); fprintf(outfile, "int %s_TEMP;\n", prefix); foreachList((ListFn) doPlankLabelMacrosSafely, operators); fprintf(outfile, "\n"); fprintf(outfile, "#ifdef __STDC__\n"); switch (max_arity) { case -1: fprintf(stderr, "ERROR: no terminals in grammar.\n"); exit(1); case 0: fprintf(outfile, "int %s_state(int op) {\n", prefix); fprintf(outfile, "#else\n"); fprintf(outfile, "int %s_state(op) int op; {\n", prefix); break; case 1: fprintf(outfile, "int %s_state(int op, int l) {\n", prefix); fprintf(outfile, "#else\n"); fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix); break; case 2: fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix); fprintf(outfile, "#else\n"); fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix); break; default: assert(0); } fprintf(outfile, "#endif\n"); fprintf(outfile, "\tregister int %s_TEMP;\n", prefix); fprintf(outfile, "#ifndef NDEBUG\n"); fprintf(outfile, "\tswitch (op) {\n"); opsOfArity(2); if (max_arity >= 2) { fprintf(outfile, "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n", prefix, globalMap->count, prefix, prefix); fprintf(outfile, "\t\t/*FALLTHROUGH*/\n"); } opsOfArity(1); if (max_arity > 1) { fprintf(outfile, "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n", prefix, globalMap->count, prefix, prefix); fprintf(outfile, "\t\t/*FALLTHROUGH*/\n"); } opsOfArity(0); fprintf(outfile, "\t\tbreak;\n"); fprintf(outfile, "\t}\n"); fprintf(outfile, "#endif\n"); fprintf(outfile, "\tswitch (op) {\n"); fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n", prefix, prefix); foreachList((ListFn) doPlankLabelSafely, operators); fprintf(outfile, "\t}\n"); fprintf(outfile, "}\n"); } void makePlanks() { List planks; renumber(); makePmaps(); planks = assemblePlanks(); purgePlanks(planks); inToEx(); makePlankRule(); makePlankState(); }