%{ /* * gen-sel-parser.y - Bison grammar for the "gen-sel" program. * * Copyright (C) 2004 Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #ifdef HAVE_STRING_H #include #elif defined(HAVE_STRINGS_H) #include #endif #ifdef HAVE_STDLIB_H #include #endif /* * Imports from the lexical analyser. */ extern int yylex(void); extern void yyrestart(FILE *file); #ifdef YYTEXT_POINTER extern char *yytext; #else extern char yytext[]; #endif /* * Report error messages from the parser. */ static void yyerror(char *msg) { puts(msg); } /* * Current file and line number. */ extern char *gensel_filename; extern long gensel_linenum; /* * Instruction type for the "inst" variable. */ static char *gensel_inst_type = "unsigned char *"; static int gensel_new_inst_type = 0; /* * Amount of space to reserve for the primary instruction output. */ static int gensel_reserve_space = 32; static int gensel_reserve_more_space = 128; /* * First register in a stack arrangement. */ static int gensel_first_stack_reg = 8; /* st0 under x86 */ /* * Option values. */ #define GENSEL_OPT_SPILL_BEFORE 0x0001 #define GENSEL_OPT_BINARY 0x0002 #define GENSEL_OPT_UNARY 0x0004 #define GENSEL_OPT_TERNARY 0x0008 #define GENSEL_OPT_STACK 0x0010 #define GENSEL_OPT_UNARY_BRANCH 0x0020 #define GENSEL_OPT_BINARY_BRANCH 0x0040 #define GENSEL_OPT_ONLY 0x0080 #define GENSEL_OPT_MANUAL 0x0100 #define GENSEL_OPT_UNARY_NOTE 0x0200 #define GENSEL_OPT_BINARY_NOTE 0x0400 #define GENSEL_OPT_MORE_SPACE 0x0800 /* * Pattern values. */ #define GENSEL_PATT_END 0 #define GENSEL_PATT_REG 1 #define GENSEL_PATT_LREG 2 #define GENSEL_PATT_FREG 3 #define GENSEL_PATT_IMM 4 #define GENSEL_PATT_IMMZERO 5 #define GENSEL_PATT_IMMS8 6 #define GENSEL_PATT_IMMU8 7 #define GENSEL_PATT_IMMS16 8 #define GENSEL_PATT_IMMU16 9 #define GENSEL_PATT_LOCAL 10 /* * Information about clauses. */ typedef struct gensel_clause *gensel_clause_t; struct gensel_clause { int pattern[8]; char *filename; long linenum; char *code; gensel_clause_t next; }; /* * Free a list of clauses. */ static void gensel_free_clauses(gensel_clause_t clauses) { gensel_clause_t next; while(clauses != 0) { next = clauses->next; free(clauses->code); free(clauses); clauses = next; } } /* * Declare the register variables that are needed for a set of clauses. */ static void gensel_declare_regs(gensel_clause_t clauses, int options) { int have_reg1 = 0; int have_reg2 = 0; int have_reg3 = 0; int have_imm = 0; int have_local = 0; int index; while(clauses != 0) { for(index = 0; clauses->pattern[index] != GENSEL_PATT_END; ++index) { switch(clauses->pattern[index]) { case GENSEL_PATT_REG: case GENSEL_PATT_LREG: case GENSEL_PATT_FREG: { if(index == 0) have_reg1 = 1; else if(index == 1) have_reg2 = 1; else have_reg3 = 1; } break; case GENSEL_PATT_IMMZERO: break; case GENSEL_PATT_IMM: case GENSEL_PATT_IMMS8: case GENSEL_PATT_IMMU8: case GENSEL_PATT_IMMS16: case GENSEL_PATT_IMMU16: { have_imm = 1; } break; case GENSEL_PATT_LOCAL: { have_local = 1; } break; } } clauses = clauses->next; } if(have_reg1) { printf("\tint reg;\n"); } if(have_reg2 && (options & GENSEL_OPT_STACK) == 0) { printf("\tint reg2;\n"); } if(have_reg3 && (options & GENSEL_OPT_STACK) == 0) { printf("\tint reg3;\n"); } if(have_imm) { printf("\tjit_nint imm_value;\n"); } if(have_local) { printf("\tjit_nint local_offset;\n"); } } /* * Output the code within a clause. */ static void gensel_output_clause_code(gensel_clause_t clause) { char *code; int index; /* Output the line number information from the original file */ printf("#line %ld \"%s\"\n", clause->linenum, clause->filename); /* Output the clause code */ printf("\t\t"); code = clause->code; while(*code != '\0') { if(*code == '$' && code[1] >= '1' && code[1] <= '9') { index = code[1] - '1'; switch(clause->pattern[index]) { case GENSEL_PATT_REG: case GENSEL_PATT_LREG: case GENSEL_PATT_FREG: { if(index == 0) printf("_jit_reg_info[reg].cpu_reg"); else if(index == 1) printf("_jit_reg_info[reg2].cpu_reg"); else printf("_jit_reg_info[reg3].cpu_reg"); } break; case GENSEL_PATT_IMM: case GENSEL_PATT_IMMZERO: case GENSEL_PATT_IMMS8: case GENSEL_PATT_IMMU8: case GENSEL_PATT_IMMS16: case GENSEL_PATT_IMMU16: { printf("imm_value"); } break; case GENSEL_PATT_LOCAL: { printf("local_offset"); } break; } code += 2; } else if(*code == '%' && code[1] >= '1' && code[1] <= '9') { index = code[1] - '1'; switch(clause->pattern[index]) { case GENSEL_PATT_REG: case GENSEL_PATT_LREG: case GENSEL_PATT_FREG: { if(index == 0) printf("_jit_reg_info[_jit_reg_info[reg].other_reg].cpu_reg"); else if(index == 1) printf("_jit_reg_info[_jit_reg_info[reg2].other_reg].cpu_reg"); else printf("_jit_reg_info[_jit_reg_info[reg3].other_reg].cpu_reg"); } break; } code += 2; } else if(*code == '\n') { putc(*code, stdout); putc('\t', stdout); ++code; } else { putc(*code, stdout); ++code; } } printf("\n"); } /* * Output a single clause for a rule. */ static void gensel_output_clause(gensel_clause_t clause, int options) { /* Cache the instruction pointer into "inst" */ if(gensel_new_inst_type) { printf("\t\tjit_gen_load_inst_ptr(gen, inst);\n"); } else { printf("\t\tinst = (%s)(gen->posn.ptr);\n", gensel_inst_type); printf("\t\tif(!jit_cache_check_for_n(&(gen->posn), %d))\n", (((options & GENSEL_OPT_MORE_SPACE) == 0) ? gensel_reserve_space : gensel_reserve_more_space)); printf("\t\t{\n"); printf("\t\t\tjit_cache_mark_full(&(gen->posn));\n"); printf("\t\t\treturn;\n"); printf("\t\t}\n"); } /* Output the clause code */ gensel_output_clause_code(clause); /* Copy "inst" back into the generation context */ if(gensel_new_inst_type) { printf("\t\tjit_gen_save_inst_ptr(gen, inst);\n"); } else { printf("\t\tgen->posn.ptr = (unsigned char *)inst;\n"); } } /* * Output the clauses for a rule. */ static void gensel_output_clauses(gensel_clause_t clauses, int options) { const char *arg1; const char *arg2; const char *arg3; const char *arg; const char *reg; const char *flag1; const char *flag2; const char *flag3; const char *flag; int destroy1; int destroy2; int destroy3; int destroy; gensel_clause_t clause; int first, index; int check_index; /* If the clause is manual, then output it as-is */ if((options & GENSEL_OPT_MANUAL) != 0) { gensel_output_clause_code(clauses); return; } /* Determine the location of this instruction's arguments */ if((options & GENSEL_OPT_TERNARY) != 0) { arg1 = "insn->dest"; arg2 = "insn->value1"; arg3 = "insn->value2"; flag1 = "DEST"; flag2 = "VALUE1"; flag3 = "VALUE2"; destroy1 = 0; destroy2 = 0; destroy3 = 0; } else { arg1 = "insn->value1"; arg2 = "insn->value2"; arg3 = "??"; flag1 = "VALUE1"; flag2 = "VALUE2"; flag3 = "??"; if((options & (GENSEL_OPT_BINARY_BRANCH | GENSEL_OPT_UNARY_BRANCH | GENSEL_OPT_BINARY_NOTE | GENSEL_OPT_UNARY_NOTE)) != 0) { destroy1 = 0; } else { destroy1 = 1; } destroy2 = 0; destroy3 = 0; } /* If all of the clauses start with a register, then load the first value into a register before we start checking cases */ check_index = 0; if((options & (GENSEL_OPT_BINARY | GENSEL_OPT_UNARY | GENSEL_OPT_BINARY_BRANCH | GENSEL_OPT_UNARY_BRANCH | GENSEL_OPT_BINARY_NOTE | GENSEL_OPT_UNARY_NOTE)) != 0 && (options & GENSEL_OPT_STACK) == 0) { clause = clauses; while(clause != 0) { if(clause->pattern[0] != GENSEL_PATT_REG && clause->pattern[0] != GENSEL_PATT_LREG && clause->pattern[0] != GENSEL_PATT_FREG) { break; } clause = clause->next; } if(!clause) { printf("\treg = _jit_regs_load_value(gen, %s, %d, ", arg1, destroy1); printf("(insn->flags & (JIT_INSN_%s_NEXT_USE | " "JIT_INSN_%s_LIVE)));\n", flag1, flag1); check_index = 1; } } /* Output the clause checking and dispatching code */ clause = clauses; first = 1; while(clause != 0) { if(clause->next) { if(first) printf("\tif("); else printf("\telse if("); for(index = check_index; clause->pattern[index]; ++index) { if(index == 0) arg = arg1; else if(index == 1) arg = arg2; else arg = arg3; switch(clause->pattern[index]) { case GENSEL_PATT_REG: case GENSEL_PATT_LREG: case GENSEL_PATT_FREG: { printf("%s->in_register", arg); } break; case GENSEL_PATT_IMM: { printf("%s->is_constant", arg); } break; case GENSEL_PATT_IMMZERO: { printf("%s->is_nint_constant && ", arg); printf("%s->address == 0", arg); } break; case GENSEL_PATT_IMMS8: { printf("%s->is_nint_constant && ", arg); printf("%s->address >= -128 && ", arg); printf("%s->address <= 127", arg); } break; case GENSEL_PATT_IMMU8: { printf("%s->is_nint_constant && ", arg); printf("%s->address >= 0 && ", arg); printf("%s->address <= 255", arg); } break; case GENSEL_PATT_IMMS16: { printf("%s->is_nint_constant && ", arg); printf("%s->address >= -32768 && ", arg); printf("%s->address <= 32767", arg); } break; case GENSEL_PATT_IMMU16: { printf("%s->is_nint_constant && ", arg); printf("%s->address >= 0 && ", arg); printf("%s->address <= 65535", arg); } break; case GENSEL_PATT_LOCAL: { printf("%s->in_frame && !(%s->in_register)", arg, arg); } break; } if(clause->pattern[index + 1]) { printf(" && "); } } printf(")\n\t{\n"); } else if(first) { printf("\t{\n"); } else { printf("\telse\n\t{\n"); } if((options & GENSEL_OPT_STACK) == 0 || clause->next) { for(index = check_index; clause->pattern[index]; ++index) { if(index == 0) { arg = arg1; reg = "reg"; flag = flag1; destroy = destroy1; } else if(index == 1) { arg = arg2; reg = "reg2"; flag = flag2; destroy = destroy2; } else { arg = arg3; reg = "reg3"; flag = flag3; destroy = destroy3; } switch(clause->pattern[index]) { case GENSEL_PATT_REG: case GENSEL_PATT_LREG: case GENSEL_PATT_FREG: { printf("\t\t%s = _jit_regs_load_value(gen, %s, %d, ", reg, arg, destroy); printf("(insn->flags & (JIT_INSN_%s_NEXT_USE | " "JIT_INSN_%s_LIVE)));\n", flag, flag); } break; case GENSEL_PATT_IMMZERO: break; case GENSEL_PATT_IMM: case GENSEL_PATT_IMMS8: case GENSEL_PATT_IMMU8: case GENSEL_PATT_IMMS16: case GENSEL_PATT_IMMU16: { printf("\t\timm_value = %s->address;\n", arg); } break; case GENSEL_PATT_LOCAL: { printf("\t\tlocal_offset = %s->frame_offset;\n", arg); } break; } } } else { if((options & GENSEL_OPT_ONLY) != 0) { printf("\t\tif(!_jit_regs_is_top(gen, insn->value1) ||\n"); printf("\t\t _jit_regs_num_used(gen, %d) != 1)\n", gensel_first_stack_reg); printf("\t\t{\n"); printf("\t\t\t_jit_regs_spill_all(gen);\n"); printf("\t\t}\n"); } if((options & GENSEL_OPT_TERNARY) != 0) { printf("\t\treg = _jit_regs_load_to_top_three\n"); printf("\t\t\t(gen, insn->dest, insn->value1, insn->value2,\n"); printf("\t\t\t\t(insn->flags & (JIT_INSN_DEST_NEXT_USE | " "JIT_INSN_DEST_LIVE)),\n"); printf("\t\t\t\t(insn->flags & (JIT_INSN_VALUE1_NEXT_USE | " "JIT_INSN_VALUE1_LIVE)),\n"); printf("\t\t\t\t(insn->flags & (JIT_INSN_VALUE2_NEXT_USE | " "JIT_INSN_VALUE2_LIVE)), " "%d);\n", gensel_first_stack_reg); } else if((options & (GENSEL_OPT_BINARY | GENSEL_OPT_BINARY_BRANCH)) != 0) { printf("\t\treg = _jit_regs_load_to_top_two\n"); printf("\t\t\t(gen, insn->value1, insn->value2,\n"); printf("\t\t\t\t(insn->flags & (JIT_INSN_VALUE1_NEXT_USE | " "JIT_INSN_VALUE1_LIVE)),\n"); printf("\t\t\t\t(insn->flags & (JIT_INSN_VALUE2_NEXT_USE | " "JIT_INSN_VALUE2_LIVE)), " "%d);\n", gensel_first_stack_reg); } else if((options & (GENSEL_OPT_UNARY | GENSEL_OPT_UNARY_BRANCH | GENSEL_OPT_UNARY_NOTE)) != 0) { printf("\t\treg = _jit_regs_load_to_top\n"); printf("\t\t\t(gen, insn->value1,\n"); printf("\t\t\t\t(insn->flags & (JIT_INSN_VALUE1_NEXT_USE | " "JIT_INSN_VALUE1_LIVE)), " "%d);\n", gensel_first_stack_reg); } } if((options & (GENSEL_OPT_BINARY_BRANCH | GENSEL_OPT_UNARY_BRANCH)) != 0) { /* Spill all other registers back to their original positions */ printf("\t\t_jit_regs_spill_all(gen);\n"); } gensel_output_clause(clause, options); printf("\t}\n"); first = 0; clause = clause->next; } } /* * List of opcodes that are supported by the input rules. */ static char **supported = 0; static char **supported_options = 0; static int num_supported = 0; /* * Add an opcode to the supported list. */ static void gensel_add_supported(char *name, char *option) { supported = (char **)realloc (supported, (num_supported + 1) * sizeof(char *)); if(!supported) { exit(1); } supported[num_supported] = name; supported_options = (char **)realloc (supported_options, (num_supported + 1) * sizeof(char *)); if(!supported_options) { exit(1); } supported_options[num_supported++] = option; } /* * Output the list of supported opcodes. */ static void gensel_output_supported(void) { int index; for(index = 0; index < num_supported; ++index) { if(supported_options[index]) { if(supported_options[index][0] == '!') { printf("#ifndef %s\n", supported_options[index] + 1); } else { printf("#ifdef %s\n", supported_options[index]); } printf("case %s:\n", supported[index]); printf("#endif\n"); } else { printf("case %s:\n", supported[index]); } } printf("\treturn 1;\n\n"); } %} /* * Define the structure of yylval. */ %union { char *name; struct { char *filename; long linenum; char *block; } code; int options; struct { int elem[8]; int size; } pattern; struct { struct gensel_clause *head; struct gensel_clause *tail; } clauses; } /* * Primitive lexical tokens and keywords. */ %token IDENTIFIER "an identifier" %token CODE_BLOCK "a code block" %token K_PTR "`->'" %token K_REG "word register" %token K_LREG "long register" %token K_FREG "float register" %token K_IMM "immediate value" %token K_IMMZERO "immediate zero value" %token K_IMMS8 "immediate signed 8-bit value" %token K_IMMU8 "immediate unsigned 8-bit value" %token K_IMMS16 "immediate signed 16-bit value" %token K_IMMU16 "immediate unsigned 16-bit value" %token K_LOCAL "local variable" %token K_SPILL_BEFORE "`spill_before'" %token K_BINARY "`binary'" %token K_UNARY "`unary'" %token K_UNARY_BRANCH "`unary_branch'" %token K_BINARY_BRANCH "`binary_branch'" %token K_UNARY_NOTE "`unary_note'" %token K_BINARY_NOTE "`binary_note'" %token K_TERNARY "`ternary'" %token K_STACK "`stack'" %token K_ONLY "`only'" %token K_MORE_SPACE "`more_space'" %token K_MANUAL "`manual'" %token K_INST_TYPE "`%inst_type'" /* * Define the yylval types of the various non-terminals. */ %type IDENTIFIER IfClause IdentifierList %type CODE_BLOCK %type Options OptionList Option PatternElement %type Clauses Clause %type Pattern Pattern2 %expect 0 %start Start %% Start : /* empty */ | Rules ; Rules : Rule | Rules Rule ; Rule : IdentifierList IfClause ':' Options Clauses { if($2) { if(($2)[0] == '!') { printf("#ifndef %s\n\n", $2 + 1); } else { printf("#ifdef %s\n\n", $2); } } printf("case %s:\n{\n", $1); if(($4 & GENSEL_OPT_MANUAL) == 0) { printf("\t%s inst;\n", gensel_inst_type); } gensel_declare_regs($5.head, $4); if(($4 & GENSEL_OPT_SPILL_BEFORE) != 0) { printf("\t_jit_regs_spill_all(gen);\n"); } gensel_output_clauses($5.head, $4); if(($4 & (GENSEL_OPT_BINARY | GENSEL_OPT_UNARY)) != 0) { printf("\tif((insn->flags & JIT_INSN_DEST_NEXT_USE) != 0)\n"); printf("\t{\n"); printf("\t\t_jit_regs_set_value(gen, reg, insn->dest, 0);\n"); printf("\t}\n"); printf("\telse\n"); printf("\t{\n"); printf("\t\tint other_reg;\n"); printf("\t\tif(gen->contents[reg].is_long_start)\n"); printf("\t\t{\n"); printf("\t\t\tother_reg = _jit_reg_info[reg].other_reg;\n"); printf("\t\t}\n"); printf("\t\telse\n"); printf("\t\t{\n"); printf("\t\t\tother_reg = -1;\n"); printf("\t\t}\n"); printf("\t\t_jit_gen_spill_reg(gen, reg, other_reg, insn->dest);\n"); printf("\t\tif(insn->dest->has_global_register)\n"); printf("\t\t\tinsn->dest->in_global_register = 1;\n"); printf("\t\telse\n"); printf("\t\t\tinsn->dest->in_frame = 1;\n"); printf("\t\t_jit_regs_free_reg(gen, reg, 1);\n"); printf("\t}\n"); } printf("}\nbreak;\n\n"); if($2) { printf("#endif /* %s */\n\n", $2); } gensel_free_clauses($5.head); gensel_add_supported($1, $2); } | K_INST_TYPE IDENTIFIER { gensel_inst_type = $2; gensel_new_inst_type = 1; } ; IdentifierList : IDENTIFIER { $$ = $1; } | IdentifierList ',' IDENTIFIER { char *result = (char *)malloc(strlen($1) + strlen($3) + 16); if(!result) { exit(1); } strcpy(result, $1); strcat(result, ":\ncase "); strcat(result, $3); free($1); free($3); $$ = result; } ; IfClause : /* empty */ { $$ = 0; } | '(' IDENTIFIER ')' { $$ = $2; } ; Options : /* empty */ { $$ = 0; } | OptionList { $$ = $1; } ; OptionList : Option { $$ = $1; } | OptionList ',' Option { $$ = $1 | $3; } ; Option : K_SPILL_BEFORE { $$ = GENSEL_OPT_SPILL_BEFORE; } | K_BINARY { $$ = GENSEL_OPT_BINARY; } | K_UNARY { $$ = GENSEL_OPT_UNARY; } | K_UNARY_BRANCH { $$ = GENSEL_OPT_UNARY_BRANCH; } | K_BINARY_BRANCH { $$ = GENSEL_OPT_BINARY_BRANCH; } | K_UNARY_NOTE { $$ = GENSEL_OPT_UNARY_NOTE; } | K_BINARY_NOTE { $$ = GENSEL_OPT_BINARY_NOTE; } | K_TERNARY { $$ = GENSEL_OPT_TERNARY; } | K_STACK { $$ = GENSEL_OPT_STACK; } | K_ONLY { $$ = GENSEL_OPT_ONLY; } | K_MORE_SPACE { $$ = GENSEL_OPT_MORE_SPACE; } | K_MANUAL { $$ = GENSEL_OPT_MANUAL; } ; Clauses : Clause { $$ = $1; } | Clauses Clause { $1.tail->next = $2.head; $$.head = $1.head; $$.tail = $2.tail; } ; Clause : '[' Pattern ']' K_PTR CODE_BLOCK { gensel_clause_t clause; int index; clause = (gensel_clause_t)malloc(sizeof(struct gensel_clause)); if(!clause) { exit(1); } for(index = 0; index < 8; ++index) { clause->pattern[index] = $2.elem[index]; } clause->filename = $5.filename; clause->linenum = $5.linenum; clause->code = $5.block; clause->next = 0; $$.head = clause; $$.tail = clause; } ; Pattern : /* empty */ { $$.elem[0] = GENSEL_PATT_END; $$.size = 0; } | Pattern2 { $$ = $1; } ; Pattern2 : PatternElement { $$.elem[0] = $1; $$.elem[1] = GENSEL_PATT_END; $$.size = 1; } | Pattern2 ',' PatternElement { $$.elem[$1.size] = $3; $$.elem[$1.size + 1] = GENSEL_PATT_END; $$.size = $1.size + 1; } ; PatternElement : K_REG { $$ = GENSEL_PATT_REG; } | K_LREG { $$ = GENSEL_PATT_LREG; } | K_FREG { $$ = GENSEL_PATT_FREG; } | K_IMM { $$ = GENSEL_PATT_IMM; } | K_IMMZERO { $$ = GENSEL_PATT_IMMZERO; } | K_IMMS8 { $$ = GENSEL_PATT_IMMS8; } | K_IMMU8 { $$ = GENSEL_PATT_IMMU8; } | K_IMMS16 { $$ = GENSEL_PATT_IMMS16; } | K_IMMU16 { $$ = GENSEL_PATT_IMMU16; } | K_LOCAL { $$ = GENSEL_PATT_LOCAL; } ; %% #define COPYRIGHT_MSG \ " * Copyright (C) 2004 Southern Storm Software, Pty Ltd.\n" \ " *\n" \ " * This program is free software; you can redistribute it and/or modify\n" \ " * it under the terms of the GNU General Public License as published by\n" \ " * the Free Software Foundation; either version 2 of the License, or\n" \ " * (at your option) any later version.\n" \ " *\n" \ " * This program is distributed in the hope that it will be useful,\n" \ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \ " * GNU General Public License for more details.\n" \ " *\n" \ " * You should have received a copy of the GNU General Public License\n" \ " * along with this program; if not, write to the Free Software\n" \ " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" int main(int argc, char *argv[]) { FILE *file; if(argc != 2) { fprintf(stderr, "Usage: %s input.sel >output.slc\n", argv[0]); return 1; } file = fopen(argv[1], "r"); if(!file) { perror(argv[1]); return 1; } printf("/%c Automatically generated from %s - DO NOT EDIT %c/\n", '*', argv[1], '*'); printf("/%c\n%s%c/\n\n", '*', COPYRIGHT_MSG, '*'); printf("#if defined(JIT_INCLUDE_RULES)\n\n"); gensel_filename = argv[1]; gensel_linenum = 1; yyrestart(file); if(yyparse()) { fclose(file); return 1; } fclose(file); printf("#elif defined(JIT_INCLUDE_SUPPORTED)\n\n"); gensel_output_supported(); printf("#endif\n"); return 0; }