static void swstmt(int loop, int lab, int lev) { Tree e; struct swtch sw; Code head, tail; t = gettok(); expect('('); definept(NULL); e = expr(')'); if (!isint(e->type)) { error("illegal type `%t' in switch expression\n", e->type); e = retype(e, inttype); } e = cast(e, promote(e->type)); if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op) && e->kids[0]->u.sym->type == e->type && !isvolatile(e->kids[0]->u.sym->type)) { sw.sym = e->kids[0]->u.sym; walk(NULL, 0, 0); } else { sw.sym = genident(REGISTER, e->type, level); addlocal(sw.sym); walk(asgn(sw.sym, e), 0, 0); } head = code(Switch); sw.lab = lab; sw.deflab = NULL; sw.ncases = 0; sw.size = SWSIZE; sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC); sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC); refinc /= 10.0; statement(loop, &sw, lev); if (sw.deflab == NULL) { sw.deflab = findlabel(lab); definelab(lab); if (sw.ncases == 0) warning("switch statement with no cases\n"); } if (findlabel(lab + 1)->ref) definelab(lab + 1); tail = codelist; codelist = head->prev; codelist->next = head->prev = NULL; if (sw.ncases > 0) swgen(&sw); branch(lab); head->next->prev = codelist; codelist->next = head->next; codelist = tail; }
void branch(int lab) { Code cp; Symbol p = findlabel(lab); assert(lab); walk(NULL, 0, 0); code(Label)->u.forest = jump(lab); for (cp = codelist->prev; cp->kind < Label; ) cp = cp->prev; while ( cp->kind == Label && cp->u.forest->op == LABEL+V && !equal(cp->u.forest->syms[0], p)) { equatelab(cp->u.forest->syms[0], p); assert(cp->next); assert(cp->prev); cp->prev->next = cp->next; cp->next->prev = cp->prev; cp = cp->prev; while (cp->kind < Label) cp = cp->prev; } if (cp->kind == Jump || cp->kind == Switch) { p->ref--; codelist->prev->next = NULL; codelist = codelist->prev; } else { codelist->kind = Jump; if (cp->kind == Label && cp->u.forest->op == LABEL+V && equal(cp->u.forest->syms[0], p)) warning("source code specifies an infinite loop"); } }
Node jump(int lab) { Symbol p = findlabel(lab); p->ref++; return newnode(JUMP+V, newnode(ADDRG+ttob(voidptype), NULL, NULL, p), NULL, NULL); }
static void caselabel(Swtch swp, long val, int lab) { int k; if (swp->ncases >= swp->size) { long *vals = swp->values; Symbol *labs = swp->labels; swp->size *= 2; swp->values = newarray(swp->size, sizeof *swp->values, FUNC); swp->labels = newarray(swp->size, sizeof *swp->labels, FUNC); for (k = 0; k < swp->ncases; k++) { swp->values[k] = vals[k]; swp->labels[k] = labs[k]; } } k = swp->ncases; for ( ; k > 0 && swp->values[k-1] >= val; k--) { swp->values[k] = swp->values[k-1]; swp->labels[k] = swp->labels[k-1]; } if (k < swp->ncases && swp->values[k] == val) error("duplicate case label `%d'\n", val); swp->values[k] = val; swp->labels[k] = findlabel(lab); ++swp->ncases; if (Aflag >= 2 && swp->ncases == 258) warning("more than 257 cases in a switch\n"); }
void Function::setconnections(LabelGenerator* l) { UUID id = l->getid(); blocks.push_back(new CInstructionsContainer(id)); blocks.back()->push_back( new FakeExitBlock ); blocks.back()->push_back( new Unc_jump("Fake Exit Block", -3) ); list<CInstructionsContainer*>::iterator i = blocks.begin(); while ( i != blocks.end() ) { if ( (*i)->onlylabel() ) { list<CInstructionsContainer*>::iterator j = i; ++i; (*i)->push_front( (*j)->front() ); blocks.remove( (*j) ); } else ++i; } i = blocks.begin(); while ( i != blocks.end()) { if ( !(*i)->empty() ) { int lab = (*i)->back()->geti(); if ( lab != -1 && (!(*i)->back()->islabel() )) { CInstructionsContainer* succ; succ = findlabel( lab ); if (succ != NULL ) { (*i)->succpush_back( succ ); succ->predpush_back( *i ); } } if ( !(*i)->back()->isuncjmp() && !(*i)->back()->isexit() && !(*i)->front()->isexit()) { list<CInstructionsContainer*>::iterator j = i; ++i; if ( !(*i)->back()->isexit() ) { (*i)->predpush_back( (*j) ); (*j)->succpush_back( *i ); } }else ++i; } else ++i; } }
static void forstmt(int lab, Swtch swp, int lev) { int once = 0; Tree e1 = NULL, e2 = NULL, e3 = NULL; Coordinate pt2, pt3; t = gettok(); expect('('); definept(NULL); if (kind[t] == ID) e1 = texpr(expr0, ';', FUNC); else expect(';'); walk(e1, 0, 0); pt2 = src; refinc *= 10.0; if (kind[t] == ID) e2 = texpr(conditional, ';', FUNC); else expect(';'); pt3 = src; if (kind[t] == ID) e3 = texpr(expr0, ')', FUNC); else { static char stop[] = { IF, ID, '}', 0 }; test(')', stop); } if (e2) { once = foldcond(e1, e2); if (!once) branch(lab + 3); } definelab(lab); statement(lab, swp, lev); definelab(lab + 1); definept(&pt3); if (e3) walk(e3, 0, 0); if (e2) { if (!once) definelab(lab + 3); definept(&pt2); walk(e2, lab, 0); } else { definept(&pt2); branch(lab); } if (findlabel(lab + 2)->ref) definelab(lab + 2); }
/* ** export pending gotos to outer level, to check them against ** outer labels; if the block being exited has upvalues, and ** the goto exits the scope of any variable (which can be the ** upvalue), close those variables being exited. */ static void movegotosout (FuncState *fs, BlockCnt *bl) { int i = bl->firstgoto; Labellist *gl = &fs->ls->dyd->gt; /* correct pending gotos to current block and try to close it with visible labels */ while (i < gl->n) { Labeldesc *gt = &gl->arr[i]; if (gt->nactvar > bl->nactvar) { if (bl->upval) luaK_patchclose(fs, gt->pc, bl->nactvar); gt->nactvar = bl->nactvar; } if (!findlabel(fs->ls, i)) i++; /* move to next one */ } }
static void ifstmt(int lab, int loop, Swtch swp, int lev) { t = gettok(); expect('('); definept(NULL); walk(conditional(')'), 0, lab); refinc /= 2.0; statement(loop, swp, lev); if (t == ELSE) { branch(lab + 1); t = gettok(); definelab(lab); statement(loop, swp, lev); if (findlabel(lab + 1)->ref) definelab(lab + 1); } else definelab(lab); }
void changepc(char *line, int *pc) { int i; int j; i = 0; j = 0; if (findlabel(line) == 1) { while (line[i] != ' ' && line[i] != '\0') i++; if (line[i] == 0) return ; i++; } while (my_instructcmp(&line[i], op_tab[j].mnemonique, ' ') == 0 && j < 16) j++; if (my_instructcmp(&line[i], op_tab[j].mnemonique, ' ') == 0) return ; adress(j, &line[i], pc); }
void definelab(int lab) { Code cp; Symbol p = findlabel(lab); assert(lab); walk(NULL, 0, 0); code(Label)->u.forest = newnode(LABEL+V, NULL, NULL, p); for (cp = codelist->prev; cp->kind <= Label; ) cp = cp->prev; while ( cp->kind == Jump && cp->u.forest->kids[0] && specific(cp->u.forest->kids[0]->op) == ADDRG+P && cp->u.forest->kids[0]->syms[0] == p) { assert(cp->u.forest->kids[0]->syms[0]->u.l.label == lab); p->ref--; assert(cp->next); assert(cp->prev); cp->prev->next = cp->next; cp->next->prev = cp->prev; cp = cp->prev; while (cp->kind <= Label) cp = cp->prev; } }
static int number(char *s, char *e) { object *l; if (*s == '*') return 0; if (*s == '(') return number(s+1, e-1); if (s < e) l = findlabel(s, e); else return 1; if (!l) { if (label_highest_byte == 0) return 1; return 0; } if (l->l.r.l.rel) return 0; if (l->l.valued == 0) return 0; if (l->l.r.l.xref < 0) return 0; if (l->l.valued == EQUF) return 0; if (l->l.valued & 128) return 0; return 1; }
void statement(int loop, Swtch swp, int lev) { float ref = refinc; if (Aflag >= 2 && lev == 15) warning("more than 15 levels of nested statements\n"); switch (t) { case IF: ifstmt(genlabel(2), loop, swp, lev + 1); break; case WHILE: whilestmt(genlabel(3), swp, lev + 1); break; case DO: dostmt(genlabel(3), swp, lev + 1); expect(';'); break; case FOR: forstmt(genlabel(4), swp, lev + 1); break; case BREAK: walk(NULL, 0, 0); definept(NULL); if (swp && swp->lab > loop) branch(swp->lab + 1); else if (loop) branch(loop + 2); else error("illegal break statement\n"); t = gettok(); expect(';'); break; case CONTINUE: walk(NULL, 0, 0); definept(NULL); if (loop) branch(loop + 1); else error("illegal continue statement\n"); t = gettok(); expect(';'); break; case SWITCH: swstmt(loop, genlabel(2), lev + 1); break; case CASE: { int lab = genlabel(1); if (swp == NULL) error("illegal case label\n"); definelab(lab); while (t == CASE) { static char stop[] = { IF, ID, 0 }; Tree p; t = gettok(); p = constexpr(0); if (generic(p->op) == CNST && isint(p->type)) { if (swp) { needconst++; p = cast(p, swp->sym->type); if (p->type->op == UNSIGNED) p->u.v.i = extend(p->u.v.u, p->type); needconst--; caselabel(swp, p->u.v.i, lab); } } else error("case label must be a constant integer expression\n"); test(':', stop); } statement(loop, swp, lev); } break; case DEFAULT: if (swp == NULL) error("illegal default label\n"); else if (swp->deflab) error("extra default label\n"); else { swp->deflab = findlabel(swp->lab); definelab(swp->deflab->u.l.label); } t = gettok(); expect(':'); statement(loop, swp, lev); break; case RETURN: { Type rty = freturn(cfunc->type); t = gettok(); definept(NULL); if (t != ';') if (rty == voidtype) { error("extraneous return value\n"); expr(0); retcode(NULL); } else retcode(expr(0)); else { if (rty != voidtype) warning("missing return value\n"); retcode(NULL); } branch(cfunc->u.f.label); } expect(';'); break; case '{': compound(loop, swp, lev + 1); break; case ';': definept(NULL); t = gettok(); break; case GOTO: walk(NULL, 0, 0); definept(NULL); t = gettok(); if (t == ID) { Symbol p = lookup(token, stmtlabs); if (p == NULL) { p = install(token, &stmtlabs, 0, FUNC); p->scope = LABELS; p->u.l.label = genlabel(1); p->src = src; } use(p, src); branch(p->u.l.label); t = gettok(); } else error("missing label in goto\n"); expect(';'); break; case ID: if (getchr() == ':') { stmtlabel(); statement(loop, swp, lev); break; } default: definept(NULL); if (kind[t] != ID) { error("unrecognized statement\n"); t = gettok(); } else { Tree e = expr0(0); listnodes(e, 0, 0); if (nodecount == 0 || nodecount > 200) walk(NULL, 0, 0); else if (glevel) walk(NULL, 0, 0); deallocate(STMT); } expect(';'); break; } if (kind[t] != IF && kind[t] != ID && t != '}' && t != EOI) { static char stop[] = { IF, ID, '}', 0 }; error("illegal statement termination\n"); skipto(0, stop); } refinc = ref; }
static void calcfirstset(grammar *g, dfa *d) { int i, j; state *s; arc *a; int nsyms; int *sym; int nbits; static bitset dummy; bitset result; int type; dfa *d1; label *l0; if (Py_DebugFlag) printf("Calculate FIRST set for '%s'\n", d->d_name); if (dummy == NULL) dummy = newbitset(1); if (d->d_first == dummy) { fprintf(stderr, "Left-recursion for '%s'\n", d->d_name); return; } if (d->d_first != NULL) { fprintf(stderr, "Re-calculating FIRST set for '%s' ???\n", d->d_name); } d->d_first = dummy; l0 = g->g_ll.ll_label; nbits = g->g_ll.ll_nlabels; result = newbitset(nbits); sym = (int *)PyObject_MALLOC(sizeof(int)); if (sym == NULL) Py_FatalError("no mem for new sym in calcfirstset"); nsyms = 1; sym[0] = findlabel(&g->g_ll, d->d_type, (char *)NULL); s = &d->d_state[d->d_initial]; for (i = 0; i < s->s_narcs; i++) { a = &s->s_arc[i]; for (j = 0; j < nsyms; j++) { if (sym[j] == a->a_lbl) break; } if (j >= nsyms) { /* New label */ sym = (int *)PyObject_REALLOC(sym, sizeof(int) * (nsyms + 1)); if (sym == NULL) Py_FatalError( "no mem to resize sym in calcfirstset"); sym[nsyms++] = a->a_lbl; type = l0[a->a_lbl].lb_type; if (ISNONTERMINAL(type)) { d1 = PyGrammar_FindDFA(g, type); if (d1->d_first == dummy) { fprintf(stderr, "Left-recursion below '%s'\n", d->d_name); } else { if (d1->d_first == NULL) calcfirstset(g, d1); mergebitset(result, d1->d_first, nbits); } } else if (ISTERMINAL(type)) { addbit(result, a->a_lbl); } } } d->d_first = result; if (Py_DebugFlag) { printf("FIRST set for '%s': {", d->d_name); for (i = 0; i < nbits; i++) { if (testbit(result, i)) printf(" %s", PyGrammar_LabelRepr(&l0[i])); } printf(" }\n"); } PyObject_FREE(sym); }
/* Execute a block. There can be a number of return values from this routine. * NORMAL indicates a normal termination * BROKEN indicates a break -- if the caller is a breakable loop, * terminate it, otherwise pass the break upwards * CONTINUED indicates a continue -- if the caller is a continuable loop, * continue, else pass the continue upwards * Any other return code is considered a pointer to a string which is * a label somewhere -- if this label is present in the block, * goto it, otherwise pass it up. Note that this prevents jumping * into a loop, which is good. * * Note that here is where we expand variables, ``, and globs for * controls. * * The 'num' argument is used by break n and continue n. */ static char * doblock(struct control *bl, int *num) { struct control *ch, *cn = NULL; wordlist *wl, *wltmp; char *i, *wlword; int nn; nn = *num + 1; /*CDHW this is a guess... CDHW*/ switch (bl->co_type) { case CO_WHILE: if (!bl->co_children) { fprintf(cp_err, "Warning: Executing empty 'while' block.\n"); fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n"); } while (bl->co_cond && cp_istrue(bl->co_cond)) { if (!bl->co_children) cp_periodic(); /*CDHW*/ for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); switch (*i) { case NORMAL: break; case BROKEN: /* Break. */ if (nn < 2) { return (NORMAL_STR); } else { *num = nn - 1; return (BROKEN_STR); } case CONTINUED: /* Continue. */ if (nn < 2) { cn = NULL; break; } else { *num = nn - 1; return (CONTINUED_STR); } default: cn = findlabel(i, bl->co_children); if (!cn) return (i); } } } break; case CO_DOWHILE: do { for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); switch (*i) { case NORMAL: break; case BROKEN: /* Break. */ if (nn < 2) { return (NORMAL_STR); } else { *num = nn - 1; return (BROKEN_STR); } case CONTINUED: /* Continue. */ if (nn < 2) { cn = NULL; break; } else { *num = nn - 1; return (CONTINUED_STR); } default: cn = findlabel(i, bl->co_children); if (!cn) return (i); } } } while (bl->co_cond && cp_istrue(bl->co_cond)); break; case CO_REPEAT: if (!bl->co_children) { fprintf(cp_err, "Warning: Executing empty 'repeat' block.\n"); fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n"); } if (!bl->co_timestodo) bl->co_timestodo = bl->co_numtimes; /*bl->co_numtimes: total repeat count bl->co_numtimes = -1: repeat forever bl->co_timestodo: remaining repeats*/ while ((bl->co_timestodo > 0) || (bl->co_timestodo == -1)) { if (!bl->co_children) cp_periodic(); /*CDHW*/ if (bl->co_timestodo != -1) bl->co_timestodo--; /* loop through all stements inside rpeat ... end */ for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); switch (*i) { case NORMAL: break; case BROKEN: /* Break. */ /* before leaving repeat loop set remaining timestodo to 0 */ bl->co_timestodo = 0; if (nn < 2) { return (NORMAL_STR); } else { *num = nn - 1; return (BROKEN_STR); } case CONTINUED: /* Continue. */ if (nn < 2) { cn = NULL; break; } else { /* before leaving repeat loop set remaining timestodo to 0 */ bl->co_timestodo = 0; *num = nn - 1; return (CONTINUED_STR); } default: cn = findlabel(i, bl->co_children); if (!cn) { /* no label found inside repeat loop: before leaving loop set remaining timestodo to 0 */ bl->co_timestodo = 0; return (i); } } } } break; case CO_IF: if (bl->co_cond && cp_istrue(bl->co_cond)) { for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); if (*i > 2) { cn = findlabel(i, bl->co_children); if (!cn) return (i); else tfree(i); } else if (*i != NORMAL) { *num = nn; return (i); } } } else { for (ch = bl->co_elseblock; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); if (*i > 2) { cn = findlabel(i, bl->co_elseblock); if (!cn) return (i); } else if (*i != NORMAL) { *num = nn; return (i); } } } break; case CO_FOREACH: wltmp = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(bl->co_text)))); for (wl = wltmp; wl; wl = wl->wl_next) { cp_vset(bl->co_foreachvar, CP_STRING, wl->wl_word); for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); switch (*i) { case NORMAL: break; case BROKEN: /* Break. */ if (nn < 2) { wl_free(wltmp); return (NORMAL_STR); } else { *num = nn - 1; wl_free(wltmp); return (BROKEN_STR); } case CONTINUED: /* Continue. */ if (nn < 2) { cn = NULL; break; } else { *num = nn - 1; wl_free(wltmp); return (CONTINUED_STR); } default: cn = findlabel(i, bl->co_children); if (!cn) { wl_free(wltmp); return (i); } } } } wl_free(wltmp); break; case CO_BREAK: if (bl->co_numtimes > 0) { *num = bl->co_numtimes; return (BROKEN_STR); } else { fprintf(cp_err, "Warning: break %d a no-op\n", bl->co_numtimes); return (NORMAL_STR); } case CO_CONTINUE: if (bl->co_numtimes > 0) { *num = bl->co_numtimes; return (CONTINUED_STR); } else { fprintf(cp_err, "Warning: continue %d a no-op\n", bl->co_numtimes); return (NORMAL_STR); } case CO_GOTO: wl = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(bl->co_text)))); wlword = wl->wl_word; wl->wl_word = NULL; wl_free(wl); return (wlword); case CO_LABEL: /* Do nothing. */ cp_periodic(); /*CDHW needed to avoid lock-ups when loop contains only a label CDHW*/ break; case CO_STATEMENT: docommand(wl_copy(bl->co_text)); break; case CO_UNFILLED: /* There was probably an error here... */ fprintf(cp_err, "Warning: ignoring previous error\n"); break; default: fprintf(cp_err, "doblock: Internal Error: bad block type %d\n", bl->co_type); return (NORMAL_STR); } return (NORMAL_STR); }