📄 parse.c
字号:
if (line_start()) { if (opts & BR_FUNCTION) singleindent(funccloseindent); else singleindent(closebraceindent); } output("}"); i = 1; cmt = findcomment(curcomments, CMT_ONEND, serial); if (!(opts & BR_REPEAT) && commentvisible(cmt)) { out_spaces(bracecommentindent, commentoverindent, commentlen(cmt), 0); output("\001"); outcomment(cmt); i = 0; } if (i) { outspnl((opts & BR_REPEAT) || ((opts & BR_THENPART) && (braceelseline & 1) == 0 && !findcomment(curcomments, -1, serial))); } } if (gotcomments) { outcontext->comments = curcomments; curcomments = savecurcmt; }}/* Should have a way to convert GOTO's to the end of the function to RETURN's *//* Convert "_RETV = foo;" at end of function to "return foo" */Static int checkreturns(spp, nearret)Stmt **spp;int nearret;{ Stmt *sp; Expr *rvar, *ex; Meaning *mp; int spnearret, spnextreturn; int result = 0; if (debug>2) { fprintf(outf, "checkreturns on:\n"); dumpstmt(*spp, 5); } while ((sp = *spp)) { spnextreturn = (sp->next && sp->next->kind == SK_RETURN && sp->next->exp1 && isretvar(sp->next->exp1) == curctx->cbase); spnearret = (nearret && !sp->next) || spnextreturn; result = 0; switch (sp->kind) { case SK_ASSIGN: ex = sp->exp1; if (ex->kind == EK_ASSIGN || structuredfunc(ex)) { rvar = ex->args[0]; mp = isretvar(rvar); if (mp == curctx->cbase && spnearret) { if (ex->kind == EK_ASSIGN) { if (mp->kind == MK_VARPARAM) { ex = makeexpr_comma(ex, makeexpr_var(mp)); } else { ex = grabarg(ex, 1); mp->refcount--; } } sp->exp1 = ex; sp->kind = SK_RETURN; if (spnextreturn) { mp->refcount--; sp->next = sp->next->next; } result = 1; } } break; case SK_RETURN: case SK_GOTO: result = 1; break; case SK_IF: result = checkreturns(&sp->stm1, spnearret) & /* NOT && */ checkreturns(&sp->stm2, spnearret); break; case SK_TRY: (void) checkreturns(&sp->stm1, 0); (void) checkreturns(&sp->stm2, spnearret); break; /* should handle CASE statements as well */ default: (void) checkreturns(&sp->stm1, 0); (void) checkreturns(&sp->stm2, 0); break; } spp = &sp->next; } return result;}/* Replace all occurrences of one expression with another expression */Expr *replaceexprexpr(ex, oldex, newex, keeptype)Expr *ex, *oldex, *newex;int keeptype;{ int i; Type *type; for (i = 0; i < ex->nargs; i++) ex->args[i] = replaceexprexpr(ex->args[i], oldex, newex, keeptype); if (exprsame(ex, oldex, 2)) { if (ex->val.type->kind == TK_POINTER && ex->val.type->basetype == oldex->val.type) { freeexpr(ex); return makeexpr_addr(copyexpr(newex)); } else if (oldex->val.type->kind == TK_POINTER && oldex->val.type->basetype == ex->val.type) { freeexpr(ex); return makeexpr_hat(copyexpr(newex), 0); } else { type = ex->val.type; freeexpr(ex); ex = copyexpr(newex); if (keeptype) ex->val.type = type; return ex; } } return resimplify(ex);}void replaceexpr(sp, oldex, newex)Stmt *sp;Expr *oldex, *newex;{ while (sp) { replaceexpr(sp->stm1, oldex, newex); replaceexpr(sp->stm2, oldex, newex); if (sp->exp1) sp->exp1 = replaceexprexpr(sp->exp1, oldex, newex, 1); if (sp->exp2) sp->exp2 = replaceexprexpr(sp->exp2, oldex, newex, 1); if (sp->exp3) sp->exp3 = replaceexprexpr(sp->exp3, oldex, newex, 1); sp = sp->next; }}Stmt *mixassignments(sp, mp)Stmt *sp;Meaning *mp;{ if (!sp) return NULL; sp->next = mixassignments(sp->next, mp); if (sp->next && sp->kind == SK_ASSIGN && sp->exp1->kind == EK_ASSIGN && sp->exp1->args[0]->kind == EK_VAR && (!mp || mp == (Meaning *)sp->exp1->args[0]->val.i) && ord_type(sp->exp1->args[0]->val.type)->kind == TK_INTEGER && nodependencies(sp->exp1->args[1], 0) && sp->next->kind == SK_ASSIGN && sp->next->exp1->kind == EK_ASSIGN && (exprsame(sp->exp1->args[0], sp->next->exp1->args[0], 1) || (mp && mp->istemporary)) && exproccurs(sp->next->exp1->args[1], sp->exp1->args[0]) == 1) { sp->next->exp1->args[1] = replaceexprexpr(sp->next->exp1->args[1], sp->exp1->args[0], sp->exp1->args[1], 1); if (mp && mp->istemporary) canceltempvar(mp); return sp->next; } return sp;}/* Do various simple (sometimes necessary) massages on the statements */Static Stmt bogusreturn = { SK_RETURN, NULL, NULL, NULL, NULL, NULL, NULL };Static int isescape(ex)Expr *ex;{ if (ex->kind == EK_BICALL && (!strcmp(ex->val.s, name_ESCAPE) || !strcmp(ex->val.s, name_ESCIO) || !strcmp(ex->val.s, name_ESCIO2) || !strcmp(ex->val.s, name_OUTMEM) || !strcmp(ex->val.s, name_CASECHECK) || !strcmp(ex->val.s, name_NILCHECK) || !strcmp(ex->val.s, "_exit") || !strcmp(ex->val.s, "exit"))) return 1; if (ex->kind == EK_CAST) return isescape(ex->args[0]); return 0;}/* check if a block can never exit by falling off the end */Static int deadendblock(sp, breaks)Stmt *sp;int breaks;{ if (!sp) return 0; while (sp->next) sp = sp->next; return (sp->kind == SK_RETURN || sp->kind == SK_CASECHECK || ((sp->kind == SK_GOTO || sp->kind == SK_BREAK || sp->kind == SK_CONTINUE) && breaks) || (sp->kind == SK_IF && deadendblock(sp->stm1, breaks) && deadendblock(sp->stm2, breaks)) || (sp->kind == SK_ASSIGN && isescape(sp->exp1)));}int expr_is_bool(ex, want)Expr *ex;int want;{ long val; if (ex->val.type == tp_boolean && isconstexpr(ex, &val)) return (val == want); return 0;}/* Returns 1 if c1 implies c2, 0 otherwise *//* If not1 is true, then checks if (!c1) implies c2; similarly for not2 *//* Identities used: c1 -> (c2a && c2b) <=> (c1 -> c2a) && (c1 -> c2b) c1 -> (c2a || c2b) <=> (c1 -> c2a) || (c1 -> c2b) (c1a && c1b) -> c2 <=> (c1a -> c2) || (c1b -> c2) (c1a || c1b) -> c2 <=> (c1a -> c2) && (c1b -> c2) (!c1) -> (!c2) <=> c2 -> c1 (a == b) -> c2(b) <=> c2(a) !(c1 && c2) <=> (!c1) || (!c2) !(c1 || c2) <=> (!c1) && (!c2)*//* This could be smarter about, e.g., (a>5) -> (a>0) */int implies(c1, c2, not1, not2)Expr *c1, *c2;int not1, not2;{ Expr *ex; int i; if (c1->kind == EK_EQ && c1->args[0]->val.type == tp_boolean) { if (checkconst(c1->args[0], 1)) { /* things like "flag = true" */ return implies(c1->args[1], c2, not1, not2); } else if (checkconst(c1->args[1], 1)) { return implies(c1->args[0], c2, not1, not2); } else if (checkconst(c1->args[0], 0)) { return implies(c1->args[1], c2, !not1, not2); } else if (checkconst(c1->args[1], 0)) { return implies(c1->args[0], c2, !not1, not2); } } if (c2->kind == EK_EQ && c2->args[0]->val.type == tp_boolean) { if (checkconst(c2->args[0], 1)) { return implies(c1, c2->args[1], not1, not2); } else if (checkconst(c2->args[1], 1)) { return implies(c1, c2->args[0], not1, not2); } else if (checkconst(c2->args[0], 0)) { return implies(c1, c2->args[1], not1, !not2); } else if (checkconst(c2->args[1], 0)) { return implies(c1, c2->args[0], not1, !not2); } } switch (c2->kind) { case EK_AND: if (not2) /* c1 -> (!c2a || !c2b) */ return (implies(c1, c2->args[0], not1, 1) || implies(c1, c2->args[1], not1, 1)); else /* c1 -> (c2a && c2b) */ return (implies(c1, c2->args[0], not1, 0) && implies(c1, c2->args[1], not1, 0)); case EK_OR: if (not2) /* c1 -> (!c2a && !c2b) */ return (implies(c1, c2->args[0], not1, 1) && implies(c1, c2->args[1], not1, 1)); else /* c1 -> (c2a || c2b) */ return (implies(c1, c2->args[0], not1, 0) || implies(c1, c2->args[1], not1, 0)); case EK_NOT: /* c1 -> (!c2) */ return (implies(c1, c2->args[0], not1, !not2)); case EK_CONST: if ((c2->val.i != 0) != not2) /* c1 -> true */ return 1; break; default: break; } switch (c1->kind) { case EK_AND: if (not1) /* (!c1a || !c1b) -> c2 */ return (implies(c1->args[0], c2, 1, not2) && implies(c1->args[1], c2, 1, not2)); else /* (c1a && c1b) -> c2 */ return (implies(c1->args[0], c2, 0, not2) || implies(c1->args[1], c2, 0, not2)); case EK_OR: if (not1) /* (!c1a && !c1b) -> c2 */ return (implies(c1->args[0], c2, 1, not2) || implies(c1->args[1], c2, 1, not2)); else /* (c1a || c1b) -> c2 */ return (implies(c1->args[0], c2, 0, not2) && implies(c1->args[1], c2, 0, not2)); case EK_NOT: /* (!c1) -> c2 */ return (implies(c1->args[0], c2, !not1, not2)); case EK_CONST: if ((c1->val.i != 0) == not1) /* false -> c2 */ return 1; break; case EK_EQ: /* (a=b) -> c2 */ case EK_ASSIGN: /* (a:=b) -> c2 */ case EK_NE: /* (a<>b) -> c2 */ if ((c1->kind == EK_NE) == not1) { if (c1->args[0]->kind == EK_VAR) { ex = replaceexprexpr(copyexpr(c2), c1->args[0], c1->args[1], 1); i = expr_is_bool(ex, !not2); freeexpr(ex); if (i) return 1; } if (c1->args[1]->kind == EK_VAR) { ex = replaceexprexpr(copyexpr(c2), c1->args[1], c1->args[0], 1); i = expr_is_bool(ex, !not2); freeexpr(ex); if (i) return 1; } } break; default: break; } if (not1 == not2 && exprequiv(c1, c2)) { /* c1 -> c1 */ return 1; } return 0;}void infiniteloop(sp)Stmt *sp;{ switch (infloopstyle) { case 1: /* write "for (;;) ..." */ sp->kind = SK_FOR; freeexpr(sp->exp1); sp->exp1 = NULL; break; case 2: /* write "while (1) ..." */ sp->kind = SK_WHILE; freeexpr(sp->exp1); sp->exp1 = makeexpr_val(make_ord(tp_boolean, 1)); break; case 3: /* write "do ... while (1)" */ sp->kind = SK_REPEAT; freeexpr(sp->exp1); sp->exp1 = makeexpr_val(make_ord(tp_boolean, 1)); break; default: /* leave it alone */ break; }}Expr *print_func(ex)Expr *ex;{ if (!ex || ex->kind != EK_BICALL) return NULL; if ((!strcmp(ex->val.s, "printf") && ex->args[0]->kind == EK_CONST) || !strcmp(ex->val.s, "putchar") || !strcmp(ex->val.s, "puts")) return ex_output; if ((!strcmp(ex->val.s, "fprintf") || !strcmp(ex->val.s, "sprintf")) && ex->args[1]->kind == EK_CONST) return ex->args[0]; if (!strcmp(ex->val.s, "putc") || !strcmp(ex->val.s, "fputc") || !strcmp(ex->val.s, "fputs")) return ex->args[1]; return NULL;}int printnl_func(ex)Expr *ex;{ char *cp, ch; int i, len; if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -