void print_h_code (bool header) { int i; if (header) printf ("extern "); printf ("const g4_bits g4_h_code [2] [64]"); if (header) { printf (";\n"); return; } printf (" =\n"); printf (" {\n"); printf (" {\n"); printf (" /* white */\n"); for (i = 0; i <= 63; i++) emit_code (6, h_code [i][0], i == 63, 1, i); printf (" },\n"); printf (" {\n"); printf (" /* black */\n"); for (i = 0; i <= 63; i++) emit_code (6, h_code [i][1], i == 63, 1, i); printf (" }\n"); printf (" };\n"); }
void print_makeup_code (bool header) { int i; if (header) printf ("extern "); printf ("const g4_bits g4_makeup_code [2] [27]"); if (header) { printf (";\n"); return; } printf (" =\n"); printf (" {\n"); printf (" {\n"); printf (" /* white */\n"); for (i = 0; i <= 26; i++) emit_code (6, makeup_code [i][0], i == 26, 1, (i + 1) * 64); printf (" },\n"); printf (" {\n"); printf (" /* black */\n"); for (i = 0; i <= 26; i++) emit_code (6, makeup_code [i][1], i == 26, 1, (i + 1) * 64); printf (" }\n"); printf (" };\n"); }
int main(int argc, char *argv[]) { char out_filename[256]; if (argc >= 2) { make_out_filename(out_filename, argv[1]); freopen(argv[1], "r", stdin); freopen(out_filename, "w", stdout); } puts("#include <stdio.h>"); puts("#include <stdlib.h>"); puts("#include <string.h>\n"); puts("typedef unsigned char byte;"); puts("static byte *ptr_start, *ptr_end, *ptr;\n"); puts("#define MEM_SIZE ( 32768 )"); puts("#ifdef NOCHECK"); puts("#define CHK(p) ( p )"); puts("#else"); puts("#define CHK(p) ( chk(p) )"); puts("static void chk(byte *p){"); puts(" if(p<ptr_start||ptr_end<=p){"); puts(" fprintf(stderr,\"Error: Memory Out Of Bounds.\\n\");"); puts(" exit(1);"); puts(" }"); puts("}"); puts("#endif\n"); puts("int main(int argc, char *argv[]){"); puts(" int i=1,mem_size=MEM_SIZE;"); puts(" for (; i < argc;){"); puts(" if (strcmp(argv[i], \"-m\") == 0){"); puts(" i++;"); puts(" if (i < argc) mem_size=atoi(argv[i++]);"); puts(" } else i++;"); puts(" }"); puts(" if (mem_size<1) mem_size=1;"); puts(" ptr_start=(byte *)calloc(mem_size, 1);"); puts(" ptr_end=ptr_start+mem_size;"); puts(" ptr=ptr_start;"); puts("/* -- translated code -- */"); emit_code(); while (g_indent_level > 0) { print_code("break;"); --g_indent_level; print_code("}"); fprintf(stderr, "Warning: Incorrect Nesting.\n"); } puts("/* -- end -- */"); puts(" putchar('\\n');"); puts(" free(ptr_start);"); puts(" return 0;"); puts("}\n"); return 0; }
int main(int argc, char * argv[]) { char * opt = argc > 1 ? argv[1] : NULL; make_primes(); make_ff(); if (!opt) emit_code(0); else if (!strcmp(opt, "h") || !strcmp(opt, ".h") || !strcmp(opt, "-h")) emit_code(1); else if (!strcmp(opt, "c") || !strcmp(opt, ".c") || !strcmp(opt, "-c")) emit_code(0); else { fprintf(stderr, "Usage: ffgen [-h|-c]\n"); fprintf(stderr, " -h for header file\n"); fprintf(stderr, " -c for C source file\n"); return 1; } return 0; }
/** * Read text from fp and generate grammer tree ** * @param fp: File pointer to the input file stream */ inline void poxc_parse(FILE * fp) { poxc_lex(fp); for (;;){ if (lex_finished) break; #ifdef __DEBUG__ if (tk_type == TYPE_KEY) debug("LEX[%d]\t%s", tk_type, tk_text); else if (tk_type == TYPE_LABEL) debug("LEX[%d]\t(LABEL)*%d", tk_type, tk_value); else if (tk_type == TYPE_VALUE) debug("LEX[%d]\t(VALUE)*%d", tk_type, tk_value); else debug("LEX[%d]\t(VAR)*%d", tk_type, tk_value); #endif // Instruction if (tk_type == TYPE_KEY){ // Save old STRING char * tt = tk_text; // Get parameter poxc_lex(fp); if (strcmp(tt, "label") == 0) { // Label definition... if (tk_type == TYPE_LABEL){ symtab_set_label(tk_value, current_code); poxc_lex(fp); } else throw(ERR_UNEXPECTED_V); } else { // ...or normal code emit_code(tt); if (tk_type != TYPE_KEY) poxc_lex(fp); } free(tt); } // Unknow? else throw(ERR_UNEXPECTED_V); } }
void print_long_makeup_code (bool header) { int i; if (header) printf ("extern "); printf ("const g4_bits g4_long_makeup_code [12]"); if (header) { printf (";\n"); return; } printf (" =\n"); printf (" {\n"); for (i = 0; i < 12; i++) emit_code (4, long_makeup_code [i], i == 11, 1, i * 64 + 1792); printf (" };\n"); }
void print_v_code (bool header) { int i; if (header) printf ("extern "); printf ("const g4_bits g4_vert_code [7]"); if (header) { printf (";\n"); return; } printf ("=\n"); printf (" {\n"); for (i = 0; i <= 6; i++) emit_code (4, v_code [i], i == 6, 1, i - 3); printf (" };\n"); }
/* Generate C source code for the parser */ void ReportTable(struct lmno *lmnop, int mhflag) { FILE *out, *in; char line[LINESIZE]; int lineno; struct state *stp; struct action *ap; struct rule *rp; struct acttab *pActtab; int i, j, n; int mnTknOfst, mxTknOfst; int mnNtOfst, mxNtOfst; struct axset *ax; // open input template and target output file and advance to first insertion in = tplt_open(lmnop); if(in == 0) return; out = (lmnop->export_c ? file_open(lmnop,".c","w") : file_open(lmnop,".cpp","w") ); if(out == 0) { fclose(in); return; } lineno = 1; tplt_xfer(lmnop->name,in,out,&lineno); // insert user's copyright and license information. copyright_print(out, lmnop, &lineno); tplt_xfer(lmnop->name,in,out,&lineno); /* Generate the action table and its associates: ** ** yy_action[] A single table containing all actions. ** yy_lookahead[] A table containing the lookahead for each entry in ** yy_action. Used to detect hash collisions. ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ /* Compute the actions on all states and count them up */ ax = malloc(sizeof(ax[0])*lmnop->nstate*2); if(ax==0) { fprintf(stderr,"malloc failed\n"); exit(1); } for(i=0; i<lmnop->nstate; i++) { stp = lmnop->sorted[i]; stp->nTknAct = stp->nNtAct = 0; stp->iDflt = lmnop->nstate + lmnop->nrule; stp->iTknOfst = NO_OFFSET; stp->iNtOfst = NO_OFFSET; for(ap=stp->ap; ap; ap=ap->next) { if(compute_action(lmnop,ap)>=0) { if(ap->sp->index<lmnop->nterminal) { stp->nTknAct++; } else if(ap->sp->index<lmnop->nsymbol) { stp->nNtAct++; } else { stp->iDflt = compute_action(lmnop, ap); } } } ax[i*2].stp = stp; ax[i*2].isTkn = 1; ax[i*2].nAction = stp->nTknAct; ax[i*2+1].stp = stp; ax[i*2+1].isTkn = 0; ax[i*2+1].nAction = stp->nNtAct; } mxTknOfst = mnTknOfst = 0; mxNtOfst = mnNtOfst = 0; /* Compute the action table. In order to try to keep the size of the ** action table to a minimum, the heuristic of placing the largest action ** sets first is used. */ qsort(ax, lmnop->nstate*2, sizeof(ax[0]), axset_compare); pActtab = acttab_alloc(); for(i=0; i<lmnop->nstate*2 && ax[i].nAction>0; i++) { stp = ax[i].stp; if(ax[i].isTkn) { for(ap=stp->ap; ap; ap=ap->next) { int action; if(ap->sp->index>=lmnop->nterminal) continue; action = compute_action(lmnop, ap); if(action<0) continue; acttab_action(pActtab, ap->sp->index, action); } stp->iTknOfst = acttab_insert(pActtab); if(stp->iTknOfst<mnTknOfst) mnTknOfst = stp->iTknOfst; if(stp->iTknOfst>mxTknOfst) mxTknOfst = stp->iTknOfst; } else { for(ap=stp->ap; ap; ap=ap->next) { int action; if(ap->sp->index<lmnop->nterminal) continue; if(ap->sp->index==lmnop->nsymbol) continue; action = compute_action(lmnop, ap); if(action<0) continue; acttab_action(pActtab, ap->sp->index, action); } stp->iNtOfst = acttab_insert(pActtab); if(stp->iNtOfst<mnNtOfst) mnNtOfst = stp->iNtOfst; if(stp->iNtOfst>mxNtOfst) mxNtOfst = stp->iNtOfst; } } free(ax); /* Output the yy_action table */ fprintf(out,"static YYACTIONTYPE yy_action[] = {\n"); lineno++; n = acttab_size(pActtab); for(i=j=0; i<n; i++) { int action = acttab_yyaction(pActtab, i); if(action<0) action = lmnop->nsymbol + lmnop->nrule + 2; if(j==0) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", action); if(j==9 || i==n-1) { fprintf(out, "\n"); lineno++; j = 0; } else { j++; } } fprintf(out, "};\n"); lineno++; /* Output the yy_lookahead table */ fprintf(out,"static YYCODETYPE yy_lookahead[] = {\n"); lineno++; for(i=j=0; i<n; i++) { int la = acttab_yylookahead(pActtab, i); if(la<0) la = lmnop->nsymbol; if(j==0) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", la); if(j==9 || i==n-1) { fprintf(out, "\n"); lineno++; j = 0; } else { j++; } } fprintf(out, "};\n"); lineno++; /* Output the yy_shift_ofst[] table */ fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; fprintf(out, "static %s yy_shift_ofst[] = {\n", minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++; n = lmnop->nstate; for(i=j=0; i<n; i++) { int ofst; stp = lmnop->sorted[i]; ofst = stp->iTknOfst; if(ofst==NO_OFFSET) ofst = mnTknOfst - 1; if(j==0) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", ofst); if(j==9 || i==n-1) { fprintf(out, "\n"); lineno++; j = 0; } else { j++; } } fprintf(out, "};\n"); lineno++; /* Output the yy_reduce_ofst[] table */ fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; fprintf(out, "static %s yy_reduce_ofst[] = {\n", minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++; n = lmnop->nstate; for(i=j=0; i<n; i++) { int ofst; stp = lmnop->sorted[i]; ofst = stp->iNtOfst; if(ofst==NO_OFFSET) ofst = mnNtOfst - 1; if(j==0) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", ofst); if(j==9 || i==n-1) { fprintf(out, "\n"); lineno++; j = 0; } else { j++; } } fprintf(out, "};\n"); lineno++; /* Output the default action table */ fprintf(out, "static YYACTIONTYPE yy_default[] = {\n"); lineno++; n = lmnop->nstate; for(i=j=0; i<n; i++) { stp = lmnop->sorted[i]; if(j==0) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", stp->iDflt); if(j==9 || i==n-1) { fprintf(out, "\n"); lineno++; j = 0; } else { j++; } } fprintf(out, "};\n"); lineno++; tplt_xfer(lmnop->name,in,out,&lineno); /* Generate the table of fallback tokens. */ if(lmnop->has_fallback) { for(i=0; i<lmnop->nterminal; i++) { struct symbol *p = lmnop->symbols[i]; if(p->fallback==0) { fprintf(out, " 0, /* %10s => nothing */\n", p->name); } else { fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index, p->name, p->fallback->name); } lineno++; } } tplt_xfer(lmnop->name, in, out, &lineno); /* Generate a table containing the symbolic name of every symbol */ for(i=0; i<lmnop->nsymbol; i++) { sprintf(line,"\"%s\",",lmnop->symbols[i]->name); fprintf(out," %-15s",line); if((i&3)==3) { fprintf(out,"\n"); lineno++; } } if((i&3)!=0) { fprintf(out,"\n"); lineno++; } tplt_xfer(lmnop->name,in,out,&lineno); /* Generate a table containing a text string that describes every ** rule in the rule set of the grammer. This information is used ** when tracing REDUCE actions. */ for(i=0, rp=lmnop->rule; rp; rp=rp->next, i++) { assert(rp->index==i); fprintf(out," /* %3d */ \"%s ->", i, rp->lhs->name); for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name); fprintf(out,"\",\n"); lineno++; } tplt_xfer(lmnop->name,in,out,&lineno); /* Generate code which executes every time a symbol is popped from ** the stack while processing errors or while destroying the parser. ** (In other words, generate the %destructor actions) */ if(lmnop->tokendest) { for(i=0; i<lmnop->nsymbol; i++) { struct symbol *sp = lmnop->symbols[i]; if(sp==0 || sp->type!=TERMINAL) continue; fprintf(out," case %d:\n",sp->index); lineno++; } for(i=0; i<lmnop->nsymbol && lmnop->symbols[i]->type!=TERMINAL; i++) { } if(i<lmnop->nsymbol) { emit_destructor_code(out,lmnop->symbols[i],lmnop,&lineno); fprintf(out," break;\n"); lineno++; } } for(i=0; i<lmnop->nsymbol; i++) { struct symbol *sp = lmnop->symbols[i]; if(sp==0 || sp->type==TERMINAL || sp->destructor==0) continue; fprintf(out," case %d:\n",sp->index); lineno++; /* Combine duplicate destructors into a single case */ for(j=i+1; j<lmnop->nsymbol; j++) { struct symbol *sp2 = lmnop->symbols[j]; if(sp2 && sp2->type!=TERMINAL && sp2->destructor && sp2->dtnum==sp->dtnum && strcmp(sp->destructor,sp2->destructor)==0) { fprintf(out," case %d:\n",sp2->index); lineno++; sp2->destructor = 0; } } emit_destructor_code(out,lmnop->symbols[i],lmnop,&lineno); fprintf(out," break;\n"); lineno++; } if(lmnop->vardest) { struct symbol *dflt_sp = 0; for(i=0; i<lmnop->nsymbol; i++) { struct symbol *sp = lmnop->symbols[i]; if(sp==0 || sp->type==TERMINAL || sp->index<=0 || sp->destructor!=0) continue; fprintf(out," case %d:\n",sp->index); lineno++; dflt_sp = sp; } if(dflt_sp!=0) { emit_destructor_code(out,dflt_sp,lmnop,&lineno); fprintf(out," break;\n"); lineno++; } } tplt_xfer(lmnop->name,in,out,&lineno); /* Generate code which executes whenever the parser stack overflows */ if(lmnop->export_c) { tplt_print(out,lmnop,lmnop->overflow,lmnop->overflowln,&lineno); tplt_xfer(lmnop->name,in,out,&lineno); } /* Generate the table of rule information ** ** Note: This code depends on the fact that rules are number ** sequentually beginning with 0. */ for(rp=lmnop->rule; rp; rp=rp->next) { fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; } tplt_xfer(lmnop->name,in,out,&lineno); /* Generate code which execution during each REDUCE action */ for(rp=lmnop->rule; rp; rp=rp->next) { if(rp->code) translate_code(lmnop, rp); } for(rp=lmnop->rule; rp; rp=rp->next) { struct rule *rp2; if(rp->code==0) continue; fprintf(out," case %d:\n",rp->index); lineno++; for(rp2=rp->next; rp2; rp2=rp2->next) { if(rp2->code==rp->code) { fprintf(out," case %d:\n",rp2->index); lineno++; rp2->code = 0; } } emit_code(out,rp,lmnop,&lineno); fprintf(out," break;\n"); lineno++; } tplt_xfer(lmnop->name,in,out,&lineno); /* Generate code which executes if a parse fails */ tplt_print(out,lmnop,lmnop->failure,lmnop->failureln,&lineno); tplt_xfer(lmnop->name,in,out,&lineno); /* Generate code which executes when a syntax error occurs */ tplt_print(out,lmnop,lmnop->error,lmnop->errorln,&lineno); tplt_xfer(lmnop->name,in,out,&lineno); /* Generate code which executes when the parser accepts its input */ tplt_print(out,lmnop,lmnop->accept,lmnop->acceptln,&lineno); tplt_xfer(lmnop->name,in,out,&lineno); /* Append any addition code the user desires */ tplt_print(out,lmnop,lmnop->extracode,lmnop->extracodeln,&lineno); fclose(in); fclose(out); return; }
int main(int argc, char* argv[]) { // deal with args if (argc < 2) { print_usage(); return 1; } int c; unsigned char ch; bool onlyPrint = false, verbose = false; opterr = 0; while ((c = getopt(argc, argv, ":e:t:" BOUNDS_ARGS "hpv")) != -1) { ch = (unsigned char) c; if (c == 'e') { onEof = EOF_VALUE; eofValue = (unsigned char) atoi(optarg); } else if (c == 't') { int len = atoi(optarg); if (len <= 0) { fprintf(stderr, "err: tape size must be positive integer\n"); return 1; } tapeLength = (size_t) len; #ifndef NO_CHECK_BOUNDS } else if (c == 'b') { check = true; } else if (c == 'c') { check = circular = true; if (infinite) { fprintf(stderr, "err: options 'c', 'f' mutually exclusive\n"); return 1; } } else if (c == 'f') { check = infinite = true; if (circular) { fprintf(stderr, "err: options 'c', 'f' mutually exclusive\n"); return 1; } #endif } else if (c == 'h') { print_usage(); return 0; } else if (c == 'p') { onlyPrint = true; } else if (c == 'v') { verbose = true; } else if (c == '?') { fprintf(stderr, "err: unknown option '%c'\n", optopt); return 1; } else if (c == ':') { fprintf(stderr, "err: option '%c' requires argument\n", optopt); return 1; } } if (optind >= argc) { fprintf(stderr, "err: no file provided\n"); return 1; } // read entire file FILE* f = fopen(argv[optind], "r"); if (!f) { fprintf(stderr, "err: unable to open file '%s'\n", argv[1]); return 1; } size_t i, length = 0, maxLength = 1024, depth = 0, maxDepth = 1, line = 1, col = 0; unsigned char* code = malloc(maxLength * sizeof(char)); if (!code) { fprintf(stderr, "err: failed to allocate file read buffer\n"); fclose(f); return 1; } while ((c = fgetc(f)) != EOF) { ch = (unsigned char) c; if (ch == '\n') { line++; col = 0; } col++; if (ch != '+' && ch != '-' && ch != '<' && ch != '>' && ch != '[' && ch != ']' && ch != '.' && ch != ',') continue; if (ch == '[') { depth++; if (depth > maxDepth) { // overestimate of loop depth b/c later optimizations, should be good enough maxDepth = depth; } } else if (ch == ']') { if (depth == 0) { fprintf(stderr, "err: closing bracket with no opening bracket at line %zu col %zu\n", line, col); fclose(f); free(code); return 1; } depth--; } length++; if (length > maxLength) { maxLength *= 2; unsigned char* newCode = realloc(code, maxLength * sizeof(char)); if (!newCode) { fprintf(stderr, "err: failed to allocate file read buffer\n"); fclose(f); free(code); return 1; } code = newCode; } code[length - 1] = ch; } fclose(f); if (depth != 0) { fprintf(stderr, "err: opening bracket with no closing bracket (need %zu at end)\n", depth); free(code); return 1; } if (verbose) fprintf(stderr, "read %zu bf instructions\n", length); // convert bf into optimized bytecode-like structure size_t instrCt; // true only if cell currently pointed to during execution must be zero (program start, end of loop) bool definiteZero = true; unsigned char deltaInc; int deltaShift; i = instrCt = depth = deltaInc = deltaShift = 0; size_t *stk = malloc(maxDepth * sizeof(size_t)); if (!stk) { fprintf(stderr, "err: failed to allocate stack\n"); free(code); return 1; } // quite a bit more memory that we will probably end up using... // can't easily realloc later without moving ptrs around Code* bytecode = calloc(length + 1, sizeof(Code)); if (!bytecode) { fprintf(stderr, "err: failed to allocate bytecode\n"); free(code); free(stk); return 1; } bf_func bf_getc = onEof == EOF_UNCHANGED ? bf_getc_unc : bf_getc_val; while (i < length) { ch = code[i]; // optimize simple loops that set cell to 0 ([-], [+]) if (!definiteZero && i < length - 2 && ch == '[' && (code[i + 1] == '+' || code[i + 1] == '-') && code[i + 2] == ']') { // definiteZero == true case handled below along with other loops if (deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; instrCt++; } deltaInc = 0; bytecode[instrCt].func = bf_zero; i += 2; instrCt++; definiteZero = true; } else if (ch == '<') { deltaShift--; definiteZero = false; } else if (ch == '>') { deltaShift++; definiteZero = false; } else if (ch == '-') { if (deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; instrCt++; } deltaInc--; definiteZero = false; } else if (ch == '+') { if (deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; instrCt++; } deltaInc++; definiteZero = false; } else if (ch == '[') { bool emitted = false; if (deltaInc || deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; //instrCt++; // don't increment instrction count yet definiteZero = false; emitted = true; } // prune dead code if (definiteZero) { size_t currentDepth = depth; depth++; while (depth > currentDepth) { i++; if (code[i] == '[') depth++; else if (code[i] == ']') depth--; // i now pts to closing bracket, but incremented again at bottom of loop } } else { bytecode[instrCt].func = emitted ? bf_inc_shift_lb : bf_lb; stk[depth++] = instrCt; // now increment ct here instrCt++; } } else if (ch == ']') { bool emitted = false; if (deltaInc || deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; //instrCt++; // similar to above definiteZero = false; emitted = true; } bytecode[instrCt].func = emitted ? bf_inc_shift_rb : definiteZero ? bf_rb_nop : bf_rb; size_t open = stk[--depth]; // point at each other for now, will get changed later bytecode[open].branch = &bytecode[instrCt]; bytecode[instrCt].branch = &bytecode[open]; instrCt++; definiteZero = true; } else if (ch == '.') { if (deltaInc || deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; instrCt++; definiteZero = false; } bytecode[instrCt].func = bf_putc; instrCt++; } else if (ch == ',') { if (deltaInc || deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; instrCt++; } deltaInc = 0; bytecode[instrCt].func = bf_getc; instrCt++; definiteZero = false; } i++; } if (deltaInc || deltaShift) { emit_code(&bytecode[instrCt], deltaInc, deltaShift); deltaInc = deltaShift = 0; instrCt++; } free(code); free(stk); if (onlyPrint) { print_code(stdout, bytecode, instrCt, true); free(bytecode); return 0; } // set next ptrs size_t realCt = 0; for (i = 0; i < instrCt; i++) { // addition loop: left bracket + inc_shift + inc_shift_rb, where the shifts are opposite if (i < instrCt - 2) { if ((bytecode[i].func == bf_lb || bytecode[i].func == bf_inc_shift_lb) && bytecode[i + 1].func == bf_inc_shift && bytecode[i + 2].func == bf_inc_shift_rb) { if (bytecode[i + 1].inc == (unsigned char) -1 && bytecode[i + 1].shift == -bytecode[i + 2].shift) { bytecode[i + 1].func = bf_nop; bytecode[i + 2].func = bf_nop; size_t change; if (bytecode[i].func == bf_inc_shift_lb) { bytecode[i].func = bf_inc_shift; change = i + 1; } else { change = i; } bytecode[change].func = bf_add; bytecode[change].inc = bytecode[i + 2].inc; bytecode[change].shift = bytecode[i + 1].shift; } } } // micro-opt: skip nops if (bytecode[i].func == bf_rb_nop) { (*(bytecode[i].branch - 1)).branch = &bytecode[realCt]; } else if (bytecode[i].func != bf_nop) { if (i != realCt) { memcpy(&bytecode[realCt], &bytecode[i], sizeof(Code)); } if (bytecode[realCt].func == bf_lb || bytecode[realCt].func == bf_inc_shift_lb) { bytecode[realCt].branch->branch = &bytecode[realCt + 1]; } else if (bytecode[realCt].func == bf_rb || bytecode[realCt].func == bf_inc_shift_rb) { (*(bytecode[realCt].branch - 1)).branch = &bytecode[realCt + 1]; } bytecode[realCt].next = &bytecode[realCt + 1]; realCt++; } } // emit last instruction // realCt == number of instructions not counting this last one bytecode[realCt].func = bf_end; // run if (verbose) fprintf(stderr, "translated to %zu bytecode instructions\n", realCt); tape = tapePtr = calloc((size_t) tapeLength, sizeof(unsigned char)); if (!tape) { fprintf(stderr, "err: failed to allocate tape\n"); free(bytecode); return 1; } #ifndef NO_CHECK_BOUNDS tapeEnd = tape + tapeLength; #endif // ip Code* ptr = bytecode; while (ptr) { ptr = ptr->func(ptr); } free(bytecode); free(tape); return 0; }
static int compile_operator(compiletime c) { int operand_count = 0; const char *op = pop_operator(c, &operand_count); if (!strcmp(op, "*")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, multiply_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "**")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, power_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "/")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, divide_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "%")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, modulo_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, assign_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ";")) { } else if (!strcmp(op, "if")) { const char *val1 = pop_operand(c); emit2(c, if_tc, val1); DEBUG printf("emit '%s' %s\n", val1, op); c->level++; } else if (!strcmp(op, "else")) { c->level--; emit1(c, else_tc); c->level++; DEBUG printf("emit %s\n", op); } else if (!strcmp(op, "fi")) { c->level--; emit1(c, fi_tc); DEBUG printf("emit %s\n", op); } else if (!strcmp(op, "!")) { const char *val1 = pop_operand(c); emit2(c, not_tc, val1); DEBUG printf("emit '%s' %s\n", val1, op); } else if (!strcmp(op, "+")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, add_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "-")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, subtract_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, gt_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, geq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "<=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, leq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "<")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, lt_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "&&")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, and_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "||")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, or_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "^^")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, xor_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "&")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, bit_and_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "|")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, bit_or_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "^")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, bit_xor_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "~")) { const char *val1 = pop_operand(c); emit2(c, bit_negate_tc, val1); DEBUG printf("emit %s %s\n", val1, op); } else if (!strcmp(op, "<<")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, shift_left_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">>")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, shift_right_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">>>")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, logical_shift_right_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "==")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, eq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "!=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, neq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "fold-case")) { const char *val1 = pop_operand(c); emit2(c, func_fold_case_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "size")) { const char *val1 = pop_operand(c); emit2(c, func_size_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "print")) { const char *val1 = pop_operand(c); emit2(c, func_print_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "jday")) { const char *val1 = pop_operand(c); emit2(c, func_jday_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "dow")) { const char *val1 = pop_operand(c); emit2(c, func_dow_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "equals")) { emit_code(c, func_eq_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "contains")) { emit_code(c, func_contains_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "begins-with")) { emit_code(c, func_begins_with_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "ends-with")) { emit_code(c, func_ends_with_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "int")) { const char *val1 = pop_operand(c); emit2(c, func_is_int_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "real")) { const char *val1 = pop_operand(c); emit2(c, func_is_real_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "nan")) { const char *val1 = pop_operand(c); emit2(c, func_is_nan_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "string")) { const char *val1 = pop_operand(c); emit2(c, func_is_string_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "(")) { return 1; } else if (!strcmp(op, ")")) { return 1; } else { DEBUG printf("bad operator '%s'\n", op); return 0; } push_operand(c, "_STACK"); return 1; }
static void emit3(compiletime c, typecode tc, const char *v1, const char *v2) { emit_code(c, tc, 2); emit_value(c, v1); emit_value(c, v2); }
static void emit2(compiletime c, typecode tc, const char *v1) { emit_code(c, tc, 1); emit_value(c, v1); }
static void emit1(compiletime c, typecode tc) { emit_code(c, tc, 0); }
static int emit_code(Node * node) { int source; #if 0 unsigned int shift; #endif int target = node->value; switch (node->opcode) { case IDENTITY: break; case NEGATE: source = emit_code(node->parent); printf("\tNEGATE,"); t = -t; #ifdef verbose fprintf(stdout, "%d = 0 - %d\n", target, source); #endif break; case SHIFT_ADD: source = emit_code(node->parent); emit_shift(target - 1, source); #ifdef verbose fprintf(stdout, "%d = %d + 1\n", target, target - 1); #endif printf("\tSHIFT_ADD, %d,", n); t = (t << n) + src; break; case SHIFT_SUB: source = emit_code(node->parent); emit_shift(target + 1, source); #ifdef verbose fprintf(stdout, "%d = %d - 1\n", target, target + 1); #endif printf("\tSHIFT_SUB, %d,",n); t = (t << n) - src; break; case SHIFT_REV: source = emit_code(node->parent); emit_shift(1 - target, source); #ifdef verbose fprintf(stdout, "%d = 1 - %d\n", target, 1 - target); #endif printf("\tSHIFT_REV, %d,",n); t = src - (t << n); break; case FACTOR_ADD: source = emit_code(node->parent); emit_shift(target - source, source); #ifdef verbose fprintf(stdout, "%d = %d + %d\n", target, target - source, source); #endif t = (t << n) + t; printf("\tFACTOR_ADD, %d,",n); break; case FACTOR_SUB: source = emit_code(node->parent); emit_shift(target + source, source); #ifdef verbose fprintf(stdout, "%d = %d - %d\n", target, target + source, source); #endif t = (t << n) - t; printf("\tFACTOR_SUB, %d,",n); break; case FACTOR_REV: source = emit_code(node->parent); emit_shift(source - target, source); #ifdef verbose fprintf(stdout, "%d = %d - %d\n", target, source, source - target); #endif t = t - (t << n); printf("\tFACTOR_REV, %d,",n); break; } return target; }