parse.c.2
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:48k
源码类别:

编译器/解释器

开发平台:

C/C++

  1.                         if (spnextreturn) {
  2.                             mp->refcount--;
  3.                             sp->next = sp->next->next;
  4.                         }
  5.                         result = 1;
  6.                     }
  7.                 }
  8.                 break;
  9.             case SK_RETURN:
  10.             case SK_GOTO:
  11.                 result = 1;
  12.                 break;
  13.             case SK_IF:
  14.                 result = checkreturns(&sp->stm1, spnearret) &    /* NOT && */
  15.                          checkreturns(&sp->stm2, spnearret);
  16.                 break;
  17.             case SK_TRY:
  18.                 (void) checkreturns(&sp->stm1, 0);
  19.                 (void) checkreturns(&sp->stm2, spnearret);
  20.                 break;
  21.             /* should handle CASE statements as well */
  22.             default:
  23.                 (void) checkreturns(&sp->stm1, 0);
  24.                 (void) checkreturns(&sp->stm2, 0);
  25.                 break;
  26.         }
  27.         spp = &sp->next;
  28.     }
  29.     return result;
  30. }
  31. /* Replace all occurrences of one expression with another expression */
  32. Expr *replaceexprexpr(ex, oldex, newex)
  33. Expr *ex, *oldex, *newex;
  34. {
  35.     int i;
  36.     Type *type;
  37.     for (i = 0; i < ex->nargs; i++)
  38.         ex->args[i] = replaceexprexpr(ex->args[i], oldex, newex);
  39.     if (exprsame(ex, oldex, 2)) {
  40.         if (ex->val.type->kind == TK_POINTER &&
  41.             ex->val.type->basetype == oldex->val.type) {
  42.             freeexpr(ex);
  43.             return makeexpr_addr(copyexpr(newex));
  44.         } else if (oldex->val.type->kind == TK_POINTER &&
  45.                    oldex->val.type->basetype == ex->val.type) {
  46.             freeexpr(ex);
  47.             return makeexpr_hat(copyexpr(newex), 0);
  48.         } else {
  49.     type = ex->val.type;
  50.             freeexpr(ex);
  51.             ex = copyexpr(newex);
  52.     ex->val.type = type;
  53.     return ex;
  54.         }
  55.     }
  56.     return resimplify(ex);
  57. }
  58. void replaceexpr(sp, oldex, newex)
  59. Stmt *sp;
  60. Expr *oldex, *newex;
  61. {
  62.     while (sp) {
  63.         replaceexpr(sp->stm1, oldex, newex);
  64.         replaceexpr(sp->stm2, oldex, newex);
  65.         if (sp->exp1)
  66.             sp->exp1 = replaceexprexpr(sp->exp1, oldex, newex);
  67.         if (sp->exp2)
  68.             sp->exp2 = replaceexprexpr(sp->exp2, oldex, newex);
  69.         if (sp->exp3)
  70.             sp->exp3 = replaceexprexpr(sp->exp3, oldex, newex);
  71.         sp = sp->next;
  72.     }
  73. }
  74. Stmt *mixassignments(sp, mp)
  75. Stmt *sp;
  76. Meaning *mp;
  77. {
  78.     if (!sp)
  79.         return NULL;
  80.     sp->next = mixassignments(sp->next, mp);
  81.     if (sp->next &&
  82.  sp->kind == SK_ASSIGN &&
  83.          sp->exp1->kind == EK_ASSIGN &&
  84.          sp->exp1->args[0]->kind == EK_VAR &&
  85.          (!mp || mp == (Meaning *)sp->exp1->args[0]->val.i) &&
  86.          ord_type(sp->exp1->args[0]->val.type)->kind == TK_INTEGER &&
  87.          nodependencies(sp->exp1->args[1], 0) &&
  88.          sp->next->kind == SK_ASSIGN &&
  89.          sp->next->exp1->kind == EK_ASSIGN &&
  90.          (exprsame(sp->exp1->args[0], sp->next->exp1->args[0], 1) ||
  91.           (mp && mp->istemporary)) &&
  92.          exproccurs(sp->next->exp1->args[1], sp->exp1->args[0]) == 1) {
  93.         sp->next->exp1->args[1] = replaceexprexpr(sp->next->exp1->args[1],
  94.                                                   sp->exp1->args[0],
  95.                                                   sp->exp1->args[1]);
  96.         if (mp && mp->istemporary)
  97.             canceltempvar(mp);
  98.         return sp->next;
  99.     }
  100.     return sp;
  101. }
  102. /* Do various simple (sometimes necessary) massages on the statements */
  103. Static Stmt bogusreturn = { SK_RETURN, NULL, NULL, NULL, NULL, NULL, NULL };
  104. Static int isescape(ex)
  105. Expr *ex;
  106. {
  107.     if (ex->kind == EK_BICALL && (!strcmp(ex->val.s, name_ESCAPE) ||
  108.                                   !strcmp(ex->val.s, name_ESCIO) ||
  109.   !strcmp(ex->val.s, name_OUTMEM) ||
  110.   !strcmp(ex->val.s, name_CASECHECK) ||
  111.   !strcmp(ex->val.s, name_NILCHECK) ||
  112.                                   !strcmp(ex->val.s, "_exit") ||
  113.                                   !strcmp(ex->val.s, "exit")))
  114.         return 1;
  115.     if (ex->kind == EK_CAST)
  116.         return isescape(ex->args[0]);
  117.     return 0;
  118. }
  119. /* check if a block can never exit by falling off the end */
  120. Static int deadendblock(sp)
  121. Stmt *sp;
  122. {
  123.     if (!sp)
  124.         return 0;
  125.     while (sp->next)
  126.         sp = sp->next;
  127.     return (sp->kind == SK_GOTO ||
  128.             sp->kind == SK_BREAK ||
  129.             sp->kind == SK_CONTINUE ||
  130.             sp->kind == SK_RETURN ||
  131.             sp->kind == SK_CASECHECK ||
  132.             (sp->kind == SK_IF && deadendblock(sp->stm1) &&
  133.                                   deadendblock(sp->stm2)) ||
  134.             (sp->kind == SK_ASSIGN && isescape(sp->exp1)));
  135. }
  136. int expr_is_bool(ex, want)
  137. Expr *ex;
  138. int want;
  139. {
  140.     long val;
  141.     if (ex->val.type == tp_boolean && isconstexpr(ex, &val))
  142.         return (val == want);
  143.     return 0;
  144. }
  145. /* Returns 1 if c1 implies c2, 0 otherwise */
  146. /* If not1 is true, then checks if (!c1) implies c2; similarly for not2 */
  147. /* Identities used:
  148.         c1 -> (c2a && c2b)      <=>     (c1 -> c2a) && (c1 -> c2b)
  149.         c1 -> (c2a || c2b)      <=>     (c1 -> c2a) || (c1 -> c2b)
  150.         (c1a && c1b) -> c2      <=>     (c1a -> c2) || (c1b -> c2)
  151.         (c1a || c1b) -> c2      <=>     (c1a -> c2) && (c1b -> c2)
  152.         (!c1) -> (!c2)          <=>     c2 -> c1
  153.         (a == b) -> c2(b)       <=>     c2(a)
  154.         !(c1 && c2)             <=>     (!c1) || (!c2)
  155.         !(c1 || c2)             <=>     (!c1) && (!c2)
  156. */
  157. /* This could be smarter about, e.g., (a>5) -> (a>0) */
  158. int implies(c1, c2, not1, not2)
  159. Expr *c1, *c2;
  160. int not1, not2;
  161. {
  162.     Expr *ex;
  163.     int i;
  164.     if (c1->kind == EK_EQ && c1->args[0]->val.type == tp_boolean) {
  165.         if (checkconst(c1->args[0], 1)) {     /* things like "flag = true" */
  166.             return implies(c1->args[1], c2, not1, not2);
  167.         } else if (checkconst(c1->args[1], 1)) {
  168.             return implies(c1->args[0], c2, not1, not2);
  169.         } else if (checkconst(c1->args[0], 0)) {
  170.             return implies(c1->args[1], c2, !not1, not2);
  171.         } else if (checkconst(c1->args[1], 0)) {
  172.             return implies(c1->args[0], c2, !not1, not2);
  173.         }
  174.     }
  175.     if (c2->kind == EK_EQ && c2->args[0]->val.type == tp_boolean) {
  176.         if (checkconst(c2->args[0], 1)) {
  177.             return implies(c1, c2->args[1], not1, not2);
  178.         } else if (checkconst(c2->args[1], 1)) {
  179.             return implies(c1, c2->args[0], not1, not2);
  180.         } else if (checkconst(c2->args[0], 0)) {
  181.             return implies(c1, c2->args[1], not1, !not2);
  182.         } else if (checkconst(c2->args[1], 0)) {
  183.             return implies(c1, c2->args[0], not1, !not2);
  184.         }
  185.     }
  186.     switch (c2->kind) {
  187.         case EK_AND:
  188.             if (not2)               /* c1 -> (!c2a || !c2b) */
  189.                 return (implies(c1, c2->args[0], not1, 1) ||
  190.                         implies(c1, c2->args[1], not1, 1));
  191.             else                    /* c1 -> (c2a && c2b) */
  192.                 return (implies(c1, c2->args[0], not1, 0) &&
  193.                         implies(c1, c2->args[1], not1, 0));
  194.         case EK_OR:
  195.             if (not2)               /* c1 -> (!c2a && !c2b) */
  196.                 return (implies(c1, c2->args[0], not1, 1) &&
  197.                         implies(c1, c2->args[1], not1, 1));
  198.             else                    /* c1 -> (c2a || c2b) */
  199.                 return (implies(c1, c2->args[0], not1, 0) ||
  200.                         implies(c1, c2->args[1], not1, 0));
  201.         case EK_NOT:                /* c1 -> (!c2) */
  202.             return (implies(c1, c2->args[0], not1, !not2));
  203.         case EK_CONST:
  204.             if ((c2->val.i != 0) != not2)  /* c1 -> true */
  205.                 return 1;
  206.             break;
  207. default:
  208.     break;
  209.     }
  210.     switch (c1->kind) {
  211.         case EK_AND:
  212.             if (not1)               /* (!c1a || !c1b) -> c2 */
  213.                 return (implies(c1->args[0], c2, 1, not2) &&
  214.                         implies(c1->args[1], c2, 1, not2));
  215.             else                    /* (c1a && c1b) -> c2 */
  216.                 return (implies(c1->args[0], c2, 0, not2) ||
  217.                         implies(c1->args[1], c2, 0, not2));
  218.         case EK_OR:
  219.             if (not1)               /* (!c1a && !c1b) -> c2 */
  220.                 return (implies(c1->args[0], c2, 1, not2) ||
  221.                         implies(c1->args[1], c2, 1, not2));
  222.             else                    /* (c1a || c1b) -> c2 */
  223.                 return (implies(c1->args[0], c2, 0, not2) &&
  224.                         implies(c1->args[1], c2, 0, not2));
  225.         case EK_NOT:                /* (!c1) -> c2 */
  226.             return (implies(c1->args[0], c2, !not1, not2));
  227.         case EK_CONST:
  228.             if ((c1->val.i != 0) == not1)  /*  false -> c2 */
  229.                 return 1;
  230.             break;
  231.         case EK_EQ:                 /* (a=b) -> c2 */
  232.         case EK_ASSIGN:             /* (a:=b) -> c2 */
  233.         case EK_NE:                 /* (a<>b) -> c2 */
  234.             if ((c1->kind == EK_NE) == not1) {
  235.                 if (c1->args[0]->kind == EK_VAR) {
  236.                     ex = replaceexprexpr(copyexpr(c2), c1->args[0], c1->args[1]);
  237.                     i = expr_is_bool(ex, !not2);
  238.                     freeexpr(ex);
  239.                     if (i)
  240.                         return 1;
  241.                 }
  242.                 if (c1->args[1]->kind == EK_VAR) {
  243.                     ex = replaceexprexpr(copyexpr(c2), c1->args[1], c1->args[0]);
  244.                     i = expr_is_bool(ex, !not2);
  245.                     freeexpr(ex);
  246.                     if (i)
  247.                         return 1;
  248.                 }
  249.             }
  250.             break;
  251. default:
  252.     break;
  253.     }
  254.     if (not1 == not2 && exprequiv(c1, c2)) {    /* c1 -> c1 */
  255.         return 1;
  256.     }
  257.     return 0;
  258. }
  259. void infiniteloop(sp)
  260. Stmt *sp;
  261. {
  262.     switch (infloopstyle) {
  263.         case 1:      /* write "for (;;) ..." */
  264.             sp->kind = SK_FOR;
  265.             freeexpr(sp->exp1);
  266.             sp->exp1 = NULL;
  267.             break;
  268.         case 2:      /* write "while (1) ..." */
  269.             sp->kind = SK_WHILE;
  270.             freeexpr(sp->exp1);
  271.             sp->exp1 = makeexpr_val(make_ord(tp_boolean, 1));
  272.             break;
  273.         case 3:      /* write "do ... while (1)" */
  274.             sp->kind = SK_REPEAT;
  275.             freeexpr(sp->exp1);
  276.             sp->exp1 = makeexpr_val(make_ord(tp_boolean, 1));
  277.             break;
  278.         default:     /* leave it alone */
  279.             break;
  280.     }
  281. }
  282. Expr *print_func(ex)
  283. Expr *ex;
  284. {
  285.     if (!ex || ex->kind != EK_BICALL)
  286. return NULL;
  287.     if ((!strcmp(ex->val.s, "printf") &&
  288.  ex->args[0]->kind == EK_CONST) ||
  289. !strcmp(ex->val.s, "putchar") ||
  290. !strcmp(ex->val.s, "puts"))
  291. return ex_output;
  292.     if ((!strcmp(ex->val.s, "fprintf") ||
  293.  !strcmp(ex->val.s, "sprintf")) &&
  294. ex->args[1]->kind == EK_CONST)
  295. return ex->args[0];
  296.     if (!strcmp(ex->val.s, "putc") ||
  297. !strcmp(ex->val.s, "fputc") ||
  298. !strcmp(ex->val.s, "fputs"))
  299. return ex->args[1];
  300.     return NULL;
  301. }
  302. int printnl_func(ex)
  303. Expr *ex;
  304. {
  305.     char *cp, ch;
  306.     int i, len;
  307.     if (debug>2) { fprintf(outf,"printnl_func("); dumpexpr(ex); fprintf(outf, ")n"); }
  308.     if (!strcmp(ex->val.s, "printf") ||
  309. !strcmp(ex->val.s, "puts") ||
  310. !strcmp(ex->val.s, "fputs")) {
  311. if (ex->args[0]->kind != EK_CONST)
  312.     return 0;
  313. cp = ex->args[0]->val.s;
  314. len = ex->args[0]->val.i;
  315.     } else if (!strcmp(ex->val.s, "fprintf")) {
  316. if (ex->args[1]->kind != EK_CONST)
  317.     return 0;
  318. cp = ex->args[1]->val.s;
  319. len = ex->args[1]->val.i;
  320.     } else if (!strcmp(ex->val.s, "putchar") ||
  321.        !strcmp(ex->val.s, "putc") ||
  322.        !strcmp(ex->val.s, "fputc")) {
  323. if (ex->args[0]->kind != EK_CONST)
  324.     return 0;
  325. ch = ex->args[0]->val.i;
  326. cp = &ch;
  327. len = 1;
  328.     } else
  329. return 0;
  330.     for (i = 1; i <= len; i++)
  331. if (*cp++ != 'n')
  332.     return 0;
  333.     return len + (!strcmp(ex->val.s, "puts"));
  334. }
  335. Expr *chg_printf(ex)
  336. Expr *ex;
  337. {
  338.     Expr *fex;
  339.     if (debug>2) { fprintf(outf,"chg_printf("); dumpexpr(ex); fprintf(outf, ")n"); }
  340.     if (!strcmp(ex->val.s, "putchar")) {
  341. ex = makeexpr_sprintfify(grabarg(ex, 0));
  342. canceltempvar(istempvar(ex->args[0]));
  343. strchange(&ex->val.s, "printf");
  344. delfreearg(&ex, 0);
  345. ex->val.type = tp_void;
  346.     } else if (!strcmp(ex->val.s, "putc") ||
  347.        !strcmp(ex->val.s, "fputc") ||
  348.        !strcmp(ex->val.s, "fputs")) {
  349. fex = copyexpr(ex->args[1]);
  350. ex = makeexpr_sprintfify(grabarg(ex, 0));
  351. canceltempvar(istempvar(ex->args[0]));
  352. strchange(&ex->val.s, "fprintf");
  353. ex->args[0] = fex;
  354. ex->val.type = tp_void;
  355.     } else if (!strcmp(ex->val.s, "puts")) {
  356. ex = makeexpr_concat(makeexpr_sprintfify(grabarg(ex, 0)),
  357.      makeexpr_string("n"), 1);
  358. strchange(&ex->val.s, "printf");
  359. delfreearg(&ex, 0);
  360. ex->val.type = tp_void;
  361.     }
  362.     if (!strcmp(ex->val.s, "fprintf") && exprsame(ex->args[0], ex_output, 1)) {
  363. delfreearg(&ex, 0);
  364. strchange(&ex->val.s, "printf");
  365.     }
  366.     return ex;
  367. }
  368. Expr *mix_printf(ex, ex2)
  369. Expr *ex, *ex2;
  370. {
  371.     int i;
  372.     ex = chg_printf(ex);
  373.     if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex); fprintf(outf, "n"); }
  374.     ex2 = chg_printf(copyexpr(ex2));
  375.     if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex2);fprintf(outf, "n"); }
  376.     i = (!strcmp(ex->val.s, "printf")) ? 0 : 1;
  377.     ex->args[i] = makeexpr_concat(ex->args[i], ex2->args[i], 0);
  378.     for (i++; i < ex2->nargs; i++) {
  379. insertarg(&ex, ex->nargs, ex2->args[i]);
  380.     }
  381.     return ex;
  382. }
  383. void eatstmt(spp)
  384. Stmt **spp;
  385. {
  386.     Stmt *sp = *spp;
  387.     if (debug>2) { fprintf(outf, "eatstmt on:n"); dumpstmt(sp, 5); }
  388.     *spp = sp->next;
  389.     sp->next = NULL;
  390.     free_stmt(sp);
  391. }
  392. int haslabels(sp)
  393. Stmt *sp;
  394. {
  395.     if (!sp)
  396.         return 0;
  397.     if (haslabels(sp->stm1) || haslabels(sp->stm2))
  398.         return 1;
  399.     return (sp->kind == SK_LABEL);
  400. }
  401. void fixblock(spp, thereturn)
  402. Stmt **spp, *thereturn;
  403. {
  404.     Stmt *sp, *sp1, *sp2, *sp3, **spp2, *thisreturn;
  405.     Expr *ex;
  406.     Meaning *tvar, *mp;
  407.     int save_tryblock;
  408.     short save_tryflag;
  409.     int i, j, de1, de2;
  410.     long saveserial = curserial;
  411.     while ((sp = *spp)) {
  412.         sp2 = sp->next;
  413.         sp->next = NULL;
  414.         sp = fix_statement(*spp);
  415.         if (!sp) {
  416.             *spp = sp2;
  417.             continue;
  418.         }
  419.         *spp = sp;
  420.         for (sp3 = sp; sp3->next; sp3 = sp3->next) ;
  421.         sp3->next = sp2;
  422.         if (!sp->next)
  423.             thisreturn = thereturn;
  424.         else if (sp->next->kind == SK_RETURN ||
  425.                  (sp->next->kind == SK_ASSIGN &&
  426.                   isescape(sp->next->exp1)))
  427.             thisreturn = sp->next;
  428.         else
  429.             thisreturn = NULL;
  430. if (sp->serial >= 0)
  431.     curserial = sp->serial;
  432.         switch (sp->kind) {
  433.             case SK_ASSIGN:
  434.         if (sp->exp1)
  435.     sp->exp1 = fixexpr(sp->exp1, ENV_STMT);
  436. if (!sp->exp1)
  437.     intwarning("fixblock", "sp->exp1 == NULL in SK_ASSIGN");
  438.                 if (!sp->exp1 || nosideeffects(sp->exp1, 1)) {
  439.     eatstmt(spp);
  440.     continue;
  441.                 } else {
  442.                     switch (sp->exp1->kind) {
  443.                         case EK_COND:
  444.                             *spp = makestmt_if(sp->exp1->args[0],
  445.                                                makestmt_call(sp->exp1->args[1]),
  446.                                                makestmt_call(sp->exp1->args[2]));
  447.                             (*spp)->next = sp->next;
  448.                             continue;    /* ... to fix this new if statement */
  449.                         case EK_ASSIGN:
  450.                             if (sp->exp1->args[1]->kind == EK_COND && usecommas != 1) {
  451.                                 *spp = makestmt_if(sp->exp1->args[1]->args[0],
  452.                                                    makestmt_assign(copyexpr(sp->exp1->args[0]),
  453.                                                                    sp->exp1->args[1]->args[1]),
  454.                                                    makestmt_assign(sp->exp1->args[0],
  455.                                                                    sp->exp1->args[1]->args[2]));
  456.                                 (*spp)->next = sp->next;
  457.                                 continue;
  458.                             }
  459.     if (isescape(sp->exp1->args[1])) {
  460.                                 sp->exp1 = grabarg(sp->exp1, 1);
  461. continue;
  462.                             }
  463.     if (exprsame(sp->exp1->args[0], sp->exp1->args[1], 1)) {
  464.                               /*  *spp = sp->next;  */
  465.                                 sp->exp1 = grabarg(sp->exp1, 0);
  466.                                 continue;
  467.                             }
  468.     if (sp->exp1->args[1]->kind == EK_BICALL) {
  469. if (!strcmp(sp->exp1->args[1]->val.s,
  470.     getfbufname) &&
  471.     buildreads == 1 &&
  472.     sp->next &&
  473.     sp->next->kind == SK_ASSIGN &&
  474.     sp->next->exp1->kind == EK_BICALL &&
  475.     !strcmp(sp->next->exp1->val.s,
  476.     getname) &&
  477.     expr_has_address(sp->exp1->args[0]) &&
  478.     similartypes(sp->exp1->args[0]->val.type,
  479.  sp->exp1->args[1]->args[0]->val.type->basetype->basetype) &&
  480.     exprsame(sp->exp1->args[1]->args[0],
  481.      sp->next->exp1->args[0], 1)) {
  482.     eatstmt(&sp->next);
  483.     ex = makeexpr_bicall_4("fread", tp_integer,
  484.    makeexpr_addr(sp->exp1->args[0]),
  485.    makeexpr_sizeof(sp->exp1->args[1]->args[1], 0),
  486.    makeexpr_long(1),
  487.    sp->exp1->args[1]->args[0]);
  488.     FREE(sp->exp1);
  489.     sp->exp1 = ex;
  490.     continue;
  491. }
  492. if (!strcmp(sp->exp1->args[1]->val.s,
  493.     chargetfbufname) &&
  494.     buildreads != 0 &&
  495.     sp->next &&
  496.     sp->next->kind == SK_ASSIGN &&
  497.     sp->next->exp1->kind == EK_BICALL &&
  498.     !strcmp(sp->next->exp1->val.s,
  499.     chargetname) &&
  500.     expr_has_address(sp->exp1->args[0]) &&
  501.     exprsame(sp->exp1->args[1]->args[0],
  502.      sp->next->exp1->args[0], 1)) {
  503.     eatstmt(&sp->next);
  504.     strchange(&sp->exp1->args[1]->val.s,
  505.       "getc");
  506.     continue;
  507. }
  508.     }
  509.                             break;
  510.                         case EK_BICALL:
  511.                             if (!strcmp(sp->exp1->val.s, name_ESCAPE)) {
  512.                                 if (fixexpr_tryblock) {
  513.                                     *spp = makestmt_assign(makeexpr_var(mp_escapecode),
  514.                                                            grabarg(sp->exp1, 0));
  515.                                     (*spp)->next = makestmt(SK_GOTO);
  516.                                     (*spp)->next->exp1 = makeexpr_name(format_s(name_LABEL,
  517.                                                                                 format_d("try%d",
  518.                                                                                          fixexpr_tryblock)),
  519.                                                                        tp_integer);
  520.                                     (*spp)->next->next = sp->next;
  521.                                     fixexpr_tryflag = 1;
  522.                                     continue;
  523.                                 }
  524.                             } else if (!strcmp(sp->exp1->val.s, name_ESCIO)) {
  525.                                 if (fixexpr_tryblock) {
  526.                                     *spp = makestmt_assign(makeexpr_var(mp_escapecode),
  527.                                                            makeexpr_long(-10));
  528.                                     (*spp)->next = makestmt_assign(makeexpr_var(mp_ioresult),
  529.                                                                    grabarg(sp->exp1, 0));
  530.                                     (*spp)->next->next = makestmt(SK_GOTO);
  531.                                     (*spp)->next->next->exp1 = makeexpr_name(format_s(name_LABEL,
  532.                                                                                       format_d("try%d",
  533.                                                                                                fixexpr_tryblock)),
  534.                                                                              tp_integer);
  535.                                     (*spp)->next->next->next = sp->next;
  536.                                     fixexpr_tryflag = 1;
  537.                                     continue;
  538.                                 }
  539.                             }
  540.     if (!strcmp(sp->exp1->val.s, putfbufname) &&
  541. buildwrites == 1 &&
  542. sp->next &&
  543. sp->next->kind == SK_ASSIGN &&
  544. sp->next->exp1->kind == EK_BICALL &&
  545. !strcmp(sp->next->exp1->val.s,
  546. putname) &&
  547. exprsame(sp->exp1->args[0],
  548.  sp->next->exp1->args[0], 1)) {
  549. eatstmt(&sp->next);
  550. if (!expr_has_address(sp->exp1->args[2]) ||
  551.     sp->exp1->args[2]->val.type !=
  552.         sp->exp1->args[1]->val.type) {
  553.     tvar = maketempvar(sp->exp1->args[1]->val.type,
  554.    name_TEMP);
  555.     sp2 = makestmt_assign(makeexpr_var(tvar),
  556.   sp->exp1->args[2]);
  557.     sp2->next = sp;
  558.     *spp = sp2;
  559.     sp->exp1->args[2] = makeexpr_var(tvar);
  560.     freetempvar(tvar);
  561. }
  562. ex = makeexpr_bicall_4("fwrite", tp_integer,
  563.        makeexpr_addr(sp->exp1->args[2]),
  564.        makeexpr_sizeof(sp->exp1->args[1], 0),
  565.        makeexpr_long(1),
  566.        sp->exp1->args[0]);
  567. FREE(sp->exp1);
  568. sp->exp1 = ex;
  569. continue;
  570.     }
  571.     if (!strcmp(sp->exp1->val.s, charputfbufname) &&
  572. buildwrites != 0 &&
  573. sp->next &&
  574. sp->next->kind == SK_ASSIGN &&
  575. sp->next->exp1->kind == EK_BICALL &&
  576. !strcmp(sp->next->exp1->val.s,
  577. charputname) &&
  578. exprsame(sp->exp1->args[0],
  579.  sp->next->exp1->args[0], 1)) {
  580. eatstmt(&sp->next);
  581. swapexprs(sp->exp1->args[0],
  582.   sp->exp1->args[1]);
  583. strchange(&sp->exp1->val.s, "putc");
  584. continue;
  585.     }
  586.     if ((!strcmp(sp->exp1->val.s, resetbufname) ||
  587.  !strcmp(sp->exp1->val.s, setupbufname)) &&
  588. (mp = isfilevar(sp->exp1->args[0])) != NULL &&
  589. !mp->bufferedfile) {
  590. eatstmt(spp);
  591. continue;
  592.     }
  593.     ex = print_func(sp->exp1);
  594.     if (ex && sp->next && mixwritelns &&
  595. sp->next->kind == SK_ASSIGN &&
  596. exprsame(ex, print_func(sp->next->exp1), 1) &&
  597. (printnl_func(sp->exp1) ||
  598.  printnl_func(sp->next->exp1))) {
  599. sp->exp1 = mix_printf(sp->exp1,
  600.       sp->next->exp1);
  601. eatstmt(&sp->next);
  602. continue;
  603.     }
  604.                             break;
  605.                         case EK_FUNCTION:
  606.                         case EK_SPCALL:
  607.                         case EK_POSTINC:
  608.                         case EK_POSTDEC:
  609.                         case EK_AND:
  610.                         case EK_OR:
  611.                             break;
  612.                         default:
  613.                             spp2 = spp;
  614.                             for (i = 0; i < sp->exp1->nargs; i++) {
  615.                                 *spp2 = makestmt_call(sp->exp1->args[i]);
  616.                                 spp2 = &(*spp2)->next;
  617.                             }
  618.                             *spp2 = sp->next;
  619.                             continue;    /* ... to fix these new statements */
  620.                     }
  621.                 }
  622.                 break;
  623.             case SK_IF:
  624.                 fixblock(&sp->stm1, thisreturn);
  625.                 fixblock(&sp->stm2, thisreturn);
  626.                 if (!sp->stm1) {
  627.                     if (!sp->stm2) {
  628.                         sp->kind = SK_ASSIGN;
  629.                         continue;
  630.                     } else {
  631. if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
  632.     freeexpr(sp->stm2->exp2);
  633.     sp->stm2->exp2 = NULL;
  634. }
  635.                         sp->exp1 = makeexpr_not(sp->exp1);   /* if (x) else foo  =>  if (!x) foo */
  636.                         swapstmts(sp->stm1, sp->stm2);
  637. /* Ought to exchange comments for then/else parts */
  638.                     }
  639.                 }
  640. /* At this point we know sp1 != NULL */
  641.                 if (thisreturn) {
  642.                     if (thisreturn->kind == SK_WHILE) {
  643.                         if (usebreaks) {
  644.                             sp1 = sp->stm1;
  645.                             while (sp1->next)
  646.                                 sp1 = sp1->next;
  647.                             if (sp->stm2) {
  648. sp2 = sp->stm2;
  649. while (sp2->next)
  650.     sp2 = sp2->next;
  651.                                 i = stmtcount(sp->stm1);
  652.                                 j = stmtcount(sp->stm2);
  653.                                 if (j >= breaklimit && i <= 2 && j > i*2 &&
  654.                                     ((implies(sp->exp1, thisreturn->exp1, 0, 1) &&
  655.       !checkexprchanged(sp->stm1, sp->exp1)) ||
  656.      (sp1->kind == SK_ASSIGN &&
  657.       implies(sp1->exp1, thisreturn->exp1, 0, 1)))) {
  658.                                     sp1->next = makestmt(SK_BREAK);
  659.                                 } else if (i >= breaklimit && j <= 2 && i > j*2 &&
  660.                                            ((implies(sp->exp1, thisreturn->exp1, 1, 1) &&
  661.      !checkexprchanged(sp->stm2, sp->exp1)) ||
  662.     (sp2->kind == SK_ASSIGN &&
  663.      implies(sp2->exp1, thisreturn->exp1, 0, 1)))) {
  664.                                     sp2->next = makestmt(SK_BREAK);
  665. } else if (!checkconst(sp->exp2, 1)) {
  666.     /* not part of an else-if */
  667.     if (j >= continuelimit) {
  668. sp1->next = makestmt(SK_CONTINUE);
  669.     } else if (i >= continuelimit) {
  670. sp2->next = makestmt(SK_CONTINUE);
  671.     }
  672. }
  673.     } else {
  674.                                 i = stmtcount(sp->stm1);
  675.                                 if (i >= breaklimit &&
  676.                                     implies(sp->exp1, thisreturn->exp1, 1, 1)) {
  677.                                     sp->exp1 = makeexpr_not(sp->exp1);
  678.                                     sp1->next = sp->next;
  679.                                     sp->next = sp->stm1;
  680.                                     sp->stm1 = makestmt(SK_BREAK);
  681.                                 } else if (i >= continuelimit) {
  682.                                     sp->exp1 = makeexpr_not(sp->exp1);
  683.                                     sp1->next = sp->next;
  684.                                     sp->next = sp->stm1;
  685.                                     sp->stm1 = makestmt(SK_CONTINUE);
  686.                                 }
  687.                             }
  688.                         }
  689.                     } else {
  690.                         if (usereturns) {
  691.                             sp2 = sp->stm1;
  692.                             while (sp2->next)
  693.                                 sp2 = sp2->next;
  694.                             if (sp->stm2) {
  695.                                 /* if (x) foo; else bar; (return;)  =>  if (x) {foo; return;} bar; */
  696.                                 if (stmtcount(sp->stm2) >= returnlimit) {
  697.     if (!deadendblock(sp->stm1))
  698. sp2->next = copystmt(thisreturn);
  699.                                 } else if (stmtcount(sp->stm1) >= returnlimit) {
  700.                                     sp2 = sp->stm2;
  701.                                     while (sp2->next)
  702.                                         sp2 = sp2->next;
  703.     if (!deadendblock(sp->stm2))
  704. sp2->next = copystmt(thisreturn);
  705.                                 }
  706.                             } else {      /* if (x) foo; (return;)  =>  if (!x) return; foo; */
  707.                                 if (stmtcount(sp->stm1) >= returnlimit) {
  708.                                     sp->exp1 = makeexpr_not(sp->exp1);
  709.                                     sp2->next = sp->next;
  710.                                     sp->next = sp->stm1;
  711.                                     sp->stm1 = copystmt(thisreturn);
  712.                                 }
  713.                             }
  714.                         }
  715.                     }
  716.                 }
  717.                 if (!checkconst(sp->exp2, 1)) {    /* not part of an else-if */
  718.                     de1 = deadendblock(sp->stm1);
  719.                     de2 = deadendblock(sp->stm2);
  720.                     if (de2 && !de1) {
  721.                         sp->exp1 = makeexpr_not(sp->exp1);
  722.                         swapstmts(sp->stm1, sp->stm2);
  723.                         de1 = 1, de2 = 0;
  724.                     }
  725.                     if (de1 && !de2 && sp->stm2) {
  726. if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
  727.     freeexpr(sp->stm2->exp2);
  728.     sp->stm2->exp2 = NULL;
  729. }
  730.                         for (sp2 = sp->stm2; sp2->next; sp2 = sp2->next) ;
  731.                         sp2->next = sp->next;
  732.                         sp->next = sp->stm2;      /* if (x) ESCAPE else foo  =>  if (x) ESCAPE; foo */
  733.                         sp->stm2 = NULL;
  734.                     }
  735.                 }
  736.                 sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
  737.                 break;
  738.             case SK_WHILE:
  739.                 if (whilefgets &&    /* handle "while eof(f) do readln(f,...)" */
  740.     sp->stm1->kind == SK_ASSIGN &&
  741.     sp->stm1->exp1->kind == EK_BICALL &&
  742.     !strcmp(sp->stm1->exp1->val.s, "fgets") &&
  743.     nosideeffects(sp->stm1->exp1->args[0], 1) &&
  744.     nosideeffects(sp->stm1->exp1->args[1], 1) &&
  745.     nosideeffects(sp->stm1->exp1->args[2], 1)) {
  746.     if ((sp->exp1->kind == EK_NOT &&
  747.  sp->exp1->args[0]->kind == EK_BICALL && *eofname &&
  748.  !strcmp(sp->exp1->args[0]->val.s, eofname) &&
  749.  exprsame(sp->exp1->args[0]->args[0],
  750.   sp->stm1->exp1->args[2], 1)) ||
  751. (sp->exp1->kind == EK_EQ &&
  752.  sp->exp1->args[0]->kind == EK_BICALL &&
  753.  !strcmp(sp->exp1->args[0]->val.s, "feof") &&
  754.  checkconst(sp->exp1->args[1], 0) &&
  755.  exprsame(sp->exp1->args[0]->args[0],
  756.   sp->stm1->exp1->args[2], 1))) {
  757. sp->stm1->exp1->val.type = tp_strptr;
  758. sp->exp1 = makeexpr_rel(EK_NE,
  759. sp->stm1->exp1,
  760. makeexpr_nil());
  761. sp->stm1 = sp->stm1->next;
  762.     }
  763.                 }
  764.                 fixblock(&sp->stm1, sp);
  765.                 sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
  766.                 if (checkconst(sp->exp1, 1))
  767.                     infiniteloop(sp);
  768.                 break;
  769.             case SK_REPEAT:
  770.                 fixblock(&sp->stm1, NULL);
  771.                 sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
  772.                 if (checkconst(sp->exp1, 1))
  773.                     infiniteloop(sp);
  774.                 break;
  775.             case SK_TRY:
  776.                 save_tryblock = fixexpr_tryblock;
  777.                 save_tryflag = fixexpr_tryflag;
  778.                 fixexpr_tryblock = sp->exp1->val.i;
  779.                 fixexpr_tryflag = 0;
  780.                 fixblock(&sp->stm1, NULL);
  781.                 if (fixexpr_tryflag)
  782.                     sp->exp2 = makeexpr_long(1);
  783.                 fixexpr_tryblock = save_tryblock;
  784.                 fixexpr_tryflag = save_tryflag;
  785.                 fixblock(&sp->stm2, NULL);
  786.                 break;
  787.             case SK_BODY:
  788.                 fixblock(&sp->stm1, thisreturn);
  789.                 break;
  790.             case SK_CASE:
  791.                 fixblock(&sp->stm1, NULL);
  792.                 sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
  793.                 if (!sp->stm1) {    /* empty case */
  794.                     sp->kind = SK_ASSIGN;
  795.                     continue;
  796.                 } else if (sp->stm1->kind != SK_CASELABEL) {   /* default only */
  797.                     for (sp2 = sp->stm1; sp2->next; sp2 = sp2->next) ;
  798.                     sp2->next = sp->next;
  799.                     sp->next = sp->stm1;
  800.                     sp->kind = SK_ASSIGN;
  801.                     sp->stm1 = NULL;
  802.                     continue;
  803.                 }
  804.                 break;
  805.             default:
  806.                 fixblock(&sp->stm1, NULL);
  807.                 fixblock(&sp->stm2, NULL);
  808.                 sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
  809.                 sp->exp2 = fixexpr(sp->exp2, ENV_EXPR);
  810.                 sp->exp3 = fixexpr(sp->exp3, ENV_EXPR);
  811.                 if (sp->next &&
  812.                     (sp->kind == SK_GOTO ||
  813.                      sp->kind == SK_BREAK ||
  814.                      sp->kind == SK_CONTINUE ||
  815.                      sp->kind == SK_RETURN) &&
  816.                     !haslabels(sp->next)) {
  817.                     if (elimdeadcode) {
  818.                         note("Deleting unreachable code [255]");
  819.                         while (sp->next && !haslabels(sp->next))
  820.                             eatstmt(&sp->next);
  821.                     } else {
  822.                         note("Code is unreachable [256]");
  823.                     }
  824.                 } else if (sp->kind == SK_RETURN &&
  825.                            thisreturn &&
  826.                            thisreturn->kind == SK_RETURN &&
  827.                            exprsame(sp->exp1, thisreturn->exp1, 1)) {
  828.                     eatstmt(spp);
  829.     continue;
  830.                 }
  831.                 break;
  832.         }
  833.         spp = &sp->next;
  834.     }
  835.     saveserial = curserial;
  836. }
  837. /* Convert comma expressions into multiple statements */
  838. Static int checkcomma_expr(spp, exp)
  839. Stmt **spp;
  840. Expr **exp;
  841. {
  842.     Stmt *sp;
  843.     Expr *ex = *exp;
  844.     int i, res;
  845.     switch (ex->kind) {
  846.         case EK_COMMA:
  847.             if (spp) {
  848.                 res = checkcomma_expr(spp, &ex->args[ex->nargs-1]);
  849.                 for (i = ex->nargs-1; --i >= 0; ) {
  850.                     sp = makestmt(SK_ASSIGN);
  851.                     sp->exp1 = ex->args[i];
  852.                     sp->next = *spp;
  853.                     *spp = sp;
  854.                     res = checkcomma_expr(spp, &ex->args[i]);
  855.                 }
  856.                 *exp = ex->args[ex->nargs-1];
  857.             }
  858.             return 1;
  859.         case EK_COND:
  860.             if (isescape(ex->args[1]) && spp &&
  861.                 !isescape(ex->args[2])) {
  862.                 swapexprs(ex->args[1], ex->args[2]);
  863.                 ex->args[0] = makeexpr_not(ex->args[0]);
  864.             }
  865.             if (isescape(ex->args[2])) {
  866.                 if (spp) {
  867.                     res = checkcomma_expr(spp, &ex->args[1]);
  868.                     if (ex->args[0]->kind == EK_ASSIGN) {
  869.                         sp = makestmt(SK_ASSIGN);
  870.                         sp->exp1 = copyexpr(ex->args[0]);
  871.                         sp->next = makestmt(SK_IF);
  872.                         sp->next->next = *spp;
  873.                         *spp = sp;
  874.                         res = checkcomma_expr(spp, &sp->exp1);
  875.                         ex->args[0] = grabarg(ex->args[0], 0);
  876.                         sp = sp->next;
  877.                     } else {
  878.                         sp = makestmt(SK_IF);
  879.                         sp->next = *spp;
  880.                         *spp = sp;
  881.                     }
  882.                     sp->exp1 = makeexpr_not(ex->args[0]);
  883.                     sp->stm1 = makestmt(SK_ASSIGN);
  884.                     sp->stm1->exp1 = eatcasts(ex->args[2]);
  885.                     res = checkcomma_expr(&sp->stm1, &ex->args[2]);
  886.                     res = checkcomma_expr(spp, &sp->exp1);
  887.                     *exp = ex->args[1];
  888.                 }
  889.                 return 1;
  890.             }
  891.             return checkcomma_expr(spp, &ex->args[0]);
  892.         case EK_AND:
  893.         case EK_OR:
  894.             return checkcomma_expr(spp, &ex->args[0]);
  895. default:
  896.     res = 0;
  897.     for (i = ex->nargs; --i >= 0; ) {
  898. res += checkcomma_expr(spp, &ex->args[i]);
  899.     }
  900.     return res;
  901.     }
  902. }
  903. Static void checkcommas(spp)
  904. Stmt **spp;
  905. {
  906.     Stmt *sp;
  907.     int res;
  908.     while ((sp = *spp)) {
  909.         checkcommas(&sp->stm1);
  910.         checkcommas(&sp->stm2);
  911.         switch (sp->kind) {
  912.             case SK_ASSIGN:
  913.             case SK_IF:
  914.             case SK_CASE:
  915.             case SK_RETURN:
  916.                 if (sp->exp1)
  917.                     res = checkcomma_expr(spp, &sp->exp1);
  918.                 break;
  919.             case SK_WHILE:
  920.                 /* handle the argument */
  921.                 break;
  922.             case SK_REPEAT:
  923.                 /* handle the argument */
  924.                 break;
  925.             case SK_FOR:
  926. if (sp->exp1)
  927.     res = checkcomma_expr(spp, &sp->exp1);
  928.                 /* handle the other arguments */
  929.                 break;
  930.     default:
  931. break;
  932.         }
  933.         spp = &sp->next;
  934.     }
  935. }
  936. Static int checkvarchangeable(ex, mp)
  937. Expr *ex;
  938. Meaning *mp;
  939. {
  940.     switch (ex->kind) {
  941.         case EK_VAR:
  942.             return (mp == (Meaning *)ex->val.i);
  943.         case EK_DOT:
  944.         case EK_INDEX:
  945.             return checkvarchangeable(ex->args[0], mp);
  946. default:
  947.     return 0;
  948.     }
  949. }
  950. int checkvarchangedexpr(ex, mp, addrokay)
  951. Expr *ex;
  952. Meaning *mp;
  953. int addrokay;
  954. {
  955.     int i;
  956.     Meaning *mp3;
  957.     unsigned int safemask = 0;
  958.     switch (ex->kind) {
  959.         case EK_FUNCTION:
  960.         case EK_SPCALL:
  961.             if (ex->kind == EK_FUNCTION) {
  962.                 i = 0;
  963.                 mp3 = ((Meaning *)ex->val.i)->type->fbase;
  964.             } else {
  965.                 i = 1;
  966.                 if (ex->args[0]->val.type->kind != TK_PROCPTR)
  967.                     return 1;
  968.                 mp3 = ex->args[0]->val.type->basetype->fbase;
  969.             }
  970.             for ( ; i < ex->nargs && i < 16; i++) {
  971.                 if (!mp3) {
  972.                     intwarning("checkvarchangedexpr", "Too many arguments for EK_FUNCTION [266]");
  973.                     break;
  974.                 }
  975.                 if (mp3->kind == MK_PARAM &&
  976.                     (mp3->type->kind == TK_ARRAY ||
  977.                      mp3->type->kind == TK_STRING ||
  978.                      mp3->type->kind == TK_SET))
  979.                     safemask |= 1<<i;
  980.                 if (mp3->kind == MK_VARPARAM &&
  981.                     mp3->type == tp_strptr && mp3->anyvarflag)
  982.                     i++;
  983.                 mp3 = mp3->xnext;
  984.             }
  985.             if (mp3)
  986.                 intwarning("checkvarchangedexpr", "Too few arguments for EK_FUNCTION [267]");
  987.             break;
  988.         case EK_VAR:
  989.             if (mp == (Meaning *)ex->val.i) {
  990.                 if ((mp->type->kind == TK_ARRAY ||
  991.                      mp->type->kind == TK_STRING ||
  992.                      mp->type->kind == TK_SET) &&
  993.                     ex->val.type->kind == TK_POINTER && !addrokay)
  994.                     return 1;   /* must be an implicit & */
  995.             }
  996.             break;
  997.         case EK_ADDR:
  998.         case EK_ASSIGN:
  999.         case EK_POSTINC:
  1000.         case EK_POSTDEC:
  1001.             if (checkvarchangeable(ex->args[0], mp))
  1002.                 return 1;
  1003.             break;
  1004.         case EK_BICALL:
  1005.             if (structuredfunc(ex) && checkvarchangeable(ex->args[0], mp))
  1006.                 return 1;
  1007.             safemask = safemask_bicall(ex->val.s);
  1008.             break;
  1009.             /* In case calls to these functions were lazy and passed
  1010.                the array rather than its (implicit) address.  Other
  1011.                BICALLs had better be careful about their arguments. */
  1012.         case EK_PLUS:
  1013.             if (addrokay)         /* to keep from being scared by pointer */
  1014.                 safemask = ~0;    /*  arithmetic on string being passed */
  1015.             break;                /*  to functions. */
  1016. default:
  1017.     break;
  1018.     }
  1019.     for (i = 0; i < ex->nargs; i++) {
  1020.         if (checkvarchangedexpr(ex->args[i], mp, safemask&1))
  1021.             return 1;
  1022.         safemask >>= 1;
  1023.     }
  1024.     return 0;
  1025. }
  1026. int checkvarchanged(sp, mp)
  1027. Stmt *sp;
  1028. Meaning *mp;
  1029. {
  1030.     if (mp->constqual)
  1031. return 0;
  1032.     if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION ||
  1033.         mp->volatilequal || alwayscopyvalues)
  1034.         return 1;
  1035.     while (sp) {
  1036.         if (/* sp->kind == SK_GOTO || */
  1037.     sp->kind == SK_LABEL ||
  1038.             checkvarchanged(sp->stm1, mp) ||
  1039.             checkvarchanged(sp->stm2, mp) ||
  1040.             (sp->exp1 && checkvarchangedexpr(sp->exp1, mp, 1)) ||
  1041.             (sp->exp2 && checkvarchangedexpr(sp->exp2, mp, 1)) ||
  1042.             (sp->exp3 && checkvarchangedexpr(sp->exp3, mp, 1)))
  1043.             return 1;
  1044.         sp = sp->next;
  1045.     }
  1046.     return 0;
  1047. }
  1048. int checkexprchanged(sp, ex)
  1049. Stmt *sp;
  1050. Expr *ex;
  1051. {
  1052.     Meaning *mp;
  1053.     int i;
  1054.     for (i = 0; i < ex->nargs; i++) {
  1055.         if (checkexprchanged(sp, ex->args[i]))
  1056.             return 1;
  1057.     }
  1058.     switch (ex->kind) {
  1059.         case EK_VAR:
  1060.             mp = (Meaning *)ex->val.i;
  1061.             if (mp->kind == MK_CONST)
  1062.                 return 0;
  1063.             else
  1064.                 return checkvarchanged(sp, mp);
  1065.         case EK_HAT:
  1066.         case EK_INDEX:
  1067.         case EK_SPCALL:
  1068.             return 1;
  1069.         case EK_FUNCTION:
  1070.         case EK_BICALL:
  1071.             return !nosideeffects_func(ex);
  1072. default:
  1073.     return 0;
  1074.     }
  1075. }
  1076. /* Check if a variable always occurs with a certain offset added, e.g. "i+1" */
  1077. Static int theoffset, numoffsets, numzerooffsets;
  1078. #define BadOffset  (-999)
  1079. void checkvaroffsetexpr(ex, mp, myoffset)
  1080. Expr *ex;
  1081. Meaning *mp;
  1082. int myoffset;
  1083. {
  1084.     int i, nextoffset = 0;
  1085.     Expr *ex2;
  1086.     if (!ex)
  1087. return;
  1088.     switch (ex->kind) {
  1089.       case EK_VAR:
  1090. if (ex->val.i == (long)mp) {
  1091.     if (myoffset == 0)
  1092. numzerooffsets++;
  1093.     else if (numoffsets == 0 || myoffset == theoffset) {
  1094. theoffset = myoffset;
  1095. numoffsets++;
  1096.     } else
  1097. theoffset = BadOffset;
  1098. }
  1099. break;
  1100.       case EK_PLUS:
  1101. ex2 = ex->args[ex->nargs-1];
  1102. if (ex2->kind == EK_CONST &&
  1103.     ex2->val.type->kind == TK_INTEGER) {
  1104.     nextoffset = ex2->val.i;
  1105. }
  1106. break;
  1107.       case EK_HAT:
  1108.       case EK_POSTINC:
  1109.       case EK_POSTDEC:
  1110. nextoffset = BadOffset;
  1111. break;
  1112.       case EK_ASSIGN:
  1113. checkvaroffsetexpr(ex->args[0], mp, BadOffset);
  1114. checkvaroffsetexpr(ex->args[1], mp, 0);
  1115. return;
  1116.       default:
  1117. break;
  1118.     }
  1119.     i = ex->nargs;
  1120.     while (--i >= 0)
  1121. checkvaroffsetexpr(ex->args[i], mp, nextoffset);
  1122. }
  1123. void checkvaroffsetstmt(sp, mp)
  1124. Stmt *sp;
  1125. Meaning *mp;
  1126. {
  1127.     while (sp) {
  1128. checkvaroffsetstmt(sp->stm1, mp);
  1129. checkvaroffsetstmt(sp->stm1, mp);
  1130. checkvaroffsetexpr(sp->exp1, mp, 0);
  1131. checkvaroffsetexpr(sp->exp2, mp, 0);
  1132. checkvaroffsetexpr(sp->exp3, mp, 0);
  1133. sp = sp->next;
  1134.     }
  1135. }
  1136. int checkvaroffset(sp, mp)
  1137. Stmt *sp;
  1138. Meaning *mp;
  1139. {
  1140.     if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION)
  1141. return 0;
  1142.     numoffsets = 0;
  1143.     numzerooffsets = 0;
  1144.     checkvaroffsetstmt(sp, mp);
  1145.     if (numoffsets == 0 || theoffset == BadOffset ||
  1146. numoffsets <= numzerooffsets * 3)
  1147. return 0;
  1148.     else
  1149. return theoffset;
  1150. }
  1151. void initfilevars(mp, sppp, exbase)
  1152. Meaning *mp;
  1153. Stmt ***sppp;
  1154. Expr *exbase;
  1155. {
  1156.     Stmt *sp;
  1157.     Type *tp;
  1158.     Expr *ex;
  1159.     while (mp) {
  1160. if ((mp->kind == MK_VAR && mp->refcount > 0 && !mp->istemporary) ||
  1161.     mp->kind == MK_FIELD) {
  1162.     tp = mp->type;
  1163.     if (isfiletype(tp)) {
  1164. mp->refcount++;
  1165. sp = makestmt(SK_ASSIGN);
  1166. sp->next = **sppp;
  1167. **sppp = sp;
  1168. if (exbase)
  1169.     ex = makeexpr_dot(copyexpr(exbase), mp);
  1170. else
  1171.     ex = makeexpr_var(mp);
  1172. sp->exp1 = makeexpr_assign(copyexpr(ex), makeexpr_nil());
  1173.     } else if (tp->kind == TK_RECORD) {
  1174. if (exbase)
  1175.     ex = makeexpr_dot(copyexpr(exbase), mp);
  1176. else
  1177.     ex = makeexpr_var(mp);
  1178. initfilevars(tp->fbase, sppp, ex);
  1179. freeexpr(ex);
  1180.     } else if (tp->kind == TK_ARRAY) {
  1181. while (tp->kind == TK_ARRAY)
  1182.     tp = tp->basetype;
  1183. if (isfiletype(tp))
  1184.     note(format_s("Array of files %s should be initialized [257]",
  1185.   mp->name));
  1186.     }
  1187. }
  1188. mp = mp->cnext;
  1189.     }
  1190. }
  1191. Static Stmt *p_body()
  1192. {
  1193.     Stmt *sp, **spp, *spbody, **sppbody, *spbase, *thereturn;
  1194.     Meaning *mp;
  1195.     Expr *ex;
  1196.     int haspostamble;
  1197.     long saveserial;
  1198.     if (verbose)
  1199. fprintf(logf, "%s, %d/%d: Translating %s (in %s)n",
  1200. infname, inf_lnum, outf_lnum,
  1201. curctx->name, curctx->ctx->name);
  1202.     notephase = 1;
  1203.     spp = &spbase;
  1204.     addstmt(SK_HEADER);
  1205.     sp->exp1 = makeexpr_var(curctx);
  1206.     checkkeyword(TOK_INLINE);
  1207.     if (curtok != TOK_END && curtok != TOK_BEGIN && curtok != TOK_INLINE) {
  1208. if (curctx->kind == MK_FUNCTION || curctx->anyvarflag)
  1209.     wexpecttok(TOK_BEGIN);
  1210. else
  1211.     wexpecttok(TOK_END);
  1212. skiptotoken2(TOK_BEGIN, TOK_END);
  1213.     }
  1214.     if (curtok == TOK_END) {
  1215. gettok();
  1216. spbody = NULL;
  1217.     } else {
  1218. spbody = p_stmt(NULL, SF_FUNC);  /* parse the procedure/program body */
  1219.     }
  1220.     if (curtok == TOK_IDENT && curtokmeaning == curctx) {
  1221. gettok();    /* Modula-2 */
  1222.     }
  1223.     notephase = 2;
  1224.     saveserial = curserial;
  1225.     curserial = 10000;
  1226.     if (curctx->kind == MK_FUNCTION) {     /* handle copy parameters */
  1227.         for (mp = curctx->type->fbase; mp; mp = mp->xnext) {
  1228.             if (!mp->othername && mp->varstructflag) {
  1229.                 mp->othername = stralloc(format_s(name_COPYPAR, mp->name));
  1230.                 mp->rectype = mp->type;
  1231.                 addstmt(SK_ASSIGN);
  1232.                 sp->exp1 = makeexpr_assign(makeexpr_var(mp), 
  1233.                                            makeexpr_name(mp->othername, mp->rectype));
  1234.                 mp->refcount++;
  1235.             } else if (mp->othername) {
  1236.                 if (checkvarchanged(spbody, mp)) {
  1237.                     addstmt(SK_ASSIGN);
  1238.                     sp->exp1 = makeexpr_assign(makeexpr_var(mp),
  1239.                                                makeexpr_hat(makeexpr_name(mp->othername,
  1240.                                                                           mp->rectype), 0));
  1241.                     mp->refcount++;
  1242.                 } else {           /* don't need to copy it after all */
  1243.                     strchange(&mp->othername, mp->name);
  1244.                     ex = makeexpr_var(mp);
  1245.                     ex->val.type = mp->rectype;
  1246.                     replaceexpr(spbody, makeexpr_var(mp), makeexpr_hat(ex, 0));
  1247.                 }
  1248.             }
  1249.         }
  1250.     }
  1251.     for (mp = curctx->cbase; mp; mp = mp->cnext) {
  1252. if (mp->kind == MK_LABEL && mp->val.i) {
  1253.     addstmt(SK_IF);
  1254.     sp->exp1 = makeexpr_bicall_1("setjmp", tp_int,
  1255.  makeexpr_var(mp->xnext));
  1256.     sp->stm1 = makestmt(SK_GOTO);
  1257.     sp->stm1->exp1 = makeexpr_name(format_s(name_LABEL, mp->name),
  1258.    tp_integer);
  1259. }
  1260.     }
  1261.     *spp = spbody;
  1262.     sppbody = spp;
  1263.     while (*spp)
  1264.         spp = &((*spp)->next);
  1265.     haspostamble = 0;
  1266.     initfilevars(curctx->cbase, &sppbody, NULL);
  1267.     for (mp = curctx->cbase; mp; mp = mp->cnext) {
  1268.         if (mp->kind == MK_VAR && mp->refcount > 0 && isfiletype(mp->type) &&
  1269.              !mp->istemporary) {
  1270.             if (curctx->kind != MK_MODULE || curctx->anyvarflag) {
  1271.                 addstmt(SK_IF);                    /* close file variables */
  1272.                 sp->exp1 = makeexpr_rel(EK_NE, makeexpr_var(mp), makeexpr_nil());
  1273.                 sp->stm1 = makestmt(SK_ASSIGN);
  1274.                 sp->stm1->exp1 = makeexpr_bicall_1("fclose", tp_void, makeexpr_var(mp));
  1275.             }
  1276.             haspostamble = 1;
  1277.         }
  1278.     }
  1279.     thereturn = &bogusreturn;
  1280.     if (curctx->kind == MK_FUNCTION && curctx->type->basetype != tp_void) {
  1281.         if ((haspostamble || !checkreturns(&spbase, 1)) &&
  1282.             curctx->cbase->refcount > 0) {      /* add function return code */
  1283.             addstmt(SK_RETURN);
  1284.             sp->exp1 = makeexpr_var(curctx->cbase);
  1285.         }
  1286.         thereturn = NULL;
  1287.     } else if (curctx->kind == MK_MODULE && curctx->anyvarflag) {
  1288.         addstmt(SK_ASSIGN);
  1289.         sp->exp1 = makeexpr_bicall_1("exit", tp_void, makeexpr_long(0));
  1290.         thereturn = NULL;
  1291.     }
  1292.     if (debug>2) { fprintf(outf, "calling fixblock/usecommas on:n"); dumpstmt(spbase, 5); }
  1293.     curserial = saveserial;
  1294.     sp = makestmt(SK_BODY);
  1295.     sp->stm1 = spbase;
  1296.     fixblock(&sp, thereturn);           /* finishing touches to statements and expressions */
  1297.     spbase = sp->stm1;
  1298.     FREE(sp);
  1299.     if (usecommas != 1)
  1300.         checkcommas(&spbase);    /* unroll ugly EK_COMMA and EK_COND expressions */
  1301.     if (debug>1) { fprintf(outf, "p_body returns:n"); dumpstmt(spbase, 5); }
  1302.     notephase = 0;
  1303.     return spbase;
  1304. }
  1305. #define checkWord()  if (anywords) output(" "); anywords = 1
  1306. Static void out_function(func)
  1307. Meaning *func;
  1308. {
  1309.     Meaning *mp;
  1310.     Symbol *sym;
  1311.     int opts, anywords, spacing, saveindent;
  1312.     if (func->varstructflag) {
  1313.         makevarstruct(func);
  1314.     }
  1315.     if (collectnest) {
  1316. for (mp = func->cbase; mp; mp = mp->cnext) {
  1317.     if (mp->kind == MK_FUNCTION && mp->isforward) {
  1318. forward_decl(mp, 0);
  1319.     }
  1320. }
  1321. for (mp = func->cbase; mp; mp = mp->cnext) {
  1322.     if (mp->kind == MK_FUNCTION && mp->type) {
  1323. pushctx(mp);
  1324. out_function(mp);    /* generate the sub-procedures first */
  1325. popctx();
  1326.     }
  1327. }
  1328.     }
  1329.     spacing = functionspace;
  1330.     for (mp = func; mp->ctx->kind == MK_FUNCTION; mp = mp->ctx) {
  1331.         if (spacing > minfuncspace)
  1332.             spacing--;
  1333.     }
  1334.     outsection(spacing);
  1335.     flushcomments(&func->comments, -1, 0);
  1336.     if (usePPMacros == 1) {
  1337.         forward_decl(func, 0);
  1338.         outsection(minorspace);
  1339.     }
  1340.     opts = ODECL_HEADER;
  1341.     anywords = 0;
  1342.     if (func->namedfile) {
  1343. checkWord();
  1344. if (useAnyptrMacros || ansiC < 2)
  1345.     output("Inline");
  1346. else
  1347.     output("inline");
  1348.     }
  1349.     if (!func->exported) {
  1350. if (func->ctx->kind == MK_FUNCTION) {
  1351.     if (useAnyptrMacros) {
  1352. checkWord();
  1353. output("Local");
  1354.     } else if (use_static) {
  1355. checkWord();
  1356. output("static");
  1357.     }
  1358. } else if ((findsymbol(func->name)->flags & NEEDSTATIC) ||
  1359.    (use_static != 0 && !useAnyptrMacros)) {
  1360.     checkWord();
  1361.     output("static");
  1362. } else if (useAnyptrMacros) {
  1363.     checkWord();
  1364.     output("Static");
  1365. }
  1366.     }
  1367.     if (func->type->basetype != tp_void || ansiC != 0) {
  1368. checkWord();
  1369.         outbasetype(func->type, 0);
  1370.     }
  1371.     if (anywords) {
  1372.         if (newlinefunctions)
  1373.             opts |= ODECL_FUNCTION;
  1374.         else
  1375.             output(" ");
  1376.     }
  1377.     outdeclarator(func->type, func->name, opts);
  1378.     if (fullprototyping == 0) {
  1379. saveindent = outindent;
  1380. moreindent(argindent);
  1381.         out_argdecls(func->type);
  1382. outindent = saveindent;
  1383.     }
  1384.     for (mp = func->type->fbase; mp; mp = mp->xnext) {
  1385.         if (mp->othername && strcmp(mp->name, mp->othername))
  1386.             mp->wasdeclared = 0;    /* make sure we also declare the copy */
  1387.     }
  1388.     func->wasdeclared = 1;
  1389.     outcontext = func;
  1390.     out_block((Stmt *)func->val.i, BR_FUNCTION, 10000);
  1391.     if (useundef) {
  1392. anywords = 0;
  1393. for (mp = func->cbase; mp; mp = mp->cnext) {
  1394.     if (mp->kind == MK_CONST &&