/** * "switch" statement */ void doswitch(void) { WHILE ws; WHILE *ptr; ws.symbol_idx = local_table_index; ws.stack_pointer = stkp; ws.type = WSSWITCH; ws.case_test = swstp; ws.body_tab = getlabel (); ws.incr_def = ws.while_exit = getlabel (); addwhile (&ws); gen_immediate (); print_label (ws.body_tab); newline (); gen_push (HL_REG); needbrack ("("); expression (YES); needbrack (")"); stkp = stkp + INTSIZE; // '?case' will adjust the stack gen_jump_case (); statement (NO); ptr = readswitch (); gen_jump (ptr->while_exit); dumpsw (ptr); generate_label (ptr->while_exit); local_table_index = ptr->symbol_idx; stkp = gen_modify_stack (ptr->stack_pointer); swstp = ptr->case_test; delwhile (); }
/** * "switch" statement */ doswitch() { loop_t loop; loop_t *ptr; loop.symbol_idx = local_table_index; loop.stack_pointer = stkp; loop.type = WSSWITCH; loop.test_label = swstp; loop.body_label = getlabel (); loop.cont_label = loop.exit_label = getlabel (); addloop (&loop); gen_immediate_a (); print_label (loop.body_label); newline (); gen_push (); needbrack ("("); expression (YES); needbrack (")"); stkp = stkp + INTSIZE; // '?case' will adjust the stack gen_jump_case (); statement (NO); ptr = readswitch (); gen_jump (ptr->exit_label); dumpsw (ptr); generate_label (ptr->exit_label); local_table_index = ptr->symbol_idx; stkp = gen_modify_stack (ptr->stack_pointer); swstp = ptr->test_label; delloop (); }
/** * perform a function call * called from "hier11", this routine will either call the named * function, or if the supplied ptr is zero, will call the contents * of HL * @param ptr name of the function */ void callfunction(char *ptr) { int nargs; nargs = 0; blanks (); if (ptr == 0) gen_push (HL_REG); while (!streq (line + lptr, ")")) { if (endst ()) break; expression (NO); if (ptr == 0) gen_swap_stack (); gen_push (HL_REG); nargs = nargs + INTSIZE; if (!match (",")) break; } needbrack (")"); if (aflag) gnargs(nargs / INTSIZE); if (ptr) gen_call (ptr); else callstk (); stkp = gen_modify_stack (stkp + nargs); }
/** * "break" statement */ dobreak() { loop_t *ptr; if ((ptr = readloop ()) == 0) return; gen_modify_stack (ptr->stack_pointer); gen_jump (ptr->exit_label); }
/** * "break" statement */ void dobreak(void) { WHILE *ptr; if ((ptr = readwhile ()) == 0) return; gen_modify_stack (ptr->stack_pointer); gen_jump (ptr->while_exit); }
/** * "continue" statement */ void docont(void) { WHILE *ptr; //int *ptr; if ((ptr = findwhile ()) == 0) return; gen_modify_stack (ptr->stack_pointer); if (ptr->type == WSFOR) gen_jump (ptr->incr_def); else gen_jump (ptr->case_test); }
/** * "continue" statement */ docont() { loop_t *ptr; if ((ptr = findloop ()) == 0) return; gen_modify_stack (ptr->stack_pointer); if (ptr->type == WSFOR) gen_jump (ptr->cont_label); else gen_jump (ptr->test_label); }
/** * "if" statement */ void doif(void) { int fstkp, flab1, flab2; int flev; flev = local_table_index; fstkp = stkp; flab1 = getlabel (); test (flab1, FALSE); statement (NO); stkp = gen_modify_stack (fstkp); local_table_index = flev; if (!amatch ("else", 4)) { generate_label (flab1); return; } gen_jump (flab2 = getlabel ()); generate_label (flab1); statement (NO); stkp = gen_modify_stack (fstkp); local_table_index = flev; generate_label (flab2); }
/** * "while" statement */ dowhile() { loop_t loop; loop.symbol_idx = local_table_index; loop.stack_pointer = stkp; loop.type = WSWHILE; loop.test_label = getlabel (); loop.exit_label = getlabel (); addloop (&loop); generate_label (loop.test_label); test (loop.exit_label, FALSE); statement (NO); gen_jump (loop.test_label); generate_label (loop.exit_label); local_table_index = loop.symbol_idx; stkp = gen_modify_stack (loop.stack_pointer); delloop (); }
/** * "while" statement */ void dowhile(void) { WHILE ws; ws.symbol_idx = local_table_index; ws.stack_pointer = stkp; ws.type = WSWHILE; ws.case_test = getlabel (); ws.while_exit = getlabel (); addwhile (&ws); generate_label (ws.case_test); test (ws.while_exit, FALSE); statement (NO); gen_jump (ws.case_test); generate_label (ws.while_exit); local_table_index = ws.symbol_idx; stkp = gen_modify_stack (ws.stack_pointer); delwhile (); }
/** * "for" statement */ void dofor(void) { WHILE ws; WHILE *pws; ws.symbol_idx = local_table_index; ws.stack_pointer = stkp; ws.type = WSFOR; ws.case_test = getlabel (); ws.incr_def = getlabel (); ws.body_tab = getlabel (); ws.while_exit = getlabel (); addwhile (&ws); pws = readwhile (); needbrack ("("); if (!match (";")) { expression (YES); need_semicolon (); } generate_label (pws->case_test); if (!match (";")) { expression (YES); gen_test_jump (pws->body_tab, TRUE); gen_jump (pws->while_exit); need_semicolon (); } else pws->case_test = pws->body_tab; generate_label (pws->incr_def); if (!match (")")) { expression (YES); needbrack (")"); gen_jump (pws->case_test); } else pws->incr_def = pws->case_test; generate_label (pws->body_tab); statement (NO); gen_jump (pws->incr_def); generate_label (pws->while_exit); local_table_index = pws->symbol_idx; stkp = gen_modify_stack (pws->stack_pointer); delwhile (); }
/** * "for" statement */ dofor() { loop_t loop; loop_t *p; loop.symbol_idx = local_table_index; loop.stack_pointer = stkp; loop.type = WSFOR; loop.test_label = getlabel (); loop.cont_label = getlabel (); loop.body_label = getlabel (); loop.exit_label = getlabel (); addloop (&loop); p = readloop (); needbrack ("("); if (!match (";")) { expression (YES); need_semicolon (); } generate_label (p->test_label); if (!match (";")) { expression (YES); gen_test_jump (p->body_label, TRUE); gen_jump (p->exit_label); need_semicolon (); } else p->test_label = p->body_label; generate_label (p->cont_label); if (!match (")")) { expression (YES); needbrack (")"); gen_jump (p->test_label); } else p->cont_label = p->test_label; generate_label (p->body_label); statement (NO); gen_jump (p->cont_label); generate_label (p->exit_label); local_table_index = p->symbol_idx; stkp = gen_modify_stack (p->stack_pointer); delloop (); }
/** * "do" statement */ dodo() { loop_t loop; loop.symbol_idx = local_table_index; loop.stack_pointer = stkp; loop.type = WSDO; loop.body_label = getlabel (); loop.test_label = getlabel (); loop.exit_label = getlabel (); addloop (&loop); generate_label (loop.body_label); statement (NO); if (!match ("while")) { error ("missing while"); return; } generate_label (loop.test_label); test (loop.body_label, TRUE); generate_label (loop.exit_label); local_table_index = loop.symbol_idx; stkp = gen_modify_stack (loop.stack_pointer); delloop (); }
/** * "do" statement */ void dodo(void) { WHILE ws; ws.symbol_idx = local_table_index; ws.stack_pointer = stkp; ws.type = WSDO; ws.body_tab = getlabel (); ws.case_test = getlabel (); ws.while_exit = getlabel (); addwhile (&ws); generate_label (ws.body_tab); statement (NO); if (!match ("while")) { error ("missing while"); return; } generate_label (ws.case_test); test (ws.body_tab, TRUE); generate_label (ws.while_exit); local_table_index = ws.symbol_idx; stkp = gen_modify_stack (ws.stack_pointer); delwhile (); }
/** * declare local variables * works just like "declglb", but modifies machine stack and adds * symbol table entry with appropriate stack offset to find it again * @param typ * @param stclass * @param otag index of tag in tag_table */ void declare_local(int typ, int stclass, int otag) { int k, j; char sname[NAMESIZE]; FOREVER { FOREVER { if (endst()) return; if (match("*")) j = POINTER; else j = VARIABLE; if (!symname(sname)) illname(); if (-1 != find_locale(sname)) multidef (sname); if (match("[")) { k = needsub(); if (k) { j = ARRAY; if (typ & CINT) { k = k * INTSIZE; } else if (typ == STRUCT) { k = k * tag_table[otag].size; } } else { j = POINTER; k = INTSIZE; } } else { if (j == POINTER) { k = INTSIZE; } else { switch (typ) { case CCHAR: case UCHAR: k = 1; break; case STRUCT: k = tag_table[otag].size; break; default: k = INTSIZE; } } } if (stclass == LSTATIC) { add_local(sname, j, typ, k, LSTATIC); break; } if (stclass == REGISTER) { int r = gen_register(j, k, typ); if (r != -1) { add_local(sname, j, typ, r, REGISTER); break; } } if (match("=")) { gen_modify_stack(stkp); expression(0); gen_push(0); } else stkp = gen_defer_modify_stack(stkp - k); add_local(sname, j, typ, stkp, AUTO); break; } if (!match(",")) return; } }
void newfunc_typed(int storage, char *n, int type) { int idx; SYMBOL *symbol; char an[NAMESIZE]; fexitlab = getlabel(); if ((idx = find_global(n)) > -1) { symbol = &symbol_table[idx]; if (symbol->identity != FUNCTION) multidef(n); } else { /* extern implies global scope */ idx = add_global(n, FUNCTION, CINT, 0, storage == EXTERN ? PUBLIC : storage); symbol = &symbol_table[idx]; } local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; argstk = 0; // ANSI style argument declaration if (doAnsiArguments()) { if (storage == EXTERN) { need_semicolon(); return; } /* No body .. just a definition */ if (match(";")) return; } else { // K&R style argument declaration while (!match(")")) { if (symname(an)) { if (find_locale(an) > -1) multidef(an); else { /* FIXME: struct */ add_local(an, 0, 0, argstk, AUTO); argstk = argstk + INTSIZE; } } else { error("illegal argument name"); junk(); } blanks(); if (!streq(line + lptr, ")")) { if (!match(",")) error("expected comma"); } if (endst()) break; } if (storage == EXTERN) { need_semicolon(); return; } /* No body .. just a definition */ if (match(";")) return; stkp = 0; argtop = argstk; while (argstk) { if ((type = get_type()) != -1) { notvoid(type); getarg(type); need_semicolon(); } else { error("wrong number args"); break; } } } if (symbol->offset == FUNCTION) multidef(n); symbol->offset = FUNCTION; output_string(n); output_label_terminator(); newline(); gen_prologue(); statement(YES); print_label(fexitlab); output_label_terminator(); newline(); gen_epilogue(); gen_modify_stack(0); gen_ret(); stkp = 0; local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; }
/** * begin a function * called from "parse", this routine tries to make a function out * of what follows * modified version. p.l. woods */ newfunc() { char n[NAMESIZE]; int idx, type; fexitlab = getlabel(); if (!symname(n)) { error("illegal function or declaration"); kill(); return; } if (idx = findglb(n)) { if (symbol_table[idx].identity != FUNCTION) multidef(n); else if (symbol_table[idx].offset == FUNCTION) multidef(n); else symbol_table[idx].offset = FUNCTION; } else add_global(n, FUNCTION, CINT, FUNCTION, PUBLIC); if (!match("(")) error("missing open paren"); output_string(n); output_label_terminator(); newline(); local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; argstk = 0; // ANSI style argument declaration if (doAnsiArguments() == 0) { // K&R style argument declaration while (!match(")")) { if (symname(n)) { if (findloc(n)) multidef(n); else { add_local(n, 0, 0, argstk, AUTO); argstk = argstk + INTSIZE; } } else { error("illegal argument name"); junk(); } blanks(); if (!streq(line + lptr, ")")) { if (!match(",")) error("expected comma"); } if (endst()) break; } stkp = 0; argtop = argstk; while (argstk) { if (type = get_type()) { getarg(type); need_semicolon(); } else { error("wrong number args"); break; } } } statement(YES); print_label(fexitlab); output_label_terminator(); newline(); gen_modify_stack(0); gen_ret(); stkp = 0; local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; }
/* FIXME - interaction with register needs thought */ int gen_defer_modify_stack(int newstkp) { return gen_modify_stack(newstkp); }