home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume21
/
p2c
/
part30
< prev
next >
Wrap
Text File
|
1990-04-05
|
53KB
|
1,639 lines
Subject: v21i075: Pascal to C translator, Part30/32
Newsgroups: comp.sources.unix
Approved: rsalz@uunet.UU.NET
X-Checksum-Snefru: d140c78b e19ae830 375027e7 9a3c700a
Submitted-by: Dave Gillespie <daveg@csvax.caltech.edu>
Posting-number: Volume 21, Issue 75
Archive-name: p2c/part30
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 30 (of 32)."
# Contents: src/parse.c.2
# Wrapped by rsalz@litchi.bbn.com on Mon Mar 26 14:29:53 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/parse.c.2' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/parse.c.2'\"
else
echo shar: Extracting \"'src/parse.c.2'\" \(49392 characters\)
sed "s/^X//" >'src/parse.c.2' <<'END_OF_FILE'
X if (spnextreturn) {
X mp->refcount--;
X sp->next = sp->next->next;
X }
X result = 1;
X }
X }
X break;
X
X case SK_RETURN:
X case SK_GOTO:
X result = 1;
X break;
X
X case SK_IF:
X result = checkreturns(&sp->stm1, spnearret) & /* NOT && */
X checkreturns(&sp->stm2, spnearret);
X break;
X
X case SK_TRY:
X (void) checkreturns(&sp->stm1, 0);
X (void) checkreturns(&sp->stm2, spnearret);
X break;
X
X /* should handle CASE statements as well */
X
X default:
X (void) checkreturns(&sp->stm1, 0);
X (void) checkreturns(&sp->stm2, 0);
X break;
X }
X spp = &sp->next;
X }
X return result;
X}
X
X
X
X
X
X
X
X/* Replace all occurrences of one expression with another expression */
X
XExpr *replaceexprexpr(ex, oldex, newex)
XExpr *ex, *oldex, *newex;
X{
X int i;
X Type *type;
X
X for (i = 0; i < ex->nargs; i++)
X ex->args[i] = replaceexprexpr(ex->args[i], oldex, newex);
X if (exprsame(ex, oldex, 2)) {
X if (ex->val.type->kind == TK_POINTER &&
X ex->val.type->basetype == oldex->val.type) {
X freeexpr(ex);
X return makeexpr_addr(copyexpr(newex));
X } else if (oldex->val.type->kind == TK_POINTER &&
X oldex->val.type->basetype == ex->val.type) {
X freeexpr(ex);
X return makeexpr_hat(copyexpr(newex), 0);
X } else {
X type = ex->val.type;
X freeexpr(ex);
X ex = copyexpr(newex);
X ex->val.type = type;
X return ex;
X }
X }
X return resimplify(ex);
X}
X
X
Xvoid replaceexpr(sp, oldex, newex)
XStmt *sp;
XExpr *oldex, *newex;
X{
X while (sp) {
X replaceexpr(sp->stm1, oldex, newex);
X replaceexpr(sp->stm2, oldex, newex);
X if (sp->exp1)
X sp->exp1 = replaceexprexpr(sp->exp1, oldex, newex);
X if (sp->exp2)
X sp->exp2 = replaceexprexpr(sp->exp2, oldex, newex);
X if (sp->exp3)
X sp->exp3 = replaceexprexpr(sp->exp3, oldex, newex);
X sp = sp->next;
X }
X}
X
X
X
X
X
X
XStmt *mixassignments(sp, mp)
XStmt *sp;
XMeaning *mp;
X{
X if (!sp)
X return NULL;
X sp->next = mixassignments(sp->next, mp);
X if (sp->next &&
X sp->kind == SK_ASSIGN &&
X sp->exp1->kind == EK_ASSIGN &&
X sp->exp1->args[0]->kind == EK_VAR &&
X (!mp || mp == (Meaning *)sp->exp1->args[0]->val.i) &&
X ord_type(sp->exp1->args[0]->val.type)->kind == TK_INTEGER &&
X nodependencies(sp->exp1->args[1], 0) &&
X sp->next->kind == SK_ASSIGN &&
X sp->next->exp1->kind == EK_ASSIGN &&
X (exprsame(sp->exp1->args[0], sp->next->exp1->args[0], 1) ||
X (mp && mp->istemporary)) &&
X exproccurs(sp->next->exp1->args[1], sp->exp1->args[0]) == 1) {
X sp->next->exp1->args[1] = replaceexprexpr(sp->next->exp1->args[1],
X sp->exp1->args[0],
X sp->exp1->args[1]);
X if (mp && mp->istemporary)
X canceltempvar(mp);
X return sp->next;
X }
X return sp;
X}
X
X
X
X
X
X
X
X
X/* Do various simple (sometimes necessary) massages on the statements */
X
X
XStatic Stmt bogusreturn = { SK_RETURN, NULL, NULL, NULL, NULL, NULL, NULL };
X
X
X
XStatic int isescape(ex)
XExpr *ex;
X{
X if (ex->kind == EK_BICALL && (!strcmp(ex->val.s, name_ESCAPE) ||
X !strcmp(ex->val.s, name_ESCIO) ||
X !strcmp(ex->val.s, name_OUTMEM) ||
X !strcmp(ex->val.s, name_CASECHECK) ||
X !strcmp(ex->val.s, name_NILCHECK) ||
X !strcmp(ex->val.s, "_exit") ||
X !strcmp(ex->val.s, "exit")))
X return 1;
X if (ex->kind == EK_CAST)
X return isescape(ex->args[0]);
X return 0;
X}
X
X
X/* check if a block can never exit by falling off the end */
XStatic int deadendblock(sp)
XStmt *sp;
X{
X if (!sp)
X return 0;
X while (sp->next)
X sp = sp->next;
X return (sp->kind == SK_GOTO ||
X sp->kind == SK_BREAK ||
X sp->kind == SK_CONTINUE ||
X sp->kind == SK_RETURN ||
X sp->kind == SK_CASECHECK ||
X (sp->kind == SK_IF && deadendblock(sp->stm1) &&
X deadendblock(sp->stm2)) ||
X (sp->kind == SK_ASSIGN && isescape(sp->exp1)));
X}
X
X
X
X
Xint expr_is_bool(ex, want)
XExpr *ex;
Xint want;
X{
X long val;
X
X if (ex->val.type == tp_boolean && isconstexpr(ex, &val))
X return (val == want);
X return 0;
X}
X
X
X
X
X/* Returns 1 if c1 implies c2, 0 otherwise */
X/* If not1 is true, then checks if (!c1) implies c2; similarly for not2 */
X
X/* Identities used:
X c1 -> (c2a && c2b) <=> (c1 -> c2a) && (c1 -> c2b)
X c1 -> (c2a || c2b) <=> (c1 -> c2a) || (c1 -> c2b)
X (c1a && c1b) -> c2 <=> (c1a -> c2) || (c1b -> c2)
X (c1a || c1b) -> c2 <=> (c1a -> c2) && (c1b -> c2)
X (!c1) -> (!c2) <=> c2 -> c1
X (a == b) -> c2(b) <=> c2(a)
X !(c1 && c2) <=> (!c1) || (!c2)
X !(c1 || c2) <=> (!c1) && (!c2)
X*/
X/* This could be smarter about, e.g., (a>5) -> (a>0) */
X
Xint implies(c1, c2, not1, not2)
XExpr *c1, *c2;
Xint not1, not2;
X{
X Expr *ex;
X int i;
X
X if (c1->kind == EK_EQ && c1->args[0]->val.type == tp_boolean) {
X if (checkconst(c1->args[0], 1)) { /* things like "flag = true" */
X return implies(c1->args[1], c2, not1, not2);
X } else if (checkconst(c1->args[1], 1)) {
X return implies(c1->args[0], c2, not1, not2);
X } else if (checkconst(c1->args[0], 0)) {
X return implies(c1->args[1], c2, !not1, not2);
X } else if (checkconst(c1->args[1], 0)) {
X return implies(c1->args[0], c2, !not1, not2);
X }
X }
X if (c2->kind == EK_EQ && c2->args[0]->val.type == tp_boolean) {
X if (checkconst(c2->args[0], 1)) {
X return implies(c1, c2->args[1], not1, not2);
X } else if (checkconst(c2->args[1], 1)) {
X return implies(c1, c2->args[0], not1, not2);
X } else if (checkconst(c2->args[0], 0)) {
X return implies(c1, c2->args[1], not1, !not2);
X } else if (checkconst(c2->args[1], 0)) {
X return implies(c1, c2->args[0], not1, !not2);
X }
X }
X switch (c2->kind) {
X
X case EK_AND:
X if (not2) /* c1 -> (!c2a || !c2b) */
X return (implies(c1, c2->args[0], not1, 1) ||
X implies(c1, c2->args[1], not1, 1));
X else /* c1 -> (c2a && c2b) */
X return (implies(c1, c2->args[0], not1, 0) &&
X implies(c1, c2->args[1], not1, 0));
X
X case EK_OR:
X if (not2) /* c1 -> (!c2a && !c2b) */
X return (implies(c1, c2->args[0], not1, 1) &&
X implies(c1, c2->args[1], not1, 1));
X else /* c1 -> (c2a || c2b) */
X return (implies(c1, c2->args[0], not1, 0) ||
X implies(c1, c2->args[1], not1, 0));
X
X case EK_NOT: /* c1 -> (!c2) */
X return (implies(c1, c2->args[0], not1, !not2));
X
X case EK_CONST:
X if ((c2->val.i != 0) != not2) /* c1 -> true */
X return 1;
X break;
X
X default:
X break;
X }
X switch (c1->kind) {
X
X case EK_AND:
X if (not1) /* (!c1a || !c1b) -> c2 */
X return (implies(c1->args[0], c2, 1, not2) &&
X implies(c1->args[1], c2, 1, not2));
X else /* (c1a && c1b) -> c2 */
X return (implies(c1->args[0], c2, 0, not2) ||
X implies(c1->args[1], c2, 0, not2));
X
X case EK_OR:
X if (not1) /* (!c1a && !c1b) -> c2 */
X return (implies(c1->args[0], c2, 1, not2) ||
X implies(c1->args[1], c2, 1, not2));
X else /* (c1a || c1b) -> c2 */
X return (implies(c1->args[0], c2, 0, not2) &&
X implies(c1->args[1], c2, 0, not2));
X
X case EK_NOT: /* (!c1) -> c2 */
X return (implies(c1->args[0], c2, !not1, not2));
X
X case EK_CONST:
X if ((c1->val.i != 0) == not1) /* false -> c2 */
X return 1;
X break;
X
X case EK_EQ: /* (a=b) -> c2 */
X case EK_ASSIGN: /* (a:=b) -> c2 */
X case EK_NE: /* (a<>b) -> c2 */
X if ((c1->kind == EK_NE) == not1) {
X if (c1->args[0]->kind == EK_VAR) {
X ex = replaceexprexpr(copyexpr(c2), c1->args[0], c1->args[1]);
X i = expr_is_bool(ex, !not2);
X freeexpr(ex);
X if (i)
X return 1;
X }
X if (c1->args[1]->kind == EK_VAR) {
X ex = replaceexprexpr(copyexpr(c2), c1->args[1], c1->args[0]);
X i = expr_is_bool(ex, !not2);
X freeexpr(ex);
X if (i)
X return 1;
X }
X }
X break;
X
X default:
X break;
X }
X if (not1 == not2 && exprequiv(c1, c2)) { /* c1 -> c1 */
X return 1;
X }
X return 0;
X}
X
X
X
X
X
Xvoid infiniteloop(sp)
XStmt *sp;
X{
X switch (infloopstyle) {
X
X case 1: /* write "for (;;) ..." */
X sp->kind = SK_FOR;
X freeexpr(sp->exp1);
X sp->exp1 = NULL;
X break;
X
X case 2: /* write "while (1) ..." */
X sp->kind = SK_WHILE;
X freeexpr(sp->exp1);
X sp->exp1 = makeexpr_val(make_ord(tp_boolean, 1));
X break;
X
X case 3: /* write "do ... while (1)" */
X sp->kind = SK_REPEAT;
X freeexpr(sp->exp1);
X sp->exp1 = makeexpr_val(make_ord(tp_boolean, 1));
X break;
X
X default: /* leave it alone */
X break;
X
X }
X}
X
X
X
X
X
XExpr *print_func(ex)
XExpr *ex;
X{
X if (!ex || ex->kind != EK_BICALL)
X return NULL;
X if ((!strcmp(ex->val.s, "printf") &&
X ex->args[0]->kind == EK_CONST) ||
X !strcmp(ex->val.s, "putchar") ||
X !strcmp(ex->val.s, "puts"))
X return ex_output;
X if ((!strcmp(ex->val.s, "fprintf") ||
X !strcmp(ex->val.s, "sprintf")) &&
X ex->args[1]->kind == EK_CONST)
X return ex->args[0];
X if (!strcmp(ex->val.s, "putc") ||
X !strcmp(ex->val.s, "fputc") ||
X !strcmp(ex->val.s, "fputs"))
X return ex->args[1];
X return NULL;
X}
X
X
X
Xint printnl_func(ex)
XExpr *ex;
X{
X char *cp, ch;
X int i, len;
X
X if (debug>2) { fprintf(outf,"printnl_func("); dumpexpr(ex); fprintf(outf, ")\n"); }
X if (!strcmp(ex->val.s, "printf") ||
X !strcmp(ex->val.s, "puts") ||
X !strcmp(ex->val.s, "fputs")) {
X if (ex->args[0]->kind != EK_CONST)
X return 0;
X cp = ex->args[0]->val.s;
X len = ex->args[0]->val.i;
X } else if (!strcmp(ex->val.s, "fprintf")) {
X if (ex->args[1]->kind != EK_CONST)
X return 0;
X cp = ex->args[1]->val.s;
X len = ex->args[1]->val.i;
X } else if (!strcmp(ex->val.s, "putchar") ||
X !strcmp(ex->val.s, "putc") ||
X !strcmp(ex->val.s, "fputc")) {
X if (ex->args[0]->kind != EK_CONST)
X return 0;
X ch = ex->args[0]->val.i;
X cp = &ch;
X len = 1;
X } else
X return 0;
X for (i = 1; i <= len; i++)
X if (*cp++ != '\n')
X return 0;
X return len + (!strcmp(ex->val.s, "puts"));
X}
X
X
X
XExpr *chg_printf(ex)
XExpr *ex;
X{
X Expr *fex;
X
X if (debug>2) { fprintf(outf,"chg_printf("); dumpexpr(ex); fprintf(outf, ")\n"); }
X if (!strcmp(ex->val.s, "putchar")) {
X ex = makeexpr_sprintfify(grabarg(ex, 0));
X canceltempvar(istempvar(ex->args[0]));
X strchange(&ex->val.s, "printf");
X delfreearg(&ex, 0);
X ex->val.type = tp_void;
X } else if (!strcmp(ex->val.s, "putc") ||
X !strcmp(ex->val.s, "fputc") ||
X !strcmp(ex->val.s, "fputs")) {
X fex = copyexpr(ex->args[1]);
X ex = makeexpr_sprintfify(grabarg(ex, 0));
X canceltempvar(istempvar(ex->args[0]));
X strchange(&ex->val.s, "fprintf");
X ex->args[0] = fex;
X ex->val.type = tp_void;
X } else if (!strcmp(ex->val.s, "puts")) {
X ex = makeexpr_concat(makeexpr_sprintfify(grabarg(ex, 0)),
X makeexpr_string("\n"), 1);
X strchange(&ex->val.s, "printf");
X delfreearg(&ex, 0);
X ex->val.type = tp_void;
X }
X if (!strcmp(ex->val.s, "fprintf") && exprsame(ex->args[0], ex_output, 1)) {
X delfreearg(&ex, 0);
X strchange(&ex->val.s, "printf");
X }
X return ex;
X}
X
X
XExpr *mix_printf(ex, ex2)
XExpr *ex, *ex2;
X{
X int i;
X
X ex = chg_printf(ex);
X if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex); fprintf(outf, "\n"); }
X ex2 = chg_printf(copyexpr(ex2));
X if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex2);fprintf(outf, "\n"); }
X i = (!strcmp(ex->val.s, "printf")) ? 0 : 1;
X ex->args[i] = makeexpr_concat(ex->args[i], ex2->args[i], 0);
X for (i++; i < ex2->nargs; i++) {
X insertarg(&ex, ex->nargs, ex2->args[i]);
X }
X return ex;
X}
X
X
X
X
X
X
Xvoid eatstmt(spp)
XStmt **spp;
X{
X Stmt *sp = *spp;
X
X if (debug>2) { fprintf(outf, "eatstmt on:\n"); dumpstmt(sp, 5); }
X *spp = sp->next;
X sp->next = NULL;
X free_stmt(sp);
X}
X
X
X
Xint haslabels(sp)
XStmt *sp;
X{
X if (!sp)
X return 0;
X if (haslabels(sp->stm1) || haslabels(sp->stm2))
X return 1;
X return (sp->kind == SK_LABEL);
X}
X
X
X
Xvoid fixblock(spp, thereturn)
XStmt **spp, *thereturn;
X{
X Stmt *sp, *sp1, *sp2, *sp3, **spp2, *thisreturn;
X Expr *ex;
X Meaning *tvar, *mp;
X int save_tryblock;
X short save_tryflag;
X int i, j, de1, de2;
X long saveserial = curserial;
X
X while ((sp = *spp)) {
X sp2 = sp->next;
X sp->next = NULL;
X sp = fix_statement(*spp);
X if (!sp) {
X *spp = sp2;
X continue;
X }
X *spp = sp;
X for (sp3 = sp; sp3->next; sp3 = sp3->next) ;
X sp3->next = sp2;
X if (!sp->next)
X thisreturn = thereturn;
X else if (sp->next->kind == SK_RETURN ||
X (sp->next->kind == SK_ASSIGN &&
X isescape(sp->next->exp1)))
X thisreturn = sp->next;
X else
X thisreturn = NULL;
X if (sp->serial >= 0)
X curserial = sp->serial;
X switch (sp->kind) {
X
X case SK_ASSIGN:
X if (sp->exp1)
X sp->exp1 = fixexpr(sp->exp1, ENV_STMT);
X if (!sp->exp1)
X intwarning("fixblock", "sp->exp1 == NULL in SK_ASSIGN");
X if (!sp->exp1 || nosideeffects(sp->exp1, 1)) {
X eatstmt(spp);
X continue;
X } else {
X switch (sp->exp1->kind) {
X
X case EK_COND:
X *spp = makestmt_if(sp->exp1->args[0],
X makestmt_call(sp->exp1->args[1]),
X makestmt_call(sp->exp1->args[2]));
X (*spp)->next = sp->next;
X continue; /* ... to fix this new if statement */
X
X case EK_ASSIGN:
X if (sp->exp1->args[1]->kind == EK_COND && usecommas != 1) {
X *spp = makestmt_if(sp->exp1->args[1]->args[0],
X makestmt_assign(copyexpr(sp->exp1->args[0]),
X sp->exp1->args[1]->args[1]),
X makestmt_assign(sp->exp1->args[0],
X sp->exp1->args[1]->args[2]));
X (*spp)->next = sp->next;
X continue;
X }
X if (isescape(sp->exp1->args[1])) {
X sp->exp1 = grabarg(sp->exp1, 1);
X continue;
X }
X if (exprsame(sp->exp1->args[0], sp->exp1->args[1], 1)) {
X /* *spp = sp->next; */
X sp->exp1 = grabarg(sp->exp1, 0);
X continue;
X }
X if (sp->exp1->args[1]->kind == EK_BICALL) {
X if (!strcmp(sp->exp1->args[1]->val.s,
X getfbufname) &&
X buildreads == 1 &&
X sp->next &&
X sp->next->kind == SK_ASSIGN &&
X sp->next->exp1->kind == EK_BICALL &&
X !strcmp(sp->next->exp1->val.s,
X getname) &&
X expr_has_address(sp->exp1->args[0]) &&
X similartypes(sp->exp1->args[0]->val.type,
X sp->exp1->args[1]->args[0]->val.type->basetype->basetype) &&
X exprsame(sp->exp1->args[1]->args[0],
X sp->next->exp1->args[0], 1)) {
X eatstmt(&sp->next);
X ex = makeexpr_bicall_4("fread", tp_integer,
X makeexpr_addr(sp->exp1->args[0]),
X makeexpr_sizeof(sp->exp1->args[1]->args[1], 0),
X makeexpr_long(1),
X sp->exp1->args[1]->args[0]);
X FREE(sp->exp1);
X sp->exp1 = ex;
X continue;
X }
X if (!strcmp(sp->exp1->args[1]->val.s,
X chargetfbufname) &&
X buildreads != 0 &&
X sp->next &&
X sp->next->kind == SK_ASSIGN &&
X sp->next->exp1->kind == EK_BICALL &&
X !strcmp(sp->next->exp1->val.s,
X chargetname) &&
X expr_has_address(sp->exp1->args[0]) &&
X exprsame(sp->exp1->args[1]->args[0],
X sp->next->exp1->args[0], 1)) {
X eatstmt(&sp->next);
X strchange(&sp->exp1->args[1]->val.s,
X "getc");
X continue;
X }
X }
X break;
X
X case EK_BICALL:
X if (!strcmp(sp->exp1->val.s, name_ESCAPE)) {
X if (fixexpr_tryblock) {
X *spp = makestmt_assign(makeexpr_var(mp_escapecode),
X grabarg(sp->exp1, 0));
X (*spp)->next = makestmt(SK_GOTO);
X (*spp)->next->exp1 = makeexpr_name(format_s(name_LABEL,
X format_d("try%d",
X fixexpr_tryblock)),
X tp_integer);
X (*spp)->next->next = sp->next;
X fixexpr_tryflag = 1;
X continue;
X }
X } else if (!strcmp(sp->exp1->val.s, name_ESCIO)) {
X if (fixexpr_tryblock) {
X *spp = makestmt_assign(makeexpr_var(mp_escapecode),
X makeexpr_long(-10));
X (*spp)->next = makestmt_assign(makeexpr_var(mp_ioresult),
X grabarg(sp->exp1, 0));
X (*spp)->next->next = makestmt(SK_GOTO);
X (*spp)->next->next->exp1 = makeexpr_name(format_s(name_LABEL,
X format_d("try%d",
X fixexpr_tryblock)),
X tp_integer);
X (*spp)->next->next->next = sp->next;
X fixexpr_tryflag = 1;
X continue;
X }
X }
X if (!strcmp(sp->exp1->val.s, putfbufname) &&
X buildwrites == 1 &&
X sp->next &&
X sp->next->kind == SK_ASSIGN &&
X sp->next->exp1->kind == EK_BICALL &&
X !strcmp(sp->next->exp1->val.s,
X putname) &&
X exprsame(sp->exp1->args[0],
X sp->next->exp1->args[0], 1)) {
X eatstmt(&sp->next);
X if (!expr_has_address(sp->exp1->args[2]) ||
X sp->exp1->args[2]->val.type !=
X sp->exp1->args[1]->val.type) {
X tvar = maketempvar(sp->exp1->args[1]->val.type,
X name_TEMP);
X sp2 = makestmt_assign(makeexpr_var(tvar),
X sp->exp1->args[2]);
X sp2->next = sp;
X *spp = sp2;
X sp->exp1->args[2] = makeexpr_var(tvar);
X freetempvar(tvar);
X }
X ex = makeexpr_bicall_4("fwrite", tp_integer,
X makeexpr_addr(sp->exp1->args[2]),
X makeexpr_sizeof(sp->exp1->args[1], 0),
X makeexpr_long(1),
X sp->exp1->args[0]);
X FREE(sp->exp1);
X sp->exp1 = ex;
X continue;
X }
X if (!strcmp(sp->exp1->val.s, charputfbufname) &&
X buildwrites != 0 &&
X sp->next &&
X sp->next->kind == SK_ASSIGN &&
X sp->next->exp1->kind == EK_BICALL &&
X !strcmp(sp->next->exp1->val.s,
X charputname) &&
X exprsame(sp->exp1->args[0],
X sp->next->exp1->args[0], 1)) {
X eatstmt(&sp->next);
X swapexprs(sp->exp1->args[0],
X sp->exp1->args[1]);
X strchange(&sp->exp1->val.s, "putc");
X continue;
X }
X if ((!strcmp(sp->exp1->val.s, resetbufname) ||
X !strcmp(sp->exp1->val.s, setupbufname)) &&
X (mp = isfilevar(sp->exp1->args[0])) != NULL &&
X !mp->bufferedfile) {
X eatstmt(spp);
X continue;
X }
X ex = print_func(sp->exp1);
X if (ex && sp->next && mixwritelns &&
X sp->next->kind == SK_ASSIGN &&
X exprsame(ex, print_func(sp->next->exp1), 1) &&
X (printnl_func(sp->exp1) ||
X printnl_func(sp->next->exp1))) {
X sp->exp1 = mix_printf(sp->exp1,
X sp->next->exp1);
X eatstmt(&sp->next);
X continue;
X }
X break;
X
X case EK_FUNCTION:
X case EK_SPCALL:
X case EK_POSTINC:
X case EK_POSTDEC:
X case EK_AND:
X case EK_OR:
X break;
X
X default:
X spp2 = spp;
X for (i = 0; i < sp->exp1->nargs; i++) {
X *spp2 = makestmt_call(sp->exp1->args[i]);
X spp2 = &(*spp2)->next;
X }
X *spp2 = sp->next;
X continue; /* ... to fix these new statements */
X
X }
X }
X break;
X
X case SK_IF:
X fixblock(&sp->stm1, thisreturn);
X fixblock(&sp->stm2, thisreturn);
X if (!sp->stm1) {
X if (!sp->stm2) {
X sp->kind = SK_ASSIGN;
X continue;
X } else {
X if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
X freeexpr(sp->stm2->exp2);
X sp->stm2->exp2 = NULL;
X }
X sp->exp1 = makeexpr_not(sp->exp1); /* if (x) else foo => if (!x) foo */
X swapstmts(sp->stm1, sp->stm2);
X /* Ought to exchange comments for then/else parts */
X }
X }
X /* At this point we know sp1 != NULL */
X if (thisreturn) {
X if (thisreturn->kind == SK_WHILE) {
X if (usebreaks) {
X sp1 = sp->stm1;
X while (sp1->next)
X sp1 = sp1->next;
X if (sp->stm2) {
X sp2 = sp->stm2;
X while (sp2->next)
X sp2 = sp2->next;
X i = stmtcount(sp->stm1);
X j = stmtcount(sp->stm2);
X if (j >= breaklimit && i <= 2 && j > i*2 &&
X ((implies(sp->exp1, thisreturn->exp1, 0, 1) &&
X !checkexprchanged(sp->stm1, sp->exp1)) ||
X (sp1->kind == SK_ASSIGN &&
X implies(sp1->exp1, thisreturn->exp1, 0, 1)))) {
X sp1->next = makestmt(SK_BREAK);
X } else if (i >= breaklimit && j <= 2 && i > j*2 &&
X ((implies(sp->exp1, thisreturn->exp1, 1, 1) &&
X !checkexprchanged(sp->stm2, sp->exp1)) ||
X (sp2->kind == SK_ASSIGN &&
X implies(sp2->exp1, thisreturn->exp1, 0, 1)))) {
X sp2->next = makestmt(SK_BREAK);
X } else if (!checkconst(sp->exp2, 1)) {
X /* not part of an else-if */
X if (j >= continuelimit) {
X sp1->next = makestmt(SK_CONTINUE);
X } else if (i >= continuelimit) {
X sp2->next = makestmt(SK_CONTINUE);
X }
X }
X } else {
X i = stmtcount(sp->stm1);
X if (i >= breaklimit &&
X implies(sp->exp1, thisreturn->exp1, 1, 1)) {
X sp->exp1 = makeexpr_not(sp->exp1);
X sp1->next = sp->next;
X sp->next = sp->stm1;
X sp->stm1 = makestmt(SK_BREAK);
X } else if (i >= continuelimit) {
X sp->exp1 = makeexpr_not(sp->exp1);
X sp1->next = sp->next;
X sp->next = sp->stm1;
X sp->stm1 = makestmt(SK_CONTINUE);
X }
X }
X }
X } else {
X if (usereturns) {
X sp2 = sp->stm1;
X while (sp2->next)
X sp2 = sp2->next;
X if (sp->stm2) {
X /* if (x) foo; else bar; (return;) => if (x) {foo; return;} bar; */
X if (stmtcount(sp->stm2) >= returnlimit) {
X if (!deadendblock(sp->stm1))
X sp2->next = copystmt(thisreturn);
X } else if (stmtcount(sp->stm1) >= returnlimit) {
X sp2 = sp->stm2;
X while (sp2->next)
X sp2 = sp2->next;
X if (!deadendblock(sp->stm2))
X sp2->next = copystmt(thisreturn);
X }
X } else { /* if (x) foo; (return;) => if (!x) return; foo; */
X if (stmtcount(sp->stm1) >= returnlimit) {
X sp->exp1 = makeexpr_not(sp->exp1);
X sp2->next = sp->next;
X sp->next = sp->stm1;
X sp->stm1 = copystmt(thisreturn);
X }
X }
X }
X }
X }
X if (!checkconst(sp->exp2, 1)) { /* not part of an else-if */
X de1 = deadendblock(sp->stm1);
X de2 = deadendblock(sp->stm2);
X if (de2 && !de1) {
X sp->exp1 = makeexpr_not(sp->exp1);
X swapstmts(sp->stm1, sp->stm2);
X de1 = 1, de2 = 0;
X }
X if (de1 && !de2 && sp->stm2) {
X if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
X freeexpr(sp->stm2->exp2);
X sp->stm2->exp2 = NULL;
X }
X for (sp2 = sp->stm2; sp2->next; sp2 = sp2->next) ;
X sp2->next = sp->next;
X sp->next = sp->stm2; /* if (x) ESCAPE else foo => if (x) ESCAPE; foo */
X sp->stm2 = NULL;
X }
X }
X sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
X break;
X
X case SK_WHILE:
X if (whilefgets && /* handle "while eof(f) do readln(f,...)" */
X sp->stm1->kind == SK_ASSIGN &&
X sp->stm1->exp1->kind == EK_BICALL &&
X !strcmp(sp->stm1->exp1->val.s, "fgets") &&
X nosideeffects(sp->stm1->exp1->args[0], 1) &&
X nosideeffects(sp->stm1->exp1->args[1], 1) &&
X nosideeffects(sp->stm1->exp1->args[2], 1)) {
X if ((sp->exp1->kind == EK_NOT &&
X sp->exp1->args[0]->kind == EK_BICALL && *eofname &&
X !strcmp(sp->exp1->args[0]->val.s, eofname) &&
X exprsame(sp->exp1->args[0]->args[0],
X sp->stm1->exp1->args[2], 1)) ||
X (sp->exp1->kind == EK_EQ &&
X sp->exp1->args[0]->kind == EK_BICALL &&
X !strcmp(sp->exp1->args[0]->val.s, "feof") &&
X checkconst(sp->exp1->args[1], 0) &&
X exprsame(sp->exp1->args[0]->args[0],
X sp->stm1->exp1->args[2], 1))) {
X sp->stm1->exp1->val.type = tp_strptr;
X sp->exp1 = makeexpr_rel(EK_NE,
X sp->stm1->exp1,
X makeexpr_nil());
X sp->stm1 = sp->stm1->next;
X }
X }
X fixblock(&sp->stm1, sp);
X sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
X if (checkconst(sp->exp1, 1))
X infiniteloop(sp);
X break;
X
X case SK_REPEAT:
X fixblock(&sp->stm1, NULL);
X sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
X if (checkconst(sp->exp1, 1))
X infiniteloop(sp);
X break;
X
X case SK_TRY:
X save_tryblock = fixexpr_tryblock;
X save_tryflag = fixexpr_tryflag;
X fixexpr_tryblock = sp->exp1->val.i;
X fixexpr_tryflag = 0;
X fixblock(&sp->stm1, NULL);
X if (fixexpr_tryflag)
X sp->exp2 = makeexpr_long(1);
X fixexpr_tryblock = save_tryblock;
X fixexpr_tryflag = save_tryflag;
X fixblock(&sp->stm2, NULL);
X break;
X
X case SK_BODY:
X fixblock(&sp->stm1, thisreturn);
X break;
X
X case SK_CASE:
X fixblock(&sp->stm1, NULL);
X sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
X if (!sp->stm1) { /* empty case */
X sp->kind = SK_ASSIGN;
X continue;
X } else if (sp->stm1->kind != SK_CASELABEL) { /* default only */
X for (sp2 = sp->stm1; sp2->next; sp2 = sp2->next) ;
X sp2->next = sp->next;
X sp->next = sp->stm1;
X sp->kind = SK_ASSIGN;
X sp->stm1 = NULL;
X continue;
X }
X break;
X
X default:
X fixblock(&sp->stm1, NULL);
X fixblock(&sp->stm2, NULL);
X sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
X sp->exp2 = fixexpr(sp->exp2, ENV_EXPR);
X sp->exp3 = fixexpr(sp->exp3, ENV_EXPR);
X if (sp->next &&
X (sp->kind == SK_GOTO ||
X sp->kind == SK_BREAK ||
X sp->kind == SK_CONTINUE ||
X sp->kind == SK_RETURN) &&
X !haslabels(sp->next)) {
X if (elimdeadcode) {
X note("Deleting unreachable code [255]");
X while (sp->next && !haslabels(sp->next))
X eatstmt(&sp->next);
X } else {
X note("Code is unreachable [256]");
X }
X } else if (sp->kind == SK_RETURN &&
X thisreturn &&
X thisreturn->kind == SK_RETURN &&
X exprsame(sp->exp1, thisreturn->exp1, 1)) {
X eatstmt(spp);
X continue;
X }
X break;
X }
X spp = &sp->next;
X }
X saveserial = curserial;
X}
X
X
X
X
X/* Convert comma expressions into multiple statements */
X
XStatic int checkcomma_expr(spp, exp)
XStmt **spp;
XExpr **exp;
X{
X Stmt *sp;
X Expr *ex = *exp;
X int i, res;
X
X switch (ex->kind) {
X
X case EK_COMMA:
X if (spp) {
X res = checkcomma_expr(spp, &ex->args[ex->nargs-1]);
X for (i = ex->nargs-1; --i >= 0; ) {
X sp = makestmt(SK_ASSIGN);
X sp->exp1 = ex->args[i];
X sp->next = *spp;
X *spp = sp;
X res = checkcomma_expr(spp, &ex->args[i]);
X }
X *exp = ex->args[ex->nargs-1];
X }
X return 1;
X
X case EK_COND:
X if (isescape(ex->args[1]) && spp &&
X !isescape(ex->args[2])) {
X swapexprs(ex->args[1], ex->args[2]);
X ex->args[0] = makeexpr_not(ex->args[0]);
X }
X if (isescape(ex->args[2])) {
X if (spp) {
X res = checkcomma_expr(spp, &ex->args[1]);
X if (ex->args[0]->kind == EK_ASSIGN) {
X sp = makestmt(SK_ASSIGN);
X sp->exp1 = copyexpr(ex->args[0]);
X sp->next = makestmt(SK_IF);
X sp->next->next = *spp;
X *spp = sp;
X res = checkcomma_expr(spp, &sp->exp1);
X ex->args[0] = grabarg(ex->args[0], 0);
X sp = sp->next;
X } else {
X sp = makestmt(SK_IF);
X sp->next = *spp;
X *spp = sp;
X }
X sp->exp1 = makeexpr_not(ex->args[0]);
X sp->stm1 = makestmt(SK_ASSIGN);
X sp->stm1->exp1 = eatcasts(ex->args[2]);
X res = checkcomma_expr(&sp->stm1, &ex->args[2]);
X res = checkcomma_expr(spp, &sp->exp1);
X *exp = ex->args[1];
X }
X return 1;
X }
X return checkcomma_expr(spp, &ex->args[0]);
X
X case EK_AND:
X case EK_OR:
X return checkcomma_expr(spp, &ex->args[0]);
X
X default:
X res = 0;
X for (i = ex->nargs; --i >= 0; ) {
X res += checkcomma_expr(spp, &ex->args[i]);
X }
X return res;
X
X }
X}
X
X
X
XStatic void checkcommas(spp)
XStmt **spp;
X{
X Stmt *sp;
X int res;
X
X while ((sp = *spp)) {
X checkcommas(&sp->stm1);
X checkcommas(&sp->stm2);
X switch (sp->kind) {
X
X case SK_ASSIGN:
X case SK_IF:
X case SK_CASE:
X case SK_RETURN:
X if (sp->exp1)
X res = checkcomma_expr(spp, &sp->exp1);
X break;
X
X case SK_WHILE:
X /* handle the argument */
X break;
X
X case SK_REPEAT:
X /* handle the argument */
X break;
X
X case SK_FOR:
X if (sp->exp1)
X res = checkcomma_expr(spp, &sp->exp1);
X /* handle the other arguments */
X break;
X
X default:
X break;
X }
X spp = &sp->next;
X }
X}
X
X
X
X
XStatic int checkvarchangeable(ex, mp)
XExpr *ex;
XMeaning *mp;
X{
X switch (ex->kind) {
X
X case EK_VAR:
X return (mp == (Meaning *)ex->val.i);
X
X case EK_DOT:
X case EK_INDEX:
X return checkvarchangeable(ex->args[0], mp);
X
X default:
X return 0;
X }
X}
X
X
X
Xint checkvarchangedexpr(ex, mp, addrokay)
XExpr *ex;
XMeaning *mp;
Xint addrokay;
X{
X int i;
X Meaning *mp3;
X unsigned int safemask = 0;
X
X switch (ex->kind) {
X
X case EK_FUNCTION:
X case EK_SPCALL:
X if (ex->kind == EK_FUNCTION) {
X i = 0;
X mp3 = ((Meaning *)ex->val.i)->type->fbase;
X } else {
X i = 1;
X if (ex->args[0]->val.type->kind != TK_PROCPTR)
X return 1;
X mp3 = ex->args[0]->val.type->basetype->fbase;
X }
X for ( ; i < ex->nargs && i < 16; i++) {
X if (!mp3) {
X intwarning("checkvarchangedexpr", "Too many arguments for EK_FUNCTION [266]");
X break;
X }
X if (mp3->kind == MK_PARAM &&
X (mp3->type->kind == TK_ARRAY ||
X mp3->type->kind == TK_STRING ||
X mp3->type->kind == TK_SET))
X safemask |= 1<<i;
X if (mp3->kind == MK_VARPARAM &&
X mp3->type == tp_strptr && mp3->anyvarflag)
X i++;
X mp3 = mp3->xnext;
X }
X if (mp3)
X intwarning("checkvarchangedexpr", "Too few arguments for EK_FUNCTION [267]");
X break;
X
X case EK_VAR:
X if (mp == (Meaning *)ex->val.i) {
X if ((mp->type->kind == TK_ARRAY ||
X mp->type->kind == TK_STRING ||
X mp->type->kind == TK_SET) &&
X ex->val.type->kind == TK_POINTER && !addrokay)
X return 1; /* must be an implicit & */
X }
X break;
X
X case EK_ADDR:
X case EK_ASSIGN:
X case EK_POSTINC:
X case EK_POSTDEC:
X if (checkvarchangeable(ex->args[0], mp))
X return 1;
X break;
X
X case EK_BICALL:
X if (structuredfunc(ex) && checkvarchangeable(ex->args[0], mp))
X return 1;
X safemask = safemask_bicall(ex->val.s);
X break;
X /* In case calls to these functions were lazy and passed
X the array rather than its (implicit) address. Other
X BICALLs had better be careful about their arguments. */
X
X case EK_PLUS:
X if (addrokay) /* to keep from being scared by pointer */
X safemask = ~0; /* arithmetic on string being passed */
X break; /* to functions. */
X
X default:
X break;
X }
X for (i = 0; i < ex->nargs; i++) {
X if (checkvarchangedexpr(ex->args[i], mp, safemask&1))
X return 1;
X safemask >>= 1;
X }
X return 0;
X}
X
X
X
Xint checkvarchanged(sp, mp)
XStmt *sp;
XMeaning *mp;
X{
X if (mp->constqual)
X return 0;
X if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION ||
X mp->volatilequal || alwayscopyvalues)
X return 1;
X while (sp) {
X if (/* sp->kind == SK_GOTO || */
X sp->kind == SK_LABEL ||
X checkvarchanged(sp->stm1, mp) ||
X checkvarchanged(sp->stm2, mp) ||
X (sp->exp1 && checkvarchangedexpr(sp->exp1, mp, 1)) ||
X (sp->exp2 && checkvarchangedexpr(sp->exp2, mp, 1)) ||
X (sp->exp3 && checkvarchangedexpr(sp->exp3, mp, 1)))
X return 1;
X sp = sp->next;
X }
X return 0;
X}
X
X
X
Xint checkexprchanged(sp, ex)
XStmt *sp;
XExpr *ex;
X{
X Meaning *mp;
X int i;
X
X for (i = 0; i < ex->nargs; i++) {
X if (checkexprchanged(sp, ex->args[i]))
X return 1;
X }
X switch (ex->kind) {
X
X case EK_VAR:
X mp = (Meaning *)ex->val.i;
X if (mp->kind == MK_CONST)
X return 0;
X else
X return checkvarchanged(sp, mp);
X
X case EK_HAT:
X case EK_INDEX:
X case EK_SPCALL:
X return 1;
X
X case EK_FUNCTION:
X case EK_BICALL:
X return !nosideeffects_func(ex);
X
X default:
X return 0;
X }
X}
X
X
X
X
X
X/* Check if a variable always occurs with a certain offset added, e.g. "i+1" */
X
XStatic int theoffset, numoffsets, numzerooffsets;
X#define BadOffset (-999)
X
Xvoid checkvaroffsetexpr(ex, mp, myoffset)
XExpr *ex;
XMeaning *mp;
Xint myoffset;
X{
X int i, nextoffset = 0;
X Expr *ex2;
X
X if (!ex)
X return;
X switch (ex->kind) {
X
X case EK_VAR:
X if (ex->val.i == (long)mp) {
X if (myoffset == 0)
X numzerooffsets++;
X else if (numoffsets == 0 || myoffset == theoffset) {
X theoffset = myoffset;
X numoffsets++;
X } else
X theoffset = BadOffset;
X }
X break;
X
X case EK_PLUS:
X ex2 = ex->args[ex->nargs-1];
X if (ex2->kind == EK_CONST &&
X ex2->val.type->kind == TK_INTEGER) {
X nextoffset = ex2->val.i;
X }
X break;
X
X case EK_HAT:
X case EK_POSTINC:
X case EK_POSTDEC:
X nextoffset = BadOffset;
X break;
X
X case EK_ASSIGN:
X checkvaroffsetexpr(ex->args[0], mp, BadOffset);
X checkvaroffsetexpr(ex->args[1], mp, 0);
X return;
X
X default:
X break;
X }
X i = ex->nargs;
X while (--i >= 0)
X checkvaroffsetexpr(ex->args[i], mp, nextoffset);
X}
X
X
Xvoid checkvaroffsetstmt(sp, mp)
XStmt *sp;
XMeaning *mp;
X{
X while (sp) {
X checkvaroffsetstmt(sp->stm1, mp);
X checkvaroffsetstmt(sp->stm1, mp);
X checkvaroffsetexpr(sp->exp1, mp, 0);
X checkvaroffsetexpr(sp->exp2, mp, 0);
X checkvaroffsetexpr(sp->exp3, mp, 0);
X sp = sp->next;
X }
X}
X
X
Xint checkvaroffset(sp, mp)
XStmt *sp;
XMeaning *mp;
X{
X if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION)
X return 0;
X numoffsets = 0;
X numzerooffsets = 0;
X checkvaroffsetstmt(sp, mp);
X if (numoffsets == 0 || theoffset == BadOffset ||
X numoffsets <= numzerooffsets * 3)
X return 0;
X else
X return theoffset;
X}
X
X
X
X
Xvoid initfilevars(mp, sppp, exbase)
XMeaning *mp;
XStmt ***sppp;
XExpr *exbase;
X{
X Stmt *sp;
X Type *tp;
X Expr *ex;
X
X while (mp) {
X if ((mp->kind == MK_VAR && mp->refcount > 0 && !mp->istemporary) ||
X mp->kind == MK_FIELD) {
X tp = mp->type;
X if (isfiletype(tp)) {
X mp->refcount++;
X sp = makestmt(SK_ASSIGN);
X sp->next = **sppp;
X **sppp = sp;
X if (exbase)
X ex = makeexpr_dot(copyexpr(exbase), mp);
X else
X ex = makeexpr_var(mp);
X sp->exp1 = makeexpr_assign(copyexpr(ex), makeexpr_nil());
X } else if (tp->kind == TK_RECORD) {
X if (exbase)
X ex = makeexpr_dot(copyexpr(exbase), mp);
X else
X ex = makeexpr_var(mp);
X initfilevars(tp->fbase, sppp, ex);
X freeexpr(ex);
X } else if (tp->kind == TK_ARRAY) {
X while (tp->kind == TK_ARRAY)
X tp = tp->basetype;
X if (isfiletype(tp))
X note(format_s("Array of files %s should be initialized [257]",
X mp->name));
X }
X }
X mp = mp->cnext;
X }
X}
X
X
X
X
X
XStatic Stmt *p_body()
X{
X Stmt *sp, **spp, *spbody, **sppbody, *spbase, *thereturn;
X Meaning *mp;
X Expr *ex;
X int haspostamble;
X long saveserial;
X
X if (verbose)
X fprintf(logf, "%s, %d/%d: Translating %s (in %s)\n",
X infname, inf_lnum, outf_lnum,
X curctx->name, curctx->ctx->name);
X notephase = 1;
X spp = &spbase;
X addstmt(SK_HEADER);
X sp->exp1 = makeexpr_var(curctx);
X checkkeyword(TOK_INLINE);
X if (curtok != TOK_END && curtok != TOK_BEGIN && curtok != TOK_INLINE) {
X if (curctx->kind == MK_FUNCTION || curctx->anyvarflag)
X wexpecttok(TOK_BEGIN);
X else
X wexpecttok(TOK_END);
X skiptotoken2(TOK_BEGIN, TOK_END);
X }
X if (curtok == TOK_END) {
X gettok();
X spbody = NULL;
X } else {
X spbody = p_stmt(NULL, SF_FUNC); /* parse the procedure/program body */
X }
X if (curtok == TOK_IDENT && curtokmeaning == curctx) {
X gettok(); /* Modula-2 */
X }
X notephase = 2;
X saveserial = curserial;
X curserial = 10000;
X if (curctx->kind == MK_FUNCTION) { /* handle copy parameters */
X for (mp = curctx->type->fbase; mp; mp = mp->xnext) {
X if (!mp->othername && mp->varstructflag) {
X mp->othername = stralloc(format_s(name_COPYPAR, mp->name));
X mp->rectype = mp->type;
X addstmt(SK_ASSIGN);
X sp->exp1 = makeexpr_assign(makeexpr_var(mp),
X makeexpr_name(mp->othername, mp->rectype));
X mp->refcount++;
X } else if (mp->othername) {
X if (checkvarchanged(spbody, mp)) {
X addstmt(SK_ASSIGN);
X sp->exp1 = makeexpr_assign(makeexpr_var(mp),
X makeexpr_hat(makeexpr_name(mp->othername,
X mp->rectype), 0));
X mp->refcount++;
X } else { /* don't need to copy it after all */
X strchange(&mp->othername, mp->name);
X ex = makeexpr_var(mp);
X ex->val.type = mp->rectype;
X replaceexpr(spbody, makeexpr_var(mp), makeexpr_hat(ex, 0));
X }
X }
X }
X }
X for (mp = curctx->cbase; mp; mp = mp->cnext) {
X if (mp->kind == MK_LABEL && mp->val.i) {
X addstmt(SK_IF);
X sp->exp1 = makeexpr_bicall_1("setjmp", tp_int,
X makeexpr_var(mp->xnext));
X sp->stm1 = makestmt(SK_GOTO);
X sp->stm1->exp1 = makeexpr_name(format_s(name_LABEL, mp->name),
X tp_integer);
X }
X }
X *spp = spbody;
X sppbody = spp;
X while (*spp)
X spp = &((*spp)->next);
X haspostamble = 0;
X initfilevars(curctx->cbase, &sppbody, NULL);
X for (mp = curctx->cbase; mp; mp = mp->cnext) {
X if (mp->kind == MK_VAR && mp->refcount > 0 && isfiletype(mp->type) &&
X !mp->istemporary) {
X if (curctx->kind != MK_MODULE || curctx->anyvarflag) {
X addstmt(SK_IF); /* close file variables */
X sp->exp1 = makeexpr_rel(EK_NE, makeexpr_var(mp), makeexpr_nil());
X sp->stm1 = makestmt(SK_ASSIGN);
X sp->stm1->exp1 = makeexpr_bicall_1("fclose", tp_void, makeexpr_var(mp));
X }
X haspostamble = 1;
X }
X }
X thereturn = &bogusreturn;
X if (curctx->kind == MK_FUNCTION && curctx->type->basetype != tp_void) {
X if ((haspostamble || !checkreturns(&spbase, 1)) &&
X curctx->cbase->refcount > 0) { /* add function return code */
X addstmt(SK_RETURN);
X sp->exp1 = makeexpr_var(curctx->cbase);
X }
X thereturn = NULL;
X } else if (curctx->kind == MK_MODULE && curctx->anyvarflag) {
X addstmt(SK_ASSIGN);
X sp->exp1 = makeexpr_bicall_1("exit", tp_void, makeexpr_long(0));
X thereturn = NULL;
X }
X if (debug>2) { fprintf(outf, "calling fixblock/usecommas on:\n"); dumpstmt(spbase, 5); }
X curserial = saveserial;
X sp = makestmt(SK_BODY);
X sp->stm1 = spbase;
X fixblock(&sp, thereturn); /* finishing touches to statements and expressions */
X spbase = sp->stm1;
X FREE(sp);
X if (usecommas != 1)
X checkcommas(&spbase); /* unroll ugly EK_COMMA and EK_COND expressions */
X if (debug>1) { fprintf(outf, "p_body returns:\n"); dumpstmt(spbase, 5); }
X notephase = 0;
X return spbase;
X}
X
X
X
X
X#define checkWord() if (anywords) output(" "); anywords = 1
X
XStatic void out_function(func)
XMeaning *func;
X{
X Meaning *mp;
X Symbol *sym;
X int opts, anywords, spacing, saveindent;
X
X if (func->varstructflag) {
X makevarstruct(func);
X }
X if (collectnest) {
X for (mp = func->cbase; mp; mp = mp->cnext) {
X if (mp->kind == MK_FUNCTION && mp->isforward) {
X forward_decl(mp, 0);
X }
X }
X for (mp = func->cbase; mp; mp = mp->cnext) {
X if (mp->kind == MK_FUNCTION && mp->type) {
X pushctx(mp);
X out_function(mp); /* generate the sub-procedures first */
X popctx();
X }
X }
X }
X spacing = functionspace;
X for (mp = func; mp->ctx->kind == MK_FUNCTION; mp = mp->ctx) {
X if (spacing > minfuncspace)
X spacing--;
X }
X outsection(spacing);
X flushcomments(&func->comments, -1, 0);
X if (usePPMacros == 1) {
X forward_decl(func, 0);
X outsection(minorspace);
X }
X opts = ODECL_HEADER;
X anywords = 0;
X if (func->namedfile) {
X checkWord();
X if (useAnyptrMacros || ansiC < 2)
X output("Inline");
X else
X output("inline");
X }
X if (!func->exported) {
X if (func->ctx->kind == MK_FUNCTION) {
X if (useAnyptrMacros) {
X checkWord();
X output("Local");
X } else if (use_static) {
X checkWord();
X output("static");
X }
X } else if ((findsymbol(func->name)->flags & NEEDSTATIC) ||
X (use_static != 0 && !useAnyptrMacros)) {
X checkWord();
X output("static");
X } else if (useAnyptrMacros) {
X checkWord();
X output("Static");
X }
X }
X if (func->type->basetype != tp_void || ansiC != 0) {
X checkWord();
X outbasetype(func->type, 0);
X }
X if (anywords) {
X if (newlinefunctions)
X opts |= ODECL_FUNCTION;
X else
X output(" ");
X }
X outdeclarator(func->type, func->name, opts);
X if (fullprototyping == 0) {
X saveindent = outindent;
X moreindent(argindent);
X out_argdecls(func->type);
X outindent = saveindent;
X }
X for (mp = func->type->fbase; mp; mp = mp->xnext) {
X if (mp->othername && strcmp(mp->name, mp->othername))
X mp->wasdeclared = 0; /* make sure we also declare the copy */
X }
X func->wasdeclared = 1;
X outcontext = func;
X out_block((Stmt *)func->val.i, BR_FUNCTION, 10000);
X if (useundef) {
X anywords = 0;
X for (mp = func->cbase; mp; mp = mp->cnext) {
X if (mp->kind == MK_CONST &&
END_OF_FILE
if test 49392 -ne `wc -c <'src/parse.c.2'`; then
echo shar: \"'src/parse.c.2'\" unpacked with wrong size!
fi
# end of 'src/parse.c.2'
fi
echo shar: End of archive 30 \(of 32\).
cp /dev/null ark30isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 32 archives.
echo "Now see PACKNOTES and the README"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0