void handlevardecl(astree node, FILE* outfile){ astree ident; astree type; if (node->first->symbol == TOK_ARRAY){ ident = node->first->last; ident->attrs = ATTR_ARRAY; type = node->first->first; } else { ident = node->first->first; type = node->first; } sym_noderef result = search_sym_table(ident,gident_tbl); if(result && (gblock_stk->top->blocknr == 0 || gblock_stk->top->blocknr == result->blocknr)){ eprintf("redeclared %s at line %d already declared at line %d\n", peek_stringtable(result->stringnode),node->linenr,result->linenr); } else { ident->attrs = ident->attrs | bitlookup(type->symbol) | ATTR_VARIABLE | ATTR_LVALUE; ident->blocknr = gblock_stk->top->blocknr; intern_sym_table(ident,gident_tbl,outfile); } }
int handlefunction(astree node, FILE* outfile){ astree type = node->first; astree ident = node->first->first; astree param = node->first->next->first; bitset_t newattrs = bitlookup(type->symbol); node->attrs = newattrs; cstring funcname = peek_stringtable(ident->lexinfo); sym_noderef lookup = search_sym_table(ident,gident_tbl); if (lookup != NULL){ if (lookup->attributes & ATTR_PROTOTYPE){ //found previous func declaration, it's a prototype if (lookup->attributes == ((newattrs | ATTR_PROTOTYPE))){ if(paramcheck(param,lookup->nextparam,funcname)){ return 1; } } else { print_attributes(stdout,(ATTR_PROTOTYPE + ATTR_BOOL)); eprintf("\n"); print_attributes(stdout,(newattrs|ATTR_PROTOTYPE)); eprintf("\n"); //func declaration does not match prototype's type eprintf( "prototype's type does not match function declaration %s\n", funcname); } } else { //found previous func declaration, it's not a prototype eprintf( "redeclaring function %s at line %d\n", peek_stringtable(ident->lexinfo),ident->linenr-1); eprintf( "(previously declared at line %d)\n",lookup->linenr-1); return 1; } } else { ident->attrs = ATTR_FUNCTION | bitlookup(type->symbol); sym_noderef temp = intern_sym_table(ident,gident_tbl,outfile); push_block(gblock_stk); for(;param != NULL; param = param->next){ param->first->attrs = bitlookup(param->symbol) | ATTR_PARAM; param->first->blocknr = gblock_stk->top->blocknr; temp->nextparam = intern_sym_table(param->first,gident_tbl,outfile); temp = temp->nextparam; } pop_idents(gident_tbl,gblock_stk->top->blocknr); pop_block(gblock_stk); } return 0; }
cstring oiltype(astree node){ bitset_t bits = node->attrs; cstring result = calloc(100,sizeof(char)); if (bits & ATTR_BOOL || bits & ATTR_CHAR){ strcpy(result,"ubyte "); } else if(bits & ATTR_INT) { strcpy(result,"int "); } else if(bits & ATTR_STRING){ strcpy(result,"ubyte *"); } else if(bits & ATTR_TYPEID){ strcpy(result,"struct s_"); sym_noderef typeptr = search_sym_table(node,gident_tbl); strcat(result, peek_stringtable(typeptr->stringnode)); strcat(result," *"); } else if(bits & ATTR_VOID){ strcpy(result,"void "); } if (bits & ATTR_ARRAY){ strcat(result,"*"); } return result; }
void generate_first_pass() { int tok = 0, i = 0; unsigned short temp = 0; int label_pc = -1; while( (tok=yylex()) ) { switch(tok) { case LODD: emit_label_op(12, "LODD", "0000"); break; case STOD: emit_label_op(12, "STOD", "0001"); break; case ADDD: emit_label_op(12, "ADDD", "0010"); break; case SUBD: emit_label_op(12, "SUBD", "0011"); break; case JPOS: emit_label_op(12, "JPOS", "0100"); break; case JZER: emit_label_op(12, "JZER", "0101"); break; case JUMP: emit_label_op(12, "JUMP", "0110"); break; case LOCO: emit_label_op(12, "LOCO", "0111"); break; case LODL: emit_int_op(12, "LODL", "1000"); break; case STOL: emit_int_op(12, "STOL", "1001"); break; case ADDL: emit_int_op(12, "ADDL", "1010"); break; case SUBL: emit_int_op(12, "SUBL", "1011"); break; case JNEG: emit_label_op(12, "JNEG", "1100"); break; case JNZE: emit_label_op(12, "JNZE", "1101"); break; case CALL: emit_label_op(12, "CALL", "1110"); break; case PSHI: emit_fixed_op( 0, "PSHI", "1111000"); break; case POPI: emit_fixed_op( 0, "POPI", "1111001"); break; case PUSH: emit_fixed_op( 0, "PUSH", "1111010"); break; case POP: emit_fixed_op( 0, "POP", "1111011"); break; case RETN: emit_fixed_op( 0, "RETN", "1111100"); break; case SWAP: emit_fixed_op( 0, "SWAP", "1111101"); break; case INSP: emit_int_op( 8, "INSP", "11111100"); break; case DESP: emit_int_op( 8, "DESP", "11111110"); break; case HALT: emit_fixed_op( 0, "HALT", "11111111"); break; case INTEG: str_16(yytext); fprintf(p1,"%d %.16s\n", pc, cstr_16); break; case LABEL: if (label_pc == pc) { /* for < lbx: lby: > */ fprintf(p1,"%d U0000000000000000 %s\n", pc, yytext); break; } search_sym_table(yytext); update_sym_table(yytext); label_pc = pc; pc--; break; case LOC: require_int(12, ".LOC"); if((temp = ((unsigned short)atoi(yytext) )) < pc) { fprintf(stderr,"Bad operand after .LOC is %s, TOO SMALL !\n",yytext); exit(1); } pc = temp - 1; break; case STR: i=1; do { if(*(yytext+i) == '\"') { bstr_16(0); fprintf(p1,"%d %.16s\n", pc, cstr_16); break; } temp = (unsigned short)*(yytext+i++); if(*(yytext+i) != '\"') { temp = (temp | ((unsigned short)*(yytext+i) << 8)); } bstr_16(temp); fprintf(p1,"%d %.16s\n", pc, cstr_16); } while (*(yytext+i++) != '\"' && ++pc); break; case JUNK: fprintf(stderr,"Unrecognized token is %s\n",yytext); exit(26); default: fprintf(stderr,"Default case, unrecoverable error\n"); exit(26); } pc++; } }
int main(int argc, char *argv[]) { int tok, i, dump_tab=0, linum=0; unsigned short temp; // if -s is included on masm command, set up to // dump the symbol table after the binary code if(argc > 1 && (strcmp(argv[1], "-s") == 0)) dump_tab = linum = 1; p1 = fopen("/tmp/passone", "w+"); unlink("/tmp/passone"); while(tok=yylex()){ switch(tok){ case LODD: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0000%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0000000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after LODD is %s on line %d\n",yytext, pc); exit(1); } break; case STOD: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0001%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0001000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after STOD is %s on line %d\n",yytext, pc); exit(1); } break; case ADDD: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0010%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0010000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after ADDD is %s on line %d\n",yytext, pc); exit(1); } break; case SUBD: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0011%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0011000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after SUBD is %s on line %d\n",yytext, pc); exit(1); } break; case JPOS: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0100%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0100000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after JPOS is %s on line %d\n",yytext, pc); exit(1); } break; case JZER: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0101%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0101000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after JZER is %s on line %d\n",yytext, pc); exit(1); } break; case JUMP: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 0110%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0110000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after JUMP is %s on line %d\n",yytext, pc); exit(1); } break; case LOCO: switch(tok=yylex()){ case INTEG: if(yytext[0] == '-'){ fprintf(stderr,"Negative operand after LOCO is %s on line %d, must be positive !\n",yytext, pc); exit(1); } str_12(yytext); fprintf(p1,"%d 0111%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U0111000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after LOCO is %s on line %d\n",yytext, pc); exit(1); } break; case LODL: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after LODL is %s\n",yytext); exit(1); } str_12(yytext); fprintf(p1,"%d 1000%s\n", pc, cstr_12); break; case STOL: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after STOL is %s\n",yytext); exit(1); } str_12(yytext); fprintf(p1,"%d 1001%s\n", pc, cstr_12); break; case ADDL: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after ADDL is %s\n",yytext); exit(1); } str_12(yytext); fprintf(p1,"%d 1010%s\n", pc, cstr_12); break; case SUBL: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after SUBL is %s\n",yytext); exit(1); } str_12(yytext); fprintf(p1,"%d 1011%s\n", pc, cstr_12); break; case JNEG: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 1100%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U1100000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after JNEG is %s on line %d\n",yytext, pc); exit(1); } break; case JNZE: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 1101%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U11010000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after JNZE is %s on line %d\n",yytext, pc); exit(1); } break; case CALL: switch(tok=yylex()){ case INTEG: str_12(yytext); fprintf(p1,"%d 1110%s\n", pc, cstr_12); break; case LABEL: fprintf(p1,"%d U1110000000000000 %s\n", pc, yytext); break; default: fprintf(stderr,"Bad operand after CALL is %s on line %d\n",yytext, pc); exit(1); } break; case PSHI: fprintf(p1,"%d 1111000000000000\n",pc); break; case POPI: fprintf(p1,"%d 1111001000000000\n",pc); break; case PUSH: fprintf(p1,"%d 1111010000000000\n",pc); break; case POP: fprintf(p1,"%d 1111011000000000\n",pc); break; case RETN: fprintf(p1,"%d 1111100000000000\n",pc); break; case SWAP: fprintf(p1,"%d 1111101000000000\n",pc); break; case INSP: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after INSP is %s\n",yytext); exit(1); } str_8(yytext); fprintf(p1,"%d 11111100%s\n", pc, cstr_8); break; case DESP: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after DESP is %s\n",yytext); exit(1); } str_8(yytext); fprintf(p1,"%d 11111110%s\n", pc, cstr_8); break; case HALT: fprintf(p1,"%d 1111111111000000\n",pc); break; // case for MULT case MULT: if((tok=yylex()) != INTEG){ //trips if issue with mult call fprintf(stderr,"Bad operand after MULT is %s\n",yytext); exit(1); } str_6(yytext); //otherwise the bits are written fprintf(p1,"%d 1111111100%s\n", pc, cstr_6); break; //case for RSHIFT case RSHIFT: if((tok=yylex()) != INTEG){ // trips if issues with rshift call fprintf(stderr,"Bad operand after RSHIFT is %s\n",yytext); exit(1); } str_6(yytext); //else bits are written fprintf(p1,"%d 1111111101%s\n", pc, cstr_6); break; case DIV: fprintf(p1,"%d 1111111110000000\n",pc); // case for DIV break; //no error case for div, takes no input from .asm all from stack case INTEG: str_16(yytext); fprintf(p1,"%d %s\n", pc, cstr_16); break; case LABEL: if (label_pc == pc){/* for < lbx: lby: > */ fprintf(p1,"%d U0000000000000000 %s\n", pc, yytext); break; } search_sym_table(yytext); update_sym_table(yytext); label_pc = pc; pc--; break; case LOC: if((tok=yylex()) != INTEG){ fprintf(stderr,"Bad operand after .LOC is %s\n",yytext); exit(1); } if((temp = ((unsigned short)atoi(yytext) )) < pc){ fprintf(stderr,"Bad operand after .LOC is %s, TOO SMALL !\n",yytext); exit(1); } pc = temp - 1; break; case STR: i=1; do{ if(*(yytext+i) == '\"'){ bstr_16(0); fprintf(p1,"%d %s\n", pc, binstr_16); break; } temp = (unsigned short)*(yytext+i++); if(*(yytext+i) != '\"'){ temp = (temp | ((unsigned short)*(yytext+i) << 8)); } bstr_16(temp); fprintf(p1,"%d %s\n", pc, binstr_16); }while(*(yytext+i++) != '\"' && ++pc); break; case JUNK: fprintf(stderr,"Unrecognized token is %s\n",yytext); exit(26); default: fprintf(stderr,"Default case, unrecoverable error\n"); exit(26); } // end while pc++; } // end switch generate_code(linum); if(dump_tab)dump_table(); return; } // end main