void third(FIELD *def) { if (dump) constr_size = 0; else { to_c("\n/*\n"); to_c(" * \"Microcode\" used to construct messages. It copies all\n"); to_c(" * fields from the construction area to the resulting message."); to_c("\n */\n\n"); to_c("static int construct[] = {\n"); begin_code(); construct(def); constr_size = end_code()+1; to_c(" OP_END\n};\n\n"); } to_c("\n/*\n * \"Microcode\" used to parse messages. It detects the\n"); to_c(" * presence of fields and copies them from the message to the\n"); to_c(" * construction area.\n */\n\n"); to_c("static int parse[] = {\n"); if (dump) { to_dump("typedef struct {\n int level;\n const SYM_NAME *sym;\n"); to_dump(" const char *name;\n"); to_dump("} DUMP_FIELD;\n\n"); to_dump("static DUMP_FIELD dump_fields[] = {\n"); } begin_code(); parser(def,0,0); parser_size = end_code()+1; to_c(" OP_END\n};\n\n"); if (dump) to_dump("};\n\n"); }
void save_state(void) { whitelist_dump(); iplist_dump(); to_dump(); tod_dump(); from_dump(); fromd_dump(); }
void second(FIELD *def) { int i; def->has_required = 0; to_c("\n/*\n"); to_c(" * If a group contains required fields, these are listed in the\n"); to_c(" * following arrays. Each list ends with -1. The variable names\n"); to_c(" * end with the group number.\n */\n\n"); dump_required(def,def,0); find_required(def); to_c("\n/*\n * Various information about groups.\n */\n\n"); to_c("typedef struct {\n int parent;\n int *required;\n"); to_c(" int start;\n int length;\n int offset;\n} GROUP;\n\n"); to_c("static GROUP groups[] = {\n"); if (def->has_required) to_c(" { -1, required_0 },\n"); else to_c(" { -1, NULL },\n"); to_test("static const char *groups[] = {\n"); groups(def,0); to_test(" NULL\n};\n\n"); to_c("};\n\n\n"); to_c("/*\n * Named case selectors only have a limited set of valid\n"); to_c(" * values. They are listed in the following arrays, each followed\n"); to_c(" * by the number of the group it enables.\n */\n\n"); values(def); to_c("\n/*\n * Various information about fields.\n */\n\n"); to_c("typedef struct {\n int parent;\n int pos,size;\n"); to_c(" int *values;\n int actual;\n} FIELD;\n\n"); to_c("static FIELD fields[] = {\n"); fields(def,0); to_c("};\n\n"); to_test("static int *unique[] = {\n"); for (i = 0; i < unique; i++) to_test(" unique_%d,\n",i); to_test(" NULL\n};\n\n"); if (dump) { to_dump("typedef struct {\n unsigned long value;\n"); to_dump(" const char *name;\n} SYM_NAME;\n\n"); symbolic_names(def); } }
static void parser(FIELD *start,int level,int group) { FIELD *walk; TAG *scan; VALUE_LIST *tag; int count,patch_here; BREAK *brk,*tmp_brks,*next; patch_here = 0; /* for gcc */ for (walk = start; walk; walk = walk->next) { if (walk->structure) { parser(walk->my_block,level,group); continue; } if (walk->brk) { code("%s%s\n","OP_IFEND","?"); brk = alloc_t(BREAK); brk->pc = pc-1; brk->next = brks; brks = brk; } if (dump) { if ((!walk->value || walk->value->type != vt_multi) && walk->size) code("%s%d\n","OP_DUMP",walk->seq); if (walk->value || walk->name_list) to_dump(" { %d, dump_sym_%d, \"%s\" },\n",level, walk->name_list ? walk->name_list->id : walk->seq,walk->id); else to_dump(" { %d, NULL, \"%s\" },\n",level,walk->id); } if (!walk->value) { if (walk->var_len != -1) code("%s%d%d%d/* %s */\n","OP_COPYVAR",walk->var_len,walk->pos, walk->size/8,walk->id); else if (*walk->id != '_' || walk->jump || dump) code("%s%d%d%d/* %s */\n","OP_COPY",walk->jump,walk->pos, walk->size,walk->id); } else switch (walk->value->type) { case vt_id: if (*walk->id != '_' || walk->jump || dump) code("%s%d%d%d/* %s */\n","OP_COPY",walk->jump, walk->pos,walk->size,walk->id); break; case vt_multi: code("%s%s/* %s */\n","OP_IFEND","?",walk->id); walk->patch = pc-1; if (dump) code("%s%d\n","OP_DUMP",walk->seq); /* fall through */ case vt_case: if (*walk->id != '_' || dump) code("%s%d%d%d/* %s */\n","OP_COPY",0,walk->pos, walk->size,walk->id); /* don't move */ count = 0; for (scan = walk->value->tags; scan; scan = scan->next) { count++; for (tag = scan->more; tag; tag = tag->next) count++; } code("%s%d%d%d%d/* %s */\n","OP_CASE",walk->jump, walk->pos,walk->size,count,walk->id); for (scan = walk->value->tags; scan; scan = scan->next) { code("%s%d%s\n",scan->deflt ? "-1" : scan->value, scan->group,"?"); scan->patch = pc-1; for (tag = scan->more; tag; tag = tag->next) { code("%s%d%s\n",tag->value,scan->group,"?"); tag->patch = pc-1; } } for (scan = walk->value->tags; scan; scan = scan->next) { patch(scan->patch,pc-scan->patch-1); for (tag = scan->more; tag; tag = tag->next) patch(tag->patch,pc-tag->patch-1); if (!scan->block && scan->abort_id) code("%s%s\n","OP_ABORT",scan->abort_id); parser(scan->block,level+1,scan->group); if (scan->next) { code("%s%s\n","OP_JUMP","?"); scan->patch = pc-1; } } for (scan = walk->value->tags; scan && scan->next; scan = scan->next) patch(scan->patch,pc-scan->patch-1); if (walk->value->type == vt_multi) { code("%s%d\n","OP_JUMP",walk->patch-pc-3); patch(walk->patch,pc-walk->patch-1); } break; case vt_length: code("%s%d%d%d/* %s */\n","OP_BEGIN_LEN",walk->jump, walk->pos,walk->size,walk->id); if (walk->value->recovery) { code("%s%s%d%d\n","OP_BEGIN_REC",walk->value->recovery, group,"?"); patch_here = pc-1; } tmp_brks = brks; if (!walk->value->block && walk->value->abort_id) code("%s%s\n","OP_ABORT",walk->value->abort_id); parser(walk->value->block,level+1,group); if (walk->value->recovery) { code("%s\n","OP_END_REC"); patch(patch_here,pc); } for (brk = brks; brk; brk = next) { next = brk->next; patch(brk->pc,pc-brk->pc-1); free(brk); } brks = tmp_brks; code("%s /* %s */\n","OP_END_LEN",walk->id); break; default: abort(); } } }
int main(int argc,char **argv) { const char *prefix; if (argc == 2 && !strcmp(argv[1],"-d")) debug = 1; if (argc == 2 && !strcmp(argv[1],"-D")) dump = 1; prefix = getenv("PREFIX"); if (!prefix) prefix = dump ? "qd" : "q"; open_files(prefix); to_h("/* THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT ! */\n\n"); to_c("/* THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT ! */\n\n"); to_c("#if HAVE_CONFIG_H\n"); to_c("#include <config.h>\n"); to_c("#endif\n\n"); to_test("/* THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT ! */\n\n"); to_test("#if HAVE_CONFIG_H\n"); to_test("#include <config.h>\n"); to_test("#endif\n\n"); if (dump) { to_dump("/* THIS IS A MACHINE-GENERATED FILE. DO NOT EDIT ! */\n\n"); to_dump("#if HAVE_CONFIG_H\n"); to_dump("#include <config.h>\n"); to_dump("#endif\n\n"); } to_c("/* (optional) user includes go here */\n\n"); to_test("/* (optional) user includes go here */\n\n"); if (dump) to_dump("/* (optional) user includes go here */\n\n"); if (yyparse()) return 1; to_test("\n#ifndef NULL\n#define NULL ((void *) 0)\n#endif\n\n"); if (dump) to_dump("\n#ifndef NULL\n#define NULL ((void *) 0)\n#endif\n\n"); to_h("#ifndef Q_OUT_H\n#define Q_OUT_H\n\n"); to_c("\n#include <stdlib.h>\n#include <stdio.h>\n"); to_c("#include <string.h>\n#include <sys/types.h>\n\n"); to_c("#include \"common.h\"\n#include \"op.h\"\n"); to_c("#include \"%s.out.h\"\n",prefix); to_c("#include \"qlib.h\"\n\n"); to_c("\n\nstatic void q_put(unsigned char *table,int pos,int size," "unsigned long value);\n\n"); first(def); second(def); third(def); to_h("#endif\n"); to_c("\n/*\n * Sorry, this is necessary ...\n */\n\n"); to_c("#include \"qlib.c\"\n"); to_test("\n/*\n * Sorry, this is necessary ...\n */\n\n"); to_test("#include \"qtest.c\"\n"); if (dump) { to_dump("\n/*\n * Sorry, this is necessary ...\n */\n\n"); to_dump("#define DUMP_MODE\n\n"); to_dump("#include \"%s.out.c\"\n",prefix); } close_files(); fprintf(stderr," %d groups, %d fields (%d var-len), construction area is " "%d bytes,\n",group,field,varlen_fields,(offset+7)/8); fprintf(stderr," %d words in constructor, %d words in parser", constr_size,parser_size); if (!dump) fprintf(stderr,".\n"); else fprintf(stderr,",\n %d symbolic names in %d tables.\n",symbols, sym_tables); return 0; }
static void symbolic_names(FIELD *start) { FIELD *walk; NAME *name; TAG *scan; VALUE_LIST *tag; for (walk = start; walk; walk = walk->next) { if (walk->structure) { symbolic_names(walk->my_block); continue; } if (walk->name_list ? walk->name_list->id == -1 : !!walk->value) { if (walk->name_list) { to_dump("static SYM_NAME dump_sym_%d[] = { /* %s */\n", walk->seq,walk->name_list->list_name); sym_tables++; walk->name_list->id = walk->seq; for (name = walk->name_list->list; name; name = name->next) { to_dump(" { %s, \"%s\" },\n",name->value,name->name); symbols++; } } else { to_dump("static SYM_NAME dump_sym_%d[] = {\n",walk->seq); sym_tables++; switch (walk->value->type) { case vt_id: to_dump(" { %s, \"%s\" },\n",walk->value->id, walk->value->id); symbols++; break; case vt_case: case vt_multi: for (scan = walk->value->tags; scan; scan = scan->next) { to_dump(" { %s, \"%s\" },\n",scan->value, scan->value); symbols++; for (tag = scan->more; tag; tag = tag->next) { to_dump(" { %s, \"%s\" },\n",tag->value, tag->value); symbols++; } } break; case vt_length: break; default: abort(); } } to_dump(" { 0, NULL }\n};\n\n"); } if (walk->value) switch (walk->value->type) { case vt_id: break; case vt_case: case vt_multi: for (scan = walk->value->tags; scan; scan = scan->next) symbolic_names(scan->block); break; case vt_length: symbolic_names(walk->value->block); break; default: abort(); } } }