parse.c.2
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:48k
- 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)
- Expr *ex, *oldex, *newex;
- {
- int i;
- Type *type;
- for (i = 0; i < ex->nargs; i++)
- ex->args[i] = replaceexprexpr(ex->args[i], oldex, newex);
- 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);
- 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);
- if (sp->exp2)
- sp->exp2 = replaceexprexpr(sp->exp2, oldex, newex);
- if (sp->exp3)
- sp->exp3 = replaceexprexpr(sp->exp3, oldex, newex);
- 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]);
- 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_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)
- Stmt *sp;
- {
- if (!sp)
- return 0;
- while (sp->next)
- sp = sp->next;
- return (sp->kind == SK_GOTO ||
- sp->kind == SK_BREAK ||
- sp->kind == SK_CONTINUE ||
- sp->kind == SK_RETURN ||
- sp->kind == SK_CASECHECK ||
- (sp->kind == SK_IF && deadendblock(sp->stm1) &&
- deadendblock(sp->stm2)) ||
- (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]);
- 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]);
- 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 (debug>2) { fprintf(outf,"printnl_func("); dumpexpr(ex); fprintf(outf, ")n"); }
- if (!strcmp(ex->val.s, "printf") ||
- !strcmp(ex->val.s, "puts") ||
- !strcmp(ex->val.s, "fputs")) {
- if (ex->args[0]->kind != EK_CONST)
- return 0;
- cp = ex->args[0]->val.s;
- len = ex->args[0]->val.i;
- } else if (!strcmp(ex->val.s, "fprintf")) {
- if (ex->args[1]->kind != EK_CONST)
- return 0;
- cp = ex->args[1]->val.s;
- len = ex->args[1]->val.i;
- } else if (!strcmp(ex->val.s, "putchar") ||
- !strcmp(ex->val.s, "putc") ||
- !strcmp(ex->val.s, "fputc")) {
- if (ex->args[0]->kind != EK_CONST)
- return 0;
- ch = ex->args[0]->val.i;
- cp = &ch;
- len = 1;
- } else
- return 0;
- for (i = 1; i <= len; i++)
- if (*cp++ != 'n')
- return 0;
- return len + (!strcmp(ex->val.s, "puts"));
- }
- Expr *chg_printf(ex)
- Expr *ex;
- {
- Expr *fex;
- if (debug>2) { fprintf(outf,"chg_printf("); dumpexpr(ex); fprintf(outf, ")n"); }
- if (!strcmp(ex->val.s, "putchar")) {
- ex = makeexpr_sprintfify(grabarg(ex, 0));
- canceltempvar(istempvar(ex->args[0]));
- strchange(&ex->val.s, "printf");
- delfreearg(&ex, 0);
- ex->val.type = tp_void;
- } else if (!strcmp(ex->val.s, "putc") ||
- !strcmp(ex->val.s, "fputc") ||
- !strcmp(ex->val.s, "fputs")) {
- fex = copyexpr(ex->args[1]);
- ex = makeexpr_sprintfify(grabarg(ex, 0));
- canceltempvar(istempvar(ex->args[0]));
- strchange(&ex->val.s, "fprintf");
- ex->args[0] = fex;
- ex->val.type = tp_void;
- } else if (!strcmp(ex->val.s, "puts")) {
- ex = makeexpr_concat(makeexpr_sprintfify(grabarg(ex, 0)),
- makeexpr_string("n"), 1);
- strchange(&ex->val.s, "printf");
- delfreearg(&ex, 0);
- ex->val.type = tp_void;
- }
- if (!strcmp(ex->val.s, "fprintf") && exprsame(ex->args[0], ex_output, 1)) {
- delfreearg(&ex, 0);
- strchange(&ex->val.s, "printf");
- }
- return ex;
- }
- Expr *mix_printf(ex, ex2)
- Expr *ex, *ex2;
- {
- int i;
- ex = chg_printf(ex);
- if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex); fprintf(outf, "n"); }
- ex2 = chg_printf(copyexpr(ex2));
- if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex2);fprintf(outf, "n"); }
- i = (!strcmp(ex->val.s, "printf")) ? 0 : 1;
- ex->args[i] = makeexpr_concat(ex->args[i], ex2->args[i], 0);
- for (i++; i < ex2->nargs; i++) {
- insertarg(&ex, ex->nargs, ex2->args[i]);
- }
- return ex;
- }
- void eatstmt(spp)
- Stmt **spp;
- {
- Stmt *sp = *spp;
- if (debug>2) { fprintf(outf, "eatstmt on:n"); dumpstmt(sp, 5); }
- *spp = sp->next;
- sp->next = NULL;
- free_stmt(sp);
- }
- int haslabels(sp)
- Stmt *sp;
- {
- if (!sp)
- return 0;
- if (haslabels(sp->stm1) || haslabels(sp->stm2))
- return 1;
- return (sp->kind == SK_LABEL);
- }
- void fixblock(spp, thereturn)
- Stmt **spp, *thereturn;
- {
- Stmt *sp, *sp1, *sp2, *sp3, **spp2, *thisreturn;
- Expr *ex;
- Meaning *tvar, *mp;
- int save_tryblock;
- short save_tryflag;
- int i, j, de1, de2;
- long saveserial = curserial;
- while ((sp = *spp)) {
- sp2 = sp->next;
- sp->next = NULL;
- sp = fix_statement(*spp);
- if (!sp) {
- *spp = sp2;
- continue;
- }
- *spp = sp;
- for (sp3 = sp; sp3->next; sp3 = sp3->next) ;
- sp3->next = sp2;
- if (!sp->next)
- thisreturn = thereturn;
- else if (sp->next->kind == SK_RETURN ||
- (sp->next->kind == SK_ASSIGN &&
- isescape(sp->next->exp1)))
- thisreturn = sp->next;
- else
- thisreturn = NULL;
- if (sp->serial >= 0)
- curserial = sp->serial;
- switch (sp->kind) {
- case SK_ASSIGN:
- if (sp->exp1)
- sp->exp1 = fixexpr(sp->exp1, ENV_STMT);
- if (!sp->exp1)
- intwarning("fixblock", "sp->exp1 == NULL in SK_ASSIGN");
- if (!sp->exp1 || nosideeffects(sp->exp1, 1)) {
- eatstmt(spp);
- continue;
- } else {
- switch (sp->exp1->kind) {
- case EK_COND:
- *spp = makestmt_if(sp->exp1->args[0],
- makestmt_call(sp->exp1->args[1]),
- makestmt_call(sp->exp1->args[2]));
- (*spp)->next = sp->next;
- continue; /* ... to fix this new if statement */
- case EK_ASSIGN:
- if (sp->exp1->args[1]->kind == EK_COND && usecommas != 1) {
- *spp = makestmt_if(sp->exp1->args[1]->args[0],
- makestmt_assign(copyexpr(sp->exp1->args[0]),
- sp->exp1->args[1]->args[1]),
- makestmt_assign(sp->exp1->args[0],
- sp->exp1->args[1]->args[2]));
- (*spp)->next = sp->next;
- continue;
- }
- if (isescape(sp->exp1->args[1])) {
- sp->exp1 = grabarg(sp->exp1, 1);
- continue;
- }
- if (exprsame(sp->exp1->args[0], sp->exp1->args[1], 1)) {
- /* *spp = sp->next; */
- sp->exp1 = grabarg(sp->exp1, 0);
- continue;
- }
- if (sp->exp1->args[1]->kind == EK_BICALL) {
- if (!strcmp(sp->exp1->args[1]->val.s,
- getfbufname) &&
- buildreads == 1 &&
- sp->next &&
- sp->next->kind == SK_ASSIGN &&
- sp->next->exp1->kind == EK_BICALL &&
- !strcmp(sp->next->exp1->val.s,
- getname) &&
- expr_has_address(sp->exp1->args[0]) &&
- similartypes(sp->exp1->args[0]->val.type,
- sp->exp1->args[1]->args[0]->val.type->basetype->basetype) &&
- exprsame(sp->exp1->args[1]->args[0],
- sp->next->exp1->args[0], 1)) {
- eatstmt(&sp->next);
- ex = makeexpr_bicall_4("fread", tp_integer,
- makeexpr_addr(sp->exp1->args[0]),
- makeexpr_sizeof(sp->exp1->args[1]->args[1], 0),
- makeexpr_long(1),
- sp->exp1->args[1]->args[0]);
- FREE(sp->exp1);
- sp->exp1 = ex;
- continue;
- }
- if (!strcmp(sp->exp1->args[1]->val.s,
- chargetfbufname) &&
- buildreads != 0 &&
- sp->next &&
- sp->next->kind == SK_ASSIGN &&
- sp->next->exp1->kind == EK_BICALL &&
- !strcmp(sp->next->exp1->val.s,
- chargetname) &&
- expr_has_address(sp->exp1->args[0]) &&
- exprsame(sp->exp1->args[1]->args[0],
- sp->next->exp1->args[0], 1)) {
- eatstmt(&sp->next);
- strchange(&sp->exp1->args[1]->val.s,
- "getc");
- continue;
- }
- }
- break;
- case EK_BICALL:
- if (!strcmp(sp->exp1->val.s, name_ESCAPE)) {
- if (fixexpr_tryblock) {
- *spp = makestmt_assign(makeexpr_var(mp_escapecode),
- grabarg(sp->exp1, 0));
- (*spp)->next = makestmt(SK_GOTO);
- (*spp)->next->exp1 = makeexpr_name(format_s(name_LABEL,
- format_d("try%d",
- fixexpr_tryblock)),
- tp_integer);
- (*spp)->next->next = sp->next;
- fixexpr_tryflag = 1;
- continue;
- }
- } else if (!strcmp(sp->exp1->val.s, name_ESCIO)) {
- if (fixexpr_tryblock) {
- *spp = makestmt_assign(makeexpr_var(mp_escapecode),
- makeexpr_long(-10));
- (*spp)->next = makestmt_assign(makeexpr_var(mp_ioresult),
- grabarg(sp->exp1, 0));
- (*spp)->next->next = makestmt(SK_GOTO);
- (*spp)->next->next->exp1 = makeexpr_name(format_s(name_LABEL,
- format_d("try%d",
- fixexpr_tryblock)),
- tp_integer);
- (*spp)->next->next->next = sp->next;
- fixexpr_tryflag = 1;
- continue;
- }
- }
- if (!strcmp(sp->exp1->val.s, putfbufname) &&
- buildwrites == 1 &&
- sp->next &&
- sp->next->kind == SK_ASSIGN &&
- sp->next->exp1->kind == EK_BICALL &&
- !strcmp(sp->next->exp1->val.s,
- putname) &&
- exprsame(sp->exp1->args[0],
- sp->next->exp1->args[0], 1)) {
- eatstmt(&sp->next);
- if (!expr_has_address(sp->exp1->args[2]) ||
- sp->exp1->args[2]->val.type !=
- sp->exp1->args[1]->val.type) {
- tvar = maketempvar(sp->exp1->args[1]->val.type,
- name_TEMP);
- sp2 = makestmt_assign(makeexpr_var(tvar),
- sp->exp1->args[2]);
- sp2->next = sp;
- *spp = sp2;
- sp->exp1->args[2] = makeexpr_var(tvar);
- freetempvar(tvar);
- }
- ex = makeexpr_bicall_4("fwrite", tp_integer,
- makeexpr_addr(sp->exp1->args[2]),
- makeexpr_sizeof(sp->exp1->args[1], 0),
- makeexpr_long(1),
- sp->exp1->args[0]);
- FREE(sp->exp1);
- sp->exp1 = ex;
- continue;
- }
- if (!strcmp(sp->exp1->val.s, charputfbufname) &&
- buildwrites != 0 &&
- sp->next &&
- sp->next->kind == SK_ASSIGN &&
- sp->next->exp1->kind == EK_BICALL &&
- !strcmp(sp->next->exp1->val.s,
- charputname) &&
- exprsame(sp->exp1->args[0],
- sp->next->exp1->args[0], 1)) {
- eatstmt(&sp->next);
- swapexprs(sp->exp1->args[0],
- sp->exp1->args[1]);
- strchange(&sp->exp1->val.s, "putc");
- continue;
- }
- if ((!strcmp(sp->exp1->val.s, resetbufname) ||
- !strcmp(sp->exp1->val.s, setupbufname)) &&
- (mp = isfilevar(sp->exp1->args[0])) != NULL &&
- !mp->bufferedfile) {
- eatstmt(spp);
- continue;
- }
- ex = print_func(sp->exp1);
- if (ex && sp->next && mixwritelns &&
- sp->next->kind == SK_ASSIGN &&
- exprsame(ex, print_func(sp->next->exp1), 1) &&
- (printnl_func(sp->exp1) ||
- printnl_func(sp->next->exp1))) {
- sp->exp1 = mix_printf(sp->exp1,
- sp->next->exp1);
- eatstmt(&sp->next);
- continue;
- }
- break;
- case EK_FUNCTION:
- case EK_SPCALL:
- case EK_POSTINC:
- case EK_POSTDEC:
- case EK_AND:
- case EK_OR:
- break;
- default:
- spp2 = spp;
- for (i = 0; i < sp->exp1->nargs; i++) {
- *spp2 = makestmt_call(sp->exp1->args[i]);
- spp2 = &(*spp2)->next;
- }
- *spp2 = sp->next;
- continue; /* ... to fix these new statements */
- }
- }
- break;
- case SK_IF:
- fixblock(&sp->stm1, thisreturn);
- fixblock(&sp->stm2, thisreturn);
- if (!sp->stm1) {
- if (!sp->stm2) {
- sp->kind = SK_ASSIGN;
- continue;
- } else {
- if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
- freeexpr(sp->stm2->exp2);
- sp->stm2->exp2 = NULL;
- }
- sp->exp1 = makeexpr_not(sp->exp1); /* if (x) else foo => if (!x) foo */
- swapstmts(sp->stm1, sp->stm2);
- /* Ought to exchange comments for then/else parts */
- }
- }
- /* At this point we know sp1 != NULL */
- if (thisreturn) {
- if (thisreturn->kind == SK_WHILE) {
- if (usebreaks) {
- sp1 = sp->stm1;
- while (sp1->next)
- sp1 = sp1->next;
- if (sp->stm2) {
- sp2 = sp->stm2;
- while (sp2->next)
- sp2 = sp2->next;
- i = stmtcount(sp->stm1);
- j = stmtcount(sp->stm2);
- if (j >= breaklimit && i <= 2 && j > i*2 &&
- ((implies(sp->exp1, thisreturn->exp1, 0, 1) &&
- !checkexprchanged(sp->stm1, sp->exp1)) ||
- (sp1->kind == SK_ASSIGN &&
- implies(sp1->exp1, thisreturn->exp1, 0, 1)))) {
- sp1->next = makestmt(SK_BREAK);
- } else if (i >= breaklimit && j <= 2 && i > j*2 &&
- ((implies(sp->exp1, thisreturn->exp1, 1, 1) &&
- !checkexprchanged(sp->stm2, sp->exp1)) ||
- (sp2->kind == SK_ASSIGN &&
- implies(sp2->exp1, thisreturn->exp1, 0, 1)))) {
- sp2->next = makestmt(SK_BREAK);
- } else if (!checkconst(sp->exp2, 1)) {
- /* not part of an else-if */
- if (j >= continuelimit) {
- sp1->next = makestmt(SK_CONTINUE);
- } else if (i >= continuelimit) {
- sp2->next = makestmt(SK_CONTINUE);
- }
- }
- } else {
- i = stmtcount(sp->stm1);
- if (i >= breaklimit &&
- implies(sp->exp1, thisreturn->exp1, 1, 1)) {
- sp->exp1 = makeexpr_not(sp->exp1);
- sp1->next = sp->next;
- sp->next = sp->stm1;
- sp->stm1 = makestmt(SK_BREAK);
- } else if (i >= continuelimit) {
- sp->exp1 = makeexpr_not(sp->exp1);
- sp1->next = sp->next;
- sp->next = sp->stm1;
- sp->stm1 = makestmt(SK_CONTINUE);
- }
- }
- }
- } else {
- if (usereturns) {
- sp2 = sp->stm1;
- while (sp2->next)
- sp2 = sp2->next;
- if (sp->stm2) {
- /* if (x) foo; else bar; (return;) => if (x) {foo; return;} bar; */
- if (stmtcount(sp->stm2) >= returnlimit) {
- if (!deadendblock(sp->stm1))
- sp2->next = copystmt(thisreturn);
- } else if (stmtcount(sp->stm1) >= returnlimit) {
- sp2 = sp->stm2;
- while (sp2->next)
- sp2 = sp2->next;
- if (!deadendblock(sp->stm2))
- sp2->next = copystmt(thisreturn);
- }
- } else { /* if (x) foo; (return;) => if (!x) return; foo; */
- if (stmtcount(sp->stm1) >= returnlimit) {
- sp->exp1 = makeexpr_not(sp->exp1);
- sp2->next = sp->next;
- sp->next = sp->stm1;
- sp->stm1 = copystmt(thisreturn);
- }
- }
- }
- }
- }
- if (!checkconst(sp->exp2, 1)) { /* not part of an else-if */
- de1 = deadendblock(sp->stm1);
- de2 = deadendblock(sp->stm2);
- if (de2 && !de1) {
- sp->exp1 = makeexpr_not(sp->exp1);
- swapstmts(sp->stm1, sp->stm2);
- de1 = 1, de2 = 0;
- }
- if (de1 && !de2 && sp->stm2) {
- if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
- freeexpr(sp->stm2->exp2);
- sp->stm2->exp2 = NULL;
- }
- for (sp2 = sp->stm2; sp2->next; sp2 = sp2->next) ;
- sp2->next = sp->next;
- sp->next = sp->stm2; /* if (x) ESCAPE else foo => if (x) ESCAPE; foo */
- sp->stm2 = NULL;
- }
- }
- sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
- break;
- case SK_WHILE:
- if (whilefgets && /* handle "while eof(f) do readln(f,...)" */
- sp->stm1->kind == SK_ASSIGN &&
- sp->stm1->exp1->kind == EK_BICALL &&
- !strcmp(sp->stm1->exp1->val.s, "fgets") &&
- nosideeffects(sp->stm1->exp1->args[0], 1) &&
- nosideeffects(sp->stm1->exp1->args[1], 1) &&
- nosideeffects(sp->stm1->exp1->args[2], 1)) {
- if ((sp->exp1->kind == EK_NOT &&
- sp->exp1->args[0]->kind == EK_BICALL && *eofname &&
- !strcmp(sp->exp1->args[0]->val.s, eofname) &&
- exprsame(sp->exp1->args[0]->args[0],
- sp->stm1->exp1->args[2], 1)) ||
- (sp->exp1->kind == EK_EQ &&
- sp->exp1->args[0]->kind == EK_BICALL &&
- !strcmp(sp->exp1->args[0]->val.s, "feof") &&
- checkconst(sp->exp1->args[1], 0) &&
- exprsame(sp->exp1->args[0]->args[0],
- sp->stm1->exp1->args[2], 1))) {
- sp->stm1->exp1->val.type = tp_strptr;
- sp->exp1 = makeexpr_rel(EK_NE,
- sp->stm1->exp1,
- makeexpr_nil());
- sp->stm1 = sp->stm1->next;
- }
- }
- fixblock(&sp->stm1, sp);
- sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
- if (checkconst(sp->exp1, 1))
- infiniteloop(sp);
- break;
- case SK_REPEAT:
- fixblock(&sp->stm1, NULL);
- sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
- if (checkconst(sp->exp1, 1))
- infiniteloop(sp);
- break;
- case SK_TRY:
- save_tryblock = fixexpr_tryblock;
- save_tryflag = fixexpr_tryflag;
- fixexpr_tryblock = sp->exp1->val.i;
- fixexpr_tryflag = 0;
- fixblock(&sp->stm1, NULL);
- if (fixexpr_tryflag)
- sp->exp2 = makeexpr_long(1);
- fixexpr_tryblock = save_tryblock;
- fixexpr_tryflag = save_tryflag;
- fixblock(&sp->stm2, NULL);
- break;
- case SK_BODY:
- fixblock(&sp->stm1, thisreturn);
- break;
- case SK_CASE:
- fixblock(&sp->stm1, NULL);
- sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
- if (!sp->stm1) { /* empty case */
- sp->kind = SK_ASSIGN;
- continue;
- } else if (sp->stm1->kind != SK_CASELABEL) { /* default only */
- for (sp2 = sp->stm1; sp2->next; sp2 = sp2->next) ;
- sp2->next = sp->next;
- sp->next = sp->stm1;
- sp->kind = SK_ASSIGN;
- sp->stm1 = NULL;
- continue;
- }
- break;
- default:
- fixblock(&sp->stm1, NULL);
- fixblock(&sp->stm2, NULL);
- sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
- sp->exp2 = fixexpr(sp->exp2, ENV_EXPR);
- sp->exp3 = fixexpr(sp->exp3, ENV_EXPR);
- if (sp->next &&
- (sp->kind == SK_GOTO ||
- sp->kind == SK_BREAK ||
- sp->kind == SK_CONTINUE ||
- sp->kind == SK_RETURN) &&
- !haslabels(sp->next)) {
- if (elimdeadcode) {
- note("Deleting unreachable code [255]");
- while (sp->next && !haslabels(sp->next))
- eatstmt(&sp->next);
- } else {
- note("Code is unreachable [256]");
- }
- } else if (sp->kind == SK_RETURN &&
- thisreturn &&
- thisreturn->kind == SK_RETURN &&
- exprsame(sp->exp1, thisreturn->exp1, 1)) {
- eatstmt(spp);
- continue;
- }
- break;
- }
- spp = &sp->next;
- }
- saveserial = curserial;
- }
- /* Convert comma expressions into multiple statements */
- Static int checkcomma_expr(spp, exp)
- Stmt **spp;
- Expr **exp;
- {
- Stmt *sp;
- Expr *ex = *exp;
- int i, res;
- switch (ex->kind) {
- case EK_COMMA:
- if (spp) {
- res = checkcomma_expr(spp, &ex->args[ex->nargs-1]);
- for (i = ex->nargs-1; --i >= 0; ) {
- sp = makestmt(SK_ASSIGN);
- sp->exp1 = ex->args[i];
- sp->next = *spp;
- *spp = sp;
- res = checkcomma_expr(spp, &ex->args[i]);
- }
- *exp = ex->args[ex->nargs-1];
- }
- return 1;
- case EK_COND:
- if (isescape(ex->args[1]) && spp &&
- !isescape(ex->args[2])) {
- swapexprs(ex->args[1], ex->args[2]);
- ex->args[0] = makeexpr_not(ex->args[0]);
- }
- if (isescape(ex->args[2])) {
- if (spp) {
- res = checkcomma_expr(spp, &ex->args[1]);
- if (ex->args[0]->kind == EK_ASSIGN) {
- sp = makestmt(SK_ASSIGN);
- sp->exp1 = copyexpr(ex->args[0]);
- sp->next = makestmt(SK_IF);
- sp->next->next = *spp;
- *spp = sp;
- res = checkcomma_expr(spp, &sp->exp1);
- ex->args[0] = grabarg(ex->args[0], 0);
- sp = sp->next;
- } else {
- sp = makestmt(SK_IF);
- sp->next = *spp;
- *spp = sp;
- }
- sp->exp1 = makeexpr_not(ex->args[0]);
- sp->stm1 = makestmt(SK_ASSIGN);
- sp->stm1->exp1 = eatcasts(ex->args[2]);
- res = checkcomma_expr(&sp->stm1, &ex->args[2]);
- res = checkcomma_expr(spp, &sp->exp1);
- *exp = ex->args[1];
- }
- return 1;
- }
- return checkcomma_expr(spp, &ex->args[0]);
- case EK_AND:
- case EK_OR:
- return checkcomma_expr(spp, &ex->args[0]);
- default:
- res = 0;
- for (i = ex->nargs; --i >= 0; ) {
- res += checkcomma_expr(spp, &ex->args[i]);
- }
- return res;
- }
- }
- Static void checkcommas(spp)
- Stmt **spp;
- {
- Stmt *sp;
- int res;
- while ((sp = *spp)) {
- checkcommas(&sp->stm1);
- checkcommas(&sp->stm2);
- switch (sp->kind) {
- case SK_ASSIGN:
- case SK_IF:
- case SK_CASE:
- case SK_RETURN:
- if (sp->exp1)
- res = checkcomma_expr(spp, &sp->exp1);
- break;
- case SK_WHILE:
- /* handle the argument */
- break;
- case SK_REPEAT:
- /* handle the argument */
- break;
- case SK_FOR:
- if (sp->exp1)
- res = checkcomma_expr(spp, &sp->exp1);
- /* handle the other arguments */
- break;
- default:
- break;
- }
- spp = &sp->next;
- }
- }
- Static int checkvarchangeable(ex, mp)
- Expr *ex;
- Meaning *mp;
- {
- switch (ex->kind) {
- case EK_VAR:
- return (mp == (Meaning *)ex->val.i);
- case EK_DOT:
- case EK_INDEX:
- return checkvarchangeable(ex->args[0], mp);
- default:
- return 0;
- }
- }
- int checkvarchangedexpr(ex, mp, addrokay)
- Expr *ex;
- Meaning *mp;
- int addrokay;
- {
- int i;
- Meaning *mp3;
- unsigned int safemask = 0;
- switch (ex->kind) {
- case EK_FUNCTION:
- case EK_SPCALL:
- if (ex->kind == EK_FUNCTION) {
- i = 0;
- mp3 = ((Meaning *)ex->val.i)->type->fbase;
- } else {
- i = 1;
- if (ex->args[0]->val.type->kind != TK_PROCPTR)
- return 1;
- mp3 = ex->args[0]->val.type->basetype->fbase;
- }
- for ( ; i < ex->nargs && i < 16; i++) {
- if (!mp3) {
- intwarning("checkvarchangedexpr", "Too many arguments for EK_FUNCTION [266]");
- break;
- }
- if (mp3->kind == MK_PARAM &&
- (mp3->type->kind == TK_ARRAY ||
- mp3->type->kind == TK_STRING ||
- mp3->type->kind == TK_SET))
- safemask |= 1<<i;
- if (mp3->kind == MK_VARPARAM &&
- mp3->type == tp_strptr && mp3->anyvarflag)
- i++;
- mp3 = mp3->xnext;
- }
- if (mp3)
- intwarning("checkvarchangedexpr", "Too few arguments for EK_FUNCTION [267]");
- break;
- case EK_VAR:
- if (mp == (Meaning *)ex->val.i) {
- if ((mp->type->kind == TK_ARRAY ||
- mp->type->kind == TK_STRING ||
- mp->type->kind == TK_SET) &&
- ex->val.type->kind == TK_POINTER && !addrokay)
- return 1; /* must be an implicit & */
- }
- break;
- case EK_ADDR:
- case EK_ASSIGN:
- case EK_POSTINC:
- case EK_POSTDEC:
- if (checkvarchangeable(ex->args[0], mp))
- return 1;
- break;
- case EK_BICALL:
- if (structuredfunc(ex) && checkvarchangeable(ex->args[0], mp))
- return 1;
- safemask = safemask_bicall(ex->val.s);
- break;
- /* In case calls to these functions were lazy and passed
- the array rather than its (implicit) address. Other
- BICALLs had better be careful about their arguments. */
- case EK_PLUS:
- if (addrokay) /* to keep from being scared by pointer */
- safemask = ~0; /* arithmetic on string being passed */
- break; /* to functions. */
- default:
- break;
- }
- for (i = 0; i < ex->nargs; i++) {
- if (checkvarchangedexpr(ex->args[i], mp, safemask&1))
- return 1;
- safemask >>= 1;
- }
- return 0;
- }
- int checkvarchanged(sp, mp)
- Stmt *sp;
- Meaning *mp;
- {
- if (mp->constqual)
- return 0;
- if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION ||
- mp->volatilequal || alwayscopyvalues)
- return 1;
- while (sp) {
- if (/* sp->kind == SK_GOTO || */
- sp->kind == SK_LABEL ||
- checkvarchanged(sp->stm1, mp) ||
- checkvarchanged(sp->stm2, mp) ||
- (sp->exp1 && checkvarchangedexpr(sp->exp1, mp, 1)) ||
- (sp->exp2 && checkvarchangedexpr(sp->exp2, mp, 1)) ||
- (sp->exp3 && checkvarchangedexpr(sp->exp3, mp, 1)))
- return 1;
- sp = sp->next;
- }
- return 0;
- }
- int checkexprchanged(sp, ex)
- Stmt *sp;
- Expr *ex;
- {
- Meaning *mp;
- int i;
- for (i = 0; i < ex->nargs; i++) {
- if (checkexprchanged(sp, ex->args[i]))
- return 1;
- }
- switch (ex->kind) {
- case EK_VAR:
- mp = (Meaning *)ex->val.i;
- if (mp->kind == MK_CONST)
- return 0;
- else
- return checkvarchanged(sp, mp);
- case EK_HAT:
- case EK_INDEX:
- case EK_SPCALL:
- return 1;
- case EK_FUNCTION:
- case EK_BICALL:
- return !nosideeffects_func(ex);
- default:
- return 0;
- }
- }
- /* Check if a variable always occurs with a certain offset added, e.g. "i+1" */
- Static int theoffset, numoffsets, numzerooffsets;
- #define BadOffset (-999)
- void checkvaroffsetexpr(ex, mp, myoffset)
- Expr *ex;
- Meaning *mp;
- int myoffset;
- {
- int i, nextoffset = 0;
- Expr *ex2;
- if (!ex)
- return;
- switch (ex->kind) {
- case EK_VAR:
- if (ex->val.i == (long)mp) {
- if (myoffset == 0)
- numzerooffsets++;
- else if (numoffsets == 0 || myoffset == theoffset) {
- theoffset = myoffset;
- numoffsets++;
- } else
- theoffset = BadOffset;
- }
- break;
- case EK_PLUS:
- ex2 = ex->args[ex->nargs-1];
- if (ex2->kind == EK_CONST &&
- ex2->val.type->kind == TK_INTEGER) {
- nextoffset = ex2->val.i;
- }
- break;
- case EK_HAT:
- case EK_POSTINC:
- case EK_POSTDEC:
- nextoffset = BadOffset;
- break;
- case EK_ASSIGN:
- checkvaroffsetexpr(ex->args[0], mp, BadOffset);
- checkvaroffsetexpr(ex->args[1], mp, 0);
- return;
- default:
- break;
- }
- i = ex->nargs;
- while (--i >= 0)
- checkvaroffsetexpr(ex->args[i], mp, nextoffset);
- }
- void checkvaroffsetstmt(sp, mp)
- Stmt *sp;
- Meaning *mp;
- {
- while (sp) {
- checkvaroffsetstmt(sp->stm1, mp);
- checkvaroffsetstmt(sp->stm1, mp);
- checkvaroffsetexpr(sp->exp1, mp, 0);
- checkvaroffsetexpr(sp->exp2, mp, 0);
- checkvaroffsetexpr(sp->exp3, mp, 0);
- sp = sp->next;
- }
- }
- int checkvaroffset(sp, mp)
- Stmt *sp;
- Meaning *mp;
- {
- if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION)
- return 0;
- numoffsets = 0;
- numzerooffsets = 0;
- checkvaroffsetstmt(sp, mp);
- if (numoffsets == 0 || theoffset == BadOffset ||
- numoffsets <= numzerooffsets * 3)
- return 0;
- else
- return theoffset;
- }
- void initfilevars(mp, sppp, exbase)
- Meaning *mp;
- Stmt ***sppp;
- Expr *exbase;
- {
- Stmt *sp;
- Type *tp;
- Expr *ex;
- while (mp) {
- if ((mp->kind == MK_VAR && mp->refcount > 0 && !mp->istemporary) ||
- mp->kind == MK_FIELD) {
- tp = mp->type;
- if (isfiletype(tp)) {
- mp->refcount++;
- sp = makestmt(SK_ASSIGN);
- sp->next = **sppp;
- **sppp = sp;
- if (exbase)
- ex = makeexpr_dot(copyexpr(exbase), mp);
- else
- ex = makeexpr_var(mp);
- sp->exp1 = makeexpr_assign(copyexpr(ex), makeexpr_nil());
- } else if (tp->kind == TK_RECORD) {
- if (exbase)
- ex = makeexpr_dot(copyexpr(exbase), mp);
- else
- ex = makeexpr_var(mp);
- initfilevars(tp->fbase, sppp, ex);
- freeexpr(ex);
- } else if (tp->kind == TK_ARRAY) {
- while (tp->kind == TK_ARRAY)
- tp = tp->basetype;
- if (isfiletype(tp))
- note(format_s("Array of files %s should be initialized [257]",
- mp->name));
- }
- }
- mp = mp->cnext;
- }
- }
- Static Stmt *p_body()
- {
- Stmt *sp, **spp, *spbody, **sppbody, *spbase, *thereturn;
- Meaning *mp;
- Expr *ex;
- int haspostamble;
- long saveserial;
- if (verbose)
- fprintf(logf, "%s, %d/%d: Translating %s (in %s)n",
- infname, inf_lnum, outf_lnum,
- curctx->name, curctx->ctx->name);
- notephase = 1;
- spp = &spbase;
- addstmt(SK_HEADER);
- sp->exp1 = makeexpr_var(curctx);
- checkkeyword(TOK_INLINE);
- if (curtok != TOK_END && curtok != TOK_BEGIN && curtok != TOK_INLINE) {
- if (curctx->kind == MK_FUNCTION || curctx->anyvarflag)
- wexpecttok(TOK_BEGIN);
- else
- wexpecttok(TOK_END);
- skiptotoken2(TOK_BEGIN, TOK_END);
- }
- if (curtok == TOK_END) {
- gettok();
- spbody = NULL;
- } else {
- spbody = p_stmt(NULL, SF_FUNC); /* parse the procedure/program body */
- }
- if (curtok == TOK_IDENT && curtokmeaning == curctx) {
- gettok(); /* Modula-2 */
- }
- notephase = 2;
- saveserial = curserial;
- curserial = 10000;
- if (curctx->kind == MK_FUNCTION) { /* handle copy parameters */
- for (mp = curctx->type->fbase; mp; mp = mp->xnext) {
- if (!mp->othername && mp->varstructflag) {
- mp->othername = stralloc(format_s(name_COPYPAR, mp->name));
- mp->rectype = mp->type;
- addstmt(SK_ASSIGN);
- sp->exp1 = makeexpr_assign(makeexpr_var(mp),
- makeexpr_name(mp->othername, mp->rectype));
- mp->refcount++;
- } else if (mp->othername) {
- if (checkvarchanged(spbody, mp)) {
- addstmt(SK_ASSIGN);
- sp->exp1 = makeexpr_assign(makeexpr_var(mp),
- makeexpr_hat(makeexpr_name(mp->othername,
- mp->rectype), 0));
- mp->refcount++;
- } else { /* don't need to copy it after all */
- strchange(&mp->othername, mp->name);
- ex = makeexpr_var(mp);
- ex->val.type = mp->rectype;
- replaceexpr(spbody, makeexpr_var(mp), makeexpr_hat(ex, 0));
- }
- }
- }
- }
- for (mp = curctx->cbase; mp; mp = mp->cnext) {
- if (mp->kind == MK_LABEL && mp->val.i) {
- addstmt(SK_IF);
- sp->exp1 = makeexpr_bicall_1("setjmp", tp_int,
- makeexpr_var(mp->xnext));
- sp->stm1 = makestmt(SK_GOTO);
- sp->stm1->exp1 = makeexpr_name(format_s(name_LABEL, mp->name),
- tp_integer);
- }
- }
- *spp = spbody;
- sppbody = spp;
- while (*spp)
- spp = &((*spp)->next);
- haspostamble = 0;
- initfilevars(curctx->cbase, &sppbody, NULL);
- for (mp = curctx->cbase; mp; mp = mp->cnext) {
- if (mp->kind == MK_VAR && mp->refcount > 0 && isfiletype(mp->type) &&
- !mp->istemporary) {
- if (curctx->kind != MK_MODULE || curctx->anyvarflag) {
- addstmt(SK_IF); /* close file variables */
- sp->exp1 = makeexpr_rel(EK_NE, makeexpr_var(mp), makeexpr_nil());
- sp->stm1 = makestmt(SK_ASSIGN);
- sp->stm1->exp1 = makeexpr_bicall_1("fclose", tp_void, makeexpr_var(mp));
- }
- haspostamble = 1;
- }
- }
- thereturn = &bogusreturn;
- if (curctx->kind == MK_FUNCTION && curctx->type->basetype != tp_void) {
- if ((haspostamble || !checkreturns(&spbase, 1)) &&
- curctx->cbase->refcount > 0) { /* add function return code */
- addstmt(SK_RETURN);
- sp->exp1 = makeexpr_var(curctx->cbase);
- }
- thereturn = NULL;
- } else if (curctx->kind == MK_MODULE && curctx->anyvarflag) {
- addstmt(SK_ASSIGN);
- sp->exp1 = makeexpr_bicall_1("exit", tp_void, makeexpr_long(0));
- thereturn = NULL;
- }
- if (debug>2) { fprintf(outf, "calling fixblock/usecommas on:n"); dumpstmt(spbase, 5); }
- curserial = saveserial;
- sp = makestmt(SK_BODY);
- sp->stm1 = spbase;
- fixblock(&sp, thereturn); /* finishing touches to statements and expressions */
- spbase = sp->stm1;
- FREE(sp);
- if (usecommas != 1)
- checkcommas(&spbase); /* unroll ugly EK_COMMA and EK_COND expressions */
- if (debug>1) { fprintf(outf, "p_body returns:n"); dumpstmt(spbase, 5); }
- notephase = 0;
- return spbase;
- }
- #define checkWord() if (anywords) output(" "); anywords = 1
- Static void out_function(func)
- Meaning *func;
- {
- Meaning *mp;
- Symbol *sym;
- int opts, anywords, spacing, saveindent;
- if (func->varstructflag) {
- makevarstruct(func);
- }
- if (collectnest) {
- for (mp = func->cbase; mp; mp = mp->cnext) {
- if (mp->kind == MK_FUNCTION && mp->isforward) {
- forward_decl(mp, 0);
- }
- }
- for (mp = func->cbase; mp; mp = mp->cnext) {
- if (mp->kind == MK_FUNCTION && mp->type) {
- pushctx(mp);
- out_function(mp); /* generate the sub-procedures first */
- popctx();
- }
- }
- }
- spacing = functionspace;
- for (mp = func; mp->ctx->kind == MK_FUNCTION; mp = mp->ctx) {
- if (spacing > minfuncspace)
- spacing--;
- }
- outsection(spacing);
- flushcomments(&func->comments, -1, 0);
- if (usePPMacros == 1) {
- forward_decl(func, 0);
- outsection(minorspace);
- }
- opts = ODECL_HEADER;
- anywords = 0;
- if (func->namedfile) {
- checkWord();
- if (useAnyptrMacros || ansiC < 2)
- output("Inline");
- else
- output("inline");
- }
- if (!func->exported) {
- if (func->ctx->kind == MK_FUNCTION) {
- if (useAnyptrMacros) {
- checkWord();
- output("Local");
- } else if (use_static) {
- checkWord();
- output("static");
- }
- } else if ((findsymbol(func->name)->flags & NEEDSTATIC) ||
- (use_static != 0 && !useAnyptrMacros)) {
- checkWord();
- output("static");
- } else if (useAnyptrMacros) {
- checkWord();
- output("Static");
- }
- }
- if (func->type->basetype != tp_void || ansiC != 0) {
- checkWord();
- outbasetype(func->type, 0);
- }
- if (anywords) {
- if (newlinefunctions)
- opts |= ODECL_FUNCTION;
- else
- output(" ");
- }
- outdeclarator(func->type, func->name, opts);
- if (fullprototyping == 0) {
- saveindent = outindent;
- moreindent(argindent);
- out_argdecls(func->type);
- outindent = saveindent;
- }
- for (mp = func->type->fbase; mp; mp = mp->xnext) {
- if (mp->othername && strcmp(mp->name, mp->othername))
- mp->wasdeclared = 0; /* make sure we also declare the copy */
- }
- func->wasdeclared = 1;
- outcontext = func;
- out_block((Stmt *)func->val.i, BR_FUNCTION, 10000);
- if (useundef) {
- anywords = 0;
- for (mp = func->cbase; mp; mp = mp->cnext) {
- if (mp->kind == MK_CONST &&