home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 379a.lha / p2c1_13a / src / src.zoo / parse3.c < prev    next >
C/C++ Source or Header  |  1990-03-11  |  32KB  |  981 lines

  1. /* "p2c", a Pascal to C translator.
  2.    Copyright (C) 1989 David Gillespie.
  3.    Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation (any version).
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  17.  
  18. #define PROTO_PARSE3_C
  19. #include "trans.h"
  20.  
  21. #define BR_NEVER        0x1     /* never use braces */
  22. #define BR_FUNCTION     0x2     /* function body */
  23. #define BR_THENPART     0x4     /* before an "else" */
  24. #define BR_ALWAYS       0x8     /* always use braces */
  25. #define BR_REPEAT       0x10    /* "do-while" loop */
  26. #define BR_TRY          0x20    /* in a recover block */
  27. #define BR_ELSEPART     0x40    /* after an "else" */
  28. #define BR_CASE         0x80    /* case of a switch stmt */
  29.  
  30. int printnl_func(ex)
  31. Expr *ex;
  32. {
  33.     char *cp, ch;
  34.     int i, len;
  35.  
  36.     if (debug>2) { fprintf(outf,"printnl_func("); dumpexpr(ex); fprintf(outf, ")\n"); }
  37.     if (!strcmp(ex->val.s, "printf") ||
  38.     !strcmp(ex->val.s, "puts") ||
  39.     !strcmp(ex->val.s, "fputs")) {
  40.     if (ex->args[0]->kind != EK_CONST)
  41.         return 0;
  42.     cp = ex->args[0]->val.s;
  43.     len = ex->args[0]->val.i;
  44.     } else if (!strcmp(ex->val.s, "fprintf")) {
  45.     if (ex->args[1]->kind != EK_CONST)
  46.         return 0;
  47.     cp = ex->args[1]->val.s;
  48.     len = ex->args[1]->val.i;
  49.     } else if (!strcmp(ex->val.s, "putchar") ||
  50.            !strcmp(ex->val.s, "putc") ||
  51.            !strcmp(ex->val.s, "fputc")) {
  52.     if (ex->args[0]->kind != EK_CONST)
  53.         return 0;
  54.     ch = ex->args[0]->val.i;
  55.     cp = &ch;
  56.     len = 1;
  57.     } else
  58.     return 0;
  59.     for (i = 1; i <= len; i++)
  60.     if (*cp++ != '\n')
  61.         return 0;
  62.     return len + (!strcmp(ex->val.s, "puts"));
  63. }
  64.  
  65.  
  66.  
  67. Expr *chg_printf(ex)
  68. Expr *ex;
  69. {
  70.     Expr *fex;
  71.  
  72.     if (debug>2) { fprintf(outf,"chg_printf("); dumpexpr(ex); fprintf(outf, ")\n"); }
  73.     if (!strcmp(ex->val.s, "putchar")) {
  74.     ex = makeexpr_sprintfify(grabarg(ex, 0));
  75.     canceltempvar(istempvar(ex->args[0]));
  76.     strchange(&ex->val.s, "printf");
  77.     delfreearg(&ex, 0);
  78.     ex->val.type = tp_void;
  79.     } else if (!strcmp(ex->val.s, "putc") ||
  80.            !strcmp(ex->val.s, "fputc") ||
  81.            !strcmp(ex->val.s, "fputs")) {
  82.     fex = copyexpr(ex->args[1]);
  83.     ex = makeexpr_sprintfify(grabarg(ex, 0));
  84.     canceltempvar(istempvar(ex->args[0]));
  85.     strchange(&ex->val.s, "fprintf");
  86.     ex->args[0] = fex;
  87.     ex->val.type = tp_void;
  88.     } else if (!strcmp(ex->val.s, "puts")) {
  89.     ex = makeexpr_concat(makeexpr_sprintfify(grabarg(ex, 0)),
  90.                  makeexpr_string("\n"), 1);
  91.     strchange(&ex->val.s, "printf");
  92.     delfreearg(&ex, 0);
  93.     ex->val.type = tp_void;
  94.     }
  95.     if (!strcmp(ex->val.s, "fprintf") && exprsame(ex->args[0], ex_output, 1)) {
  96.     delfreearg(&ex, 0);
  97.     strchange(&ex->val.s, "printf");
  98.     }
  99.     return ex;
  100. }
  101.  
  102.  
  103. Expr *mix_printf(ex, ex2)
  104. Expr *ex, *ex2;
  105. {
  106.     int i;
  107.  
  108.     ex = chg_printf(ex);
  109.     if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex); fprintf(outf, "\n"); }
  110.     ex2 = chg_printf(copyexpr(ex2));
  111.     if (debug>2) { fprintf(outf,"chg_printf returns "); dumpexpr(ex2);fprintf(outf, "\n"); }
  112.     i = (!strcmp(ex->val.s, "printf")) ? 0 : 1;
  113.     ex->args[i] = makeexpr_concat(ex->args[i], ex2->args[i], 0);
  114.     for (i++; i < ex2->nargs; i++) {
  115.     insertarg(&ex, ex->nargs, ex2->args[i]);
  116.     }
  117.     return ex;
  118. }
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125. void eatstmt(spp)
  126. Stmt **spp;
  127. {
  128.     Stmt *sp = *spp;
  129.  
  130.     if (debug>2) { fprintf(outf, "eatstmt on:\n"); dumpstmt(sp, 5); }
  131.     *spp = sp->next;
  132.     sp->next = NULL;
  133.     free_stmt(sp);
  134. }
  135.  
  136.  
  137.  
  138. int haslabels(sp)
  139. Stmt *sp;
  140. {
  141.     if (!sp)
  142.         return 0;
  143.     if (haslabels(sp->stm1) || haslabels(sp->stm2))
  144.         return 1;
  145.     return (sp->kind == SK_LABEL);
  146. }
  147.  
  148.  
  149.  
  150. void fixblock(spp, thereturn)
  151. Stmt **spp, *thereturn;
  152. {
  153.     Stmt *sp, *sp1, *sp2, *sp3, **spp2, *thisreturn;
  154.     Expr *ex;
  155.     Meaning *tvar, *mp;
  156.     int save_tryblock;
  157.     short save_tryflag;
  158.     int i, j, de1, de2;
  159.     long saveserial = curserial;
  160.  
  161.     while ((sp = *spp)) {
  162.         sp2 = sp->next;
  163.         sp->next = NULL;
  164.         sp = fix_statement(*spp);
  165.         if (!sp) {
  166.             *spp = sp2;
  167.             continue;
  168.         }
  169.         *spp = sp;
  170.         for (sp3 = sp; sp3->next; sp3 = sp3->next) ;
  171.         sp3->next = sp2;
  172.         if (!sp->next)
  173.             thisreturn = thereturn;
  174.         else if (sp->next->kind == SK_RETURN ||
  175.                  (sp->next->kind == SK_ASSIGN &&
  176.                   isescape(sp->next->exp1)))
  177.             thisreturn = sp->next;
  178.         else
  179.             thisreturn = NULL;
  180.     if (sp->serial >= 0)
  181.         curserial = sp->serial;
  182.         switch (sp->kind) {
  183.  
  184.             case SK_ASSIGN:
  185.             if (sp->exp1)
  186.             sp->exp1 = fixexpr(sp->exp1, ENV_STMT);
  187.         if (!sp->exp1)
  188.             intwarning("fixblock", "sp->exp1 == NULL in SK_ASSIGN");
  189.                 if (!sp->exp1 || nosideeffects(sp->exp1, 1)) {
  190.             eatstmt(spp);
  191.             continue;
  192.                 } else {
  193.                     switch (sp->exp1->kind) {
  194.  
  195.                         case EK_COND:
  196.                             *spp = makestmt_if(sp->exp1->args[0],
  197.                                                makestmt_call(sp->exp1->args[1]),
  198.                                                makestmt_call(sp->exp1->args[2]));
  199.                             (*spp)->next = sp->next;
  200.                             continue;    /* ... to fix this new if statement */
  201.  
  202.                         case EK_ASSIGN:
  203.                             if (sp->exp1->args[1]->kind == EK_COND && usecommas != 1) {
  204.                                 *spp = makestmt_if(sp->exp1->args[1]->args[0],
  205.                                                    makestmt_assign(copyexpr(sp->exp1->args[0]),
  206.                                                                    sp->exp1->args[1]->args[1]),
  207.                                                    makestmt_assign(sp->exp1->args[0],
  208.                                                                    sp->exp1->args[1]->args[2]));
  209.                                 (*spp)->next = sp->next;
  210.                                 continue;
  211.                             }
  212.                 if (isescape(sp->exp1->args[1])) {
  213.                                 sp->exp1 = grabarg(sp->exp1, 1);
  214.                 continue;
  215.                             }
  216.                 if (exprsame(sp->exp1->args[0], sp->exp1->args[1], 1)) {
  217.                               /*  *spp = sp->next;  */
  218.                                 sp->exp1 = grabarg(sp->exp1, 0);
  219.                                 continue;
  220.                             }
  221.                 if (sp->exp1->args[1]->kind == EK_BICALL) {
  222.                 if (!strcmp(sp->exp1->args[1]->val.s,
  223.                         getfbufname) &&
  224.                     buildreads == 1 &&
  225.                     sp->next &&
  226.                     sp->next->kind == SK_ASSIGN &&
  227.                     sp->next->exp1->kind == EK_BICALL &&
  228.                     !strcmp(sp->next->exp1->val.s,
  229.                         getname) &&
  230.                     expr_has_address(sp->exp1->args[0]) &&
  231.                     similartypes(sp->exp1->args[0]->val.type,
  232.                          sp->exp1->args[1]->args[0]->val.type->basetype->basetype) &&
  233.                     exprsame(sp->exp1->args[1]->args[0],
  234.                          sp->next->exp1->args[0], 1)) {
  235.                     eatstmt(&sp->next);
  236.                     ex = makeexpr_bicall_4("fread", tp_integer,
  237.                                makeexpr_addr(sp->exp1->args[0]),
  238.                                makeexpr_sizeof(sp->exp1->args[1]->args[1], 0),
  239.                                makeexpr_long(1),
  240.                                sp->exp1->args[1]->args[0]);
  241.                     FREE(sp->exp1);
  242.                     sp->exp1 = ex;
  243.                     continue;
  244.                 }
  245.                 if (!strcmp(sp->exp1->args[1]->val.s,
  246.                         chargetfbufname) &&
  247.                     buildreads != 0 &&
  248.                     sp->next &&
  249.                     sp->next->kind == SK_ASSIGN &&
  250.                     sp->next->exp1->kind == EK_BICALL &&
  251.                     !strcmp(sp->next->exp1->val.s,
  252.                         chargetname) &&
  253.                     expr_has_address(sp->exp1->args[0]) &&
  254.                     exprsame(sp->exp1->args[1]->args[0],
  255.                          sp->next->exp1->args[0], 1)) {
  256.                     eatstmt(&sp->next);
  257.                     strchange(&sp->exp1->args[1]->val.s,
  258.                           "getc");
  259.                     continue;
  260.                 }
  261.                 }
  262.                             break;
  263.  
  264.                         case EK_BICALL:
  265.                             if (!strcmp(sp->exp1->val.s, name_ESCAPE)) {
  266.                                 if (fixexpr_tryblock) {
  267.                                     *spp = makestmt_assign(makeexpr_var(mp_escapecode),
  268.                                                            grabarg(sp->exp1, 0));
  269.                                     (*spp)->next = makestmt(SK_GOTO);
  270.                                     (*spp)->next->exp1 = makeexpr_name(format_s(name_LABEL,
  271.                                                                                 format_d("try%d",
  272.                                                                                          fixexpr_tryblock)),
  273.                                                                        tp_integer);
  274.                                     (*spp)->next->next = sp->next;
  275.                                     fixexpr_tryflag = 1;
  276.                                     continue;
  277.                                 }
  278.                             } else if (!strcmp(sp->exp1->val.s, name_ESCIO)) {
  279.                                 if (fixexpr_tryblock) {
  280.                                     *spp = makestmt_assign(makeexpr_var(mp_escapecode),
  281.                                                            makeexpr_long(-10));
  282.                                     (*spp)->next = makestmt_assign(makeexpr_var(mp_ioresult),
  283.                                                                    grabarg(sp->exp1, 0));
  284.                                     (*spp)->next->next = makestmt(SK_GOTO);
  285.                                     (*spp)->next->next->exp1 = makeexpr_name(format_s(name_LABEL,
  286.                                                                                       format_d("try%d",
  287.                                                                                                fixexpr_tryblock)),
  288.                                                                              tp_integer);
  289.                                     (*spp)->next->next->next = sp->next;
  290.                                     fixexpr_tryflag = 1;
  291.                                     continue;
  292.                                 }
  293.                             }
  294.                 if (!strcmp(sp->exp1->val.s, putfbufname) &&
  295.                 buildwrites == 1 &&
  296.                 sp->next &&
  297.                 sp->next->kind == SK_ASSIGN &&
  298.                 sp->next->exp1->kind == EK_BICALL &&
  299.                 !strcmp(sp->next->exp1->val.s,
  300.                     putname) &&
  301.                 exprsame(sp->exp1->args[0],
  302.                      sp->next->exp1->args[0], 1)) {
  303.                 eatstmt(&sp->next);
  304.                 if (!expr_has_address(sp->exp1->args[2]) ||
  305.                     sp->exp1->args[2]->val.type !=
  306.                         sp->exp1->args[1]->val.type) {
  307.                     tvar = maketempvar(sp->exp1->args[1]->val.type,
  308.                                name_TEMP);
  309.                     sp2 = makestmt_assign(makeexpr_var(tvar),
  310.                               sp->exp1->args[2]);
  311.                     sp2->next = sp;
  312.                     *spp = sp2;
  313.                     sp->exp1->args[2] = makeexpr_var(tvar);
  314.                     freetempvar(tvar);
  315.                 }
  316.                 ex = makeexpr_bicall_4("fwrite", tp_integer,
  317.                                makeexpr_addr(sp->exp1->args[2]),
  318.                                makeexpr_sizeof(sp->exp1->args[1], 0),
  319.                                makeexpr_long(1),
  320.                                sp->exp1->args[0]);
  321.                 FREE(sp->exp1);
  322.                 sp->exp1 = ex;
  323.                 continue;
  324.                 }
  325.                 if (!strcmp(sp->exp1->val.s, charputfbufname) &&
  326.                 buildwrites != 0 &&
  327.                 sp->next &&
  328.                 sp->next->kind == SK_ASSIGN &&
  329.                 sp->next->exp1->kind == EK_BICALL &&
  330.                 !strcmp(sp->next->exp1->val.s,
  331.                     charputname) &&
  332.                 exprsame(sp->exp1->args[0],
  333.                      sp->next->exp1->args[0], 1)) {
  334.                 eatstmt(&sp->next);
  335.                 swapexprs(sp->exp1->args[0],
  336.                       sp->exp1->args[1]);
  337.                 strchange(&sp->exp1->val.s, "putc");
  338.                 continue;
  339.                 }
  340.                 if ((!strcmp(sp->exp1->val.s, resetbufname) ||
  341.                  !strcmp(sp->exp1->val.s, setupbufname)) &&
  342.                 (mp = isfilevar(sp->exp1->args[0])) != NULL &&
  343.                 !mp->bufferedfile) {
  344.                 eatstmt(spp);
  345.                 continue;
  346.                 }
  347.                 ex = print_func(sp->exp1);
  348.                 if (ex && sp->next && mixwritelns &&
  349.                 sp->next->kind == SK_ASSIGN &&
  350.                 exprsame(ex, print_func(sp->next->exp1), 1) &&
  351.                 (printnl_func(sp->exp1) ||
  352.                  printnl_func(sp->next->exp1))) {
  353.                 sp->exp1 = mix_printf(sp->exp1,
  354.                               sp->next->exp1);
  355.                 eatstmt(&sp->next);
  356.                 continue;
  357.                 }
  358.                             break;
  359.  
  360.                         case EK_FUNCTION:
  361.                         case EK_SPCALL:
  362.                         case EK_POSTINC:
  363.                         case EK_POSTDEC:
  364.                         case EK_AND:
  365.                         case EK_OR:
  366.                             break;
  367.  
  368.                         default:
  369.                             spp2 = spp;
  370.                             for (i = 0; i < sp->exp1->nargs; i++) {
  371.                                 *spp2 = makestmt_call(sp->exp1->args[i]);
  372.                                 spp2 = &(*spp2)->next;
  373.                             }
  374.                             *spp2 = sp->next;
  375.                             continue;    /* ... to fix these new statements */
  376.  
  377.                     }
  378.                 }
  379.                 break;
  380.  
  381.             case SK_IF:
  382.                 fixblock(&sp->stm1, thisreturn);
  383.                 fixblock(&sp->stm2, thisreturn);
  384.                 if (!sp->stm1) {
  385.                     if (!sp->stm2) {
  386.                         sp->kind = SK_ASSIGN;
  387.                         continue;
  388.                     } else {
  389.             if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
  390.                 freeexpr(sp->stm2->exp2);
  391.                 sp->stm2->exp2 = NULL;
  392.             }
  393.                         sp->exp1 = makeexpr_not(sp->exp1);   /* if (x) else foo  =>  if (!x) foo */
  394.                         swapstmts(sp->stm1, sp->stm2);
  395.             /* Ought to exchange comments for then/else parts */
  396.                     }
  397.                 }
  398.         /* At this point we know sp1 != NULL */
  399.                 if (thisreturn) {
  400.                     if (thisreturn->kind == SK_WHILE) {
  401.                         if (usebreaks) {
  402.                             sp1 = sp->stm1;
  403.                             while (sp1->next)
  404.                                 sp1 = sp1->next;
  405.                             if (sp->stm2) {
  406.                 sp2 = sp->stm2;
  407.                 while (sp2->next)
  408.                     sp2 = sp2->next;
  409.                                 i = stmtcount(sp->stm1);
  410.                                 j = stmtcount(sp->stm2);
  411.                                 if (j >= breaklimit && i <= 2 && j > i*2 &&
  412.                                     ((implies(sp->exp1, thisreturn->exp1, 0, 1) &&
  413.                       !checkexprchanged(sp->stm1, sp->exp1)) ||
  414.                      (sp1->kind == SK_ASSIGN &&
  415.                       implies(sp1->exp1, thisreturn->exp1, 0, 1)))) {
  416.                                     sp1->next = makestmt(SK_BREAK);
  417.                                 } else if (i >= breaklimit && j <= 2 && i > j*2 &&
  418.                                            ((implies(sp->exp1, thisreturn->exp1, 1, 1) &&
  419.                          !checkexprchanged(sp->stm2, sp->exp1)) ||
  420.                         (sp2->kind == SK_ASSIGN &&
  421.                          implies(sp2->exp1, thisreturn->exp1, 0, 1)))) {
  422.                                     sp2->next = makestmt(SK_BREAK);
  423.                 } else if (!checkconst(sp->exp2, 1)) {
  424.                     /* not part of an else-if */
  425.                     if (j >= continuelimit) {
  426.                     sp1->next = makestmt(SK_CONTINUE);
  427.                     } else if (i >= continuelimit) {
  428.                     sp2->next = makestmt(SK_CONTINUE);
  429.                     }
  430.                 }
  431.                 } else {
  432.                                 i = stmtcount(sp->stm1);
  433.                                 if (i >= breaklimit &&
  434.                                     implies(sp->exp1, thisreturn->exp1, 1, 1)) {
  435.                                     sp->exp1 = makeexpr_not(sp->exp1);
  436.                                     sp1->next = sp->next;
  437.                                     sp->next = sp->stm1;
  438.                                     sp->stm1 = makestmt(SK_BREAK);
  439.                                 } else if (i >= continuelimit) {
  440.                                     sp->exp1 = makeexpr_not(sp->exp1);
  441.                                     sp1->next = sp->next;
  442.                                     sp->next = sp->stm1;
  443.                                     sp->stm1 = makestmt(SK_CONTINUE);
  444.                                 }
  445.                             }
  446.                         }
  447.                     } else {
  448.                         if (usereturns) {
  449.                             sp2 = sp->stm1;
  450.                             while (sp2->next)
  451.                                 sp2 = sp2->next;
  452.                             if (sp->stm2) {
  453.                                 /* if (x) foo; else bar; (return;)  =>  if (x) {foo; return;} bar; */
  454.                                 if (stmtcount(sp->stm2) >= returnlimit) {
  455.                     if (!deadendblock(sp->stm1))
  456.                     sp2->next = copystmt(thisreturn);
  457.                                 } else if (stmtcount(sp->stm1) >= returnlimit) {
  458.                                     sp2 = sp->stm2;
  459.                                     while (sp2->next)
  460.                                         sp2 = sp2->next;
  461.                     if (!deadendblock(sp->stm2))
  462.                     sp2->next = copystmt(thisreturn);
  463.                                 }
  464.                             } else {      /* if (x) foo; (return;)  =>  if (!x) return; foo; */
  465.                                 if (stmtcount(sp->stm1) >= returnlimit) {
  466.                                     sp->exp1 = makeexpr_not(sp->exp1);
  467.                                     sp2->next = sp->next;
  468.                                     sp->next = sp->stm1;
  469.                                     sp->stm1 = copystmt(thisreturn);
  470.                                 }
  471.                             }
  472.                         }
  473.                     }
  474.                 }
  475.                 if (!checkconst(sp->exp2, 1)) {    /* not part of an else-if */
  476.                     de1 = deadendblock(sp->stm1);
  477.                     de2 = deadendblock(sp->stm2);
  478.                     if (de2 && !de1) {
  479.                         sp->exp1 = makeexpr_not(sp->exp1);
  480.                         swapstmts(sp->stm1, sp->stm2);
  481.                         de1 = 1, de2 = 0;
  482.                     }
  483.                     if (de1 && !de2 && sp->stm2) {
  484.             if (sp->stm2->kind == SK_IF && sp->stm2->exp2) {
  485.                 freeexpr(sp->stm2->exp2);
  486.                 sp->stm2->exp2 = NULL;
  487.             }
  488.                         for (sp2 = sp->stm2; sp2->next; sp2 = sp2->next) ;
  489.                         sp2->next = sp->next;
  490.                         sp->next = sp->stm2;      /* if (x) ESCAPE else foo  =>  if (x) ESCAPE; foo */
  491.                         sp->stm2 = NULL;
  492.                     }
  493.                 }
  494.                 sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
  495.                 break;
  496.  
  497.             case SK_WHILE:
  498.                 if (whilefgets &&    /* handle "while eof(f) do readln(f,...)" */
  499.             sp->stm1->kind == SK_ASSIGN &&
  500.             sp->stm1->exp1->kind == EK_BICALL &&
  501.             !strcmp(sp->stm1->exp1->val.s, "fgets") &&
  502.             nosideeffects(sp->stm1->exp1->args[0], 1) &&
  503.             nosideeffects(sp->stm1->exp1->args[1], 1) &&
  504.             nosideeffects(sp->stm1->exp1->args[2], 1)) {
  505.             if ((sp->exp1->kind == EK_NOT &&
  506.              sp->exp1->args[0]->kind == EK_BICALL && *eofname &&
  507.              !strcmp(sp->exp1->args[0]->val.s, eofname) &&
  508.              exprsame(sp->exp1->args[0]->args[0],
  509.                   sp->stm1->exp1->args[2], 1)) ||
  510.             (sp->exp1->kind == EK_EQ &&
  511.              sp->exp1->args[0]->kind == EK_BICALL &&
  512.              !strcmp(sp->exp1->args[0]->val.s, "feof") &&
  513.              checkconst(sp->exp1->args[1], 0) &&
  514.              exprsame(sp->exp1->args[0]->args[0],
  515.                   sp->stm1->exp1->args[2], 1))) {
  516.             sp->stm1->exp1->val.type = tp_strptr;
  517.             sp->exp1 = makeexpr_rel(EK_NE,
  518.                         sp->stm1->exp1,
  519.                         makeexpr_nil());
  520.             sp->stm1 = sp->stm1->next;
  521.             }
  522.                 }
  523.                 fixblock(&sp->stm1, sp);
  524.                 sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
  525.                 if (checkconst(sp->exp1, 1))
  526.                     infiniteloop(sp);
  527.                 break;
  528.  
  529.             case SK_REPEAT:
  530.                 fixblock(&sp->stm1, NULL);
  531.                 sp->exp1 = fixexpr(sp->exp1, ENV_BOOL);
  532.                 if (checkconst(sp->exp1, 1))
  533.                     infiniteloop(sp);
  534.                 break;
  535.  
  536.             case SK_TRY:
  537.                 save_tryblock = fixexpr_tryblock;
  538.                 save_tryflag = fixexpr_tryflag;
  539.                 fixexpr_tryblock = sp->exp1->val.i;
  540.                 fixexpr_tryflag = 0;
  541.                 fixblock(&sp->stm1, NULL);
  542.                 if (fixexpr_tryflag)
  543.                     sp->exp2 = makeexpr_long(1);
  544.                 fixexpr_tryblock = save_tryblock;
  545.                 fixexpr_tryflag = save_tryflag;
  546.                 fixblock(&sp->stm2, NULL);
  547.                 break;
  548.  
  549.             case SK_BODY:
  550.                 fixblock(&sp->stm1, thisreturn);
  551.                 break;
  552.  
  553.             case SK_CASE:
  554.                 fixblock(&sp->stm1, NULL);
  555.                 sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
  556.                 if (!sp->stm1) {    /* empty case */
  557.                     sp->kind = SK_ASSIGN;
  558.                     continue;
  559.                 } else if (sp->stm1->kind != SK_CASELABEL) {   /* default only */
  560.                     for (sp2 = sp->stm1; sp2->next; sp2 = sp2->next) ;
  561.                     sp2->next = sp->next;
  562.                     sp->next = sp->stm1;
  563.                     sp->kind = SK_ASSIGN;
  564.                     sp->stm1 = NULL;
  565.                     continue;
  566.                 }
  567.                 break;
  568.  
  569.             default:
  570.                 fixblock(&sp->stm1, NULL);
  571.                 fixblock(&sp->stm2, NULL);
  572.                 sp->exp1 = fixexpr(sp->exp1, ENV_EXPR);
  573.                 sp->exp2 = fixexpr(sp->exp2, ENV_EXPR);
  574.                 sp->exp3 = fixexpr(sp->exp3, ENV_EXPR);
  575.                 if (sp->next &&
  576.                     (sp->kind == SK_GOTO ||
  577.                      sp->kind == SK_BREAK ||
  578.                      sp->kind == SK_CONTINUE ||
  579.                      sp->kind == SK_RETURN) &&
  580.                     !haslabels(sp->next)) {
  581.                     if (elimdeadcode) {
  582.                         note("Deleting unreachable code [255]");
  583.                         while (sp->next && !haslabels(sp->next))
  584.                             eatstmt(&sp->next);
  585.                     } else {
  586.                         note("Code is unreachable [256]");
  587.                     }
  588.                 } else if (sp->kind == SK_RETURN &&
  589.                            thisreturn &&
  590.                            thisreturn->kind == SK_RETURN &&
  591.                            exprsame(sp->exp1, thisreturn->exp1, 1)) {
  592.                     eatstmt(spp);
  593.             continue;
  594.                 }
  595.                 break;
  596.         }
  597.         spp = &sp->next;
  598.     }
  599.     saveserial = curserial;
  600. }
  601.  
  602.  
  603.  
  604.  
  605. /* Convert comma expressions into multiple statements */
  606.  
  607. Static int checkcomma_expr(spp, exp)
  608. Stmt **spp;
  609. Expr **exp;
  610. {
  611.     Stmt *sp;
  612.     Expr *ex = *exp;
  613.     int i, res;
  614.  
  615.     switch (ex->kind) {
  616.  
  617.         case EK_COMMA:
  618.             if (spp) {
  619.                 res = checkcomma_expr(spp, &ex->args[ex->nargs-1]);
  620.                 for (i = ex->nargs-1; --i >= 0; ) {
  621.                     sp = makestmt(SK_ASSIGN);
  622.                     sp->exp1 = ex->args[i];
  623.                     sp->next = *spp;
  624.                     *spp = sp;
  625.                     res = checkcomma_expr(spp, &ex->args[i]);
  626.                 }
  627.                 *exp = ex->args[ex->nargs-1];
  628.             }
  629.             return 1;
  630.  
  631.         case EK_COND:
  632.             if (isescape(ex->args[1]) && spp &&
  633.                 !isescape(ex->args[2])) {
  634.                 swapexprs(ex->args[1], ex->args[2]);
  635.                 ex->args[0] = makeexpr_not(ex->args[0]);
  636.             }
  637.             if (isescape(ex->args[2])) {
  638.                 if (spp) {
  639.                     res = checkcomma_expr(spp, &ex->args[1]);
  640.                     if (ex->args[0]->kind == EK_ASSIGN) {
  641.                         sp = makestmt(SK_ASSIGN);
  642.                         sp->exp1 = copyexpr(ex->args[0]);
  643.                         sp->next = makestmt(SK_IF);
  644.                         sp->next->next = *spp;
  645.                         *spp = sp;
  646.                         res = checkcomma_expr(spp, &sp->exp1);
  647.                         ex->args[0] = grabarg(ex->args[0], 0);
  648.                         sp = sp->next;
  649.                     } else {
  650.                         sp = makestmt(SK_IF);
  651.                         sp->next = *spp;
  652.                         *spp = sp;
  653.                     }
  654.                     sp->exp1 = makeexpr_not(ex->args[0]);
  655.                     sp->stm1 = makestmt(SK_ASSIGN);
  656.                     sp->stm1->exp1 = eatcasts(ex->args[2]);
  657.                     res = checkcomma_expr(&sp->stm1, &ex->args[2]);
  658.                     res = checkcomma_expr(spp, &sp->exp1);
  659.                     *exp = ex->args[1];
  660.                 }
  661.                 return 1;
  662.             }
  663.             return checkcomma_expr(spp, &ex->args[0]);
  664.  
  665.         case EK_AND:
  666.         case EK_OR:
  667.             return checkcomma_expr(spp, &ex->args[0]);
  668.  
  669.     default:
  670.         res = 0;
  671.         for (i = ex->nargs; --i >= 0; ) {
  672.         res += checkcomma_expr(spp, &ex->args[i]);
  673.         }
  674.         return res;
  675.  
  676.     }
  677. }
  678.  
  679.  
  680.  
  681. Static void checkcommas(spp)
  682. Stmt **spp;
  683. {
  684.     Stmt *sp;
  685.     int res;
  686.  
  687.     while ((sp = *spp)) {
  688.         checkcommas(&sp->stm1);
  689.         checkcommas(&sp->stm2);
  690.         switch (sp->kind) {
  691.  
  692.             case SK_ASSIGN:
  693.             case SK_IF:
  694.             case SK_CASE:
  695.             case SK_RETURN:
  696.                 if (sp->exp1)
  697.                     res = checkcomma_expr(spp, &sp->exp1);
  698.                 break;
  699.  
  700.             case SK_WHILE:
  701.                 /* handle the argument */
  702.                 break;
  703.  
  704.             case SK_REPEAT:
  705.                 /* handle the argument */
  706.                 break;
  707.  
  708.             case SK_FOR:
  709.         if (sp->exp1)
  710.             res = checkcomma_expr(spp, &sp->exp1);
  711.                 /* handle the other arguments */
  712.                 break;
  713.  
  714.         default:
  715.         break;
  716.         }
  717.         spp = &sp->next;
  718.     }
  719. }
  720.  
  721.  
  722.  
  723.  
  724. Static int checkvarchangeable(ex, mp)
  725. Expr *ex;
  726. Meaning *mp;
  727. {
  728.     switch (ex->kind) {
  729.  
  730.         case EK_VAR:
  731.             return (mp == (Meaning *)ex->val.i);
  732.  
  733.         case EK_DOT:
  734.         case EK_INDEX:
  735.             return checkvarchangeable(ex->args[0], mp);
  736.  
  737.     default:
  738.         return 0;
  739.     }
  740. }
  741.  
  742.  
  743.  
  744. int checkvarchangedexpr(ex, mp, addrokay)
  745. Expr *ex;
  746. Meaning *mp;
  747. int addrokay;
  748. {
  749.     int i;
  750.     Meaning *mp3;
  751.     unsigned int safemask = 0;
  752.  
  753.     switch (ex->kind) {
  754.  
  755.         case EK_FUNCTION:
  756.         case EK_SPCALL:
  757.             if (ex->kind == EK_FUNCTION) {
  758.                 i = 0;
  759.                 mp3 = ((Meaning *)ex->val.i)->type->fbase;
  760.             } else {
  761.                 i = 1;
  762.                 if (ex->args[0]->val.type->kind != TK_PROCPTR)
  763.                     return 1;
  764.                 mp3 = ex->args[0]->val.type->basetype->fbase;
  765.             }
  766.             for ( ; i < ex->nargs && i < 16; i++) {
  767.                 if (!mp3) {
  768.                     intwarning("checkvarchangedexpr", "Too many arguments for EK_FUNCTION [266]");
  769.                     break;
  770.                 }
  771.                 if (mp3->kind == MK_PARAM &&
  772.                     (mp3->type->kind == TK_ARRAY ||
  773.                      mp3->type->kind == TK_STRING ||
  774.                      mp3->type->kind == TK_SET))
  775.                     safemask |= 1<<i;
  776.                 if (mp3->kind == MK_VARPARAM &&
  777.                     mp3->type == tp_strptr && mp3->anyvarflag)
  778.                     i++;
  779.                 mp3 = mp3->xnext;
  780.             }
  781.             if (mp3)
  782.                 intwarning("checkvarchangedexpr", "Too few arguments for EK_FUNCTION [267]");
  783.             break;
  784.  
  785.         case EK_VAR:
  786.             if (mp == (Meaning *)ex->val.i) {
  787.                 if ((mp->type->kind == TK_ARRAY ||
  788.                      mp->type->kind == TK_STRING ||
  789.                      mp->type->kind == TK_SET) &&
  790.                     ex->val.type->kind == TK_POINTER && !addrokay)
  791.                     return 1;   /* must be an implicit & */
  792.             }
  793.             break;
  794.  
  795.         case EK_ADDR:
  796.         case EK_ASSIGN:
  797.         case EK_POSTINC:
  798.         case EK_POSTDEC:
  799.             if (checkvarchangeable(ex->args[0], mp))
  800.                 return 1;
  801.             break;
  802.  
  803.         case EK_BICALL:
  804.             if (structuredfunc(ex) && checkvarchangeable(ex->args[0], mp))
  805.                 return 1;
  806.             safemask = safemask_bicall(ex->val.s);
  807.             break;
  808.             /* In case calls to these functions were lazy and passed
  809.                the array rather than its (implicit) address.  Other
  810.                BICALLs had better be careful about their arguments. */
  811.  
  812.         case EK_PLUS:
  813.             if (addrokay)         /* to keep from being scared by pointer */
  814.                 safemask = ~0;    /*  arithmetic on string being passed */
  815.             break;                /*  to functions. */
  816.  
  817.     default:
  818.         break;
  819.     }
  820.     for (i = 0; i < ex->nargs; i++) {
  821.         if (checkvarchangedexpr(ex->args[i], mp, safemask&1))
  822.             return 1;
  823.         safemask >>= 1;
  824.     }
  825.     return 0;
  826. }
  827.  
  828.  
  829.  
  830. int checkvarchanged(sp, mp)
  831. Stmt *sp;
  832. Meaning *mp;
  833. {
  834.     if (mp->constqual)
  835.     return 0;
  836.     if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION ||
  837.         mp->volatilequal || alwayscopyvalues)
  838.         return 1;
  839.     while (sp) {
  840.         if (/* sp->kind == SK_GOTO || */
  841.         sp->kind == SK_LABEL ||
  842.             checkvarchanged(sp->stm1, mp) ||
  843.             checkvarchanged(sp->stm2, mp) ||
  844.             (sp->exp1 && checkvarchangedexpr(sp->exp1, mp, 1)) ||
  845.             (sp->exp2 && checkvarchangedexpr(sp->exp2, mp, 1)) ||
  846.             (sp->exp3 && checkvarchangedexpr(sp->exp3, mp, 1)))
  847.             return 1;
  848.         sp = sp->next;
  849.     }
  850.     return 0;
  851. }
  852.  
  853.  
  854.  
  855. int checkexprchanged(sp, ex)
  856. Stmt *sp;
  857. Expr *ex;
  858. {
  859.     Meaning *mp;
  860.     int i;
  861.  
  862.     for (i = 0; i < ex->nargs; i++) {
  863.         if (checkexprchanged(sp, ex->args[i]))
  864.             return 1;
  865.     }
  866.     switch (ex->kind) {
  867.  
  868.         case EK_VAR:
  869.             mp = (Meaning *)ex->val.i;
  870.             if (mp->kind == MK_CONST)
  871.                 return 0;
  872.             else
  873.                 return checkvarchanged(sp, mp);
  874.  
  875.         case EK_HAT:
  876.         case EK_INDEX:
  877.         case EK_SPCALL:
  878.             return 1;
  879.  
  880.         case EK_FUNCTION:
  881.         case EK_BICALL:
  882.             return !nosideeffects_func(ex);
  883.  
  884.     default:
  885.         return 0;
  886.     }
  887. }
  888.  
  889.  
  890.  
  891.  
  892.  
  893. /* Check if a variable always occurs with a certain offset added, e.g. "i+1" */
  894.  
  895. Static int theoffset, numoffsets, numzerooffsets;
  896. #define BadOffset  (-999)
  897.  
  898. void checkvaroffsetexpr(ex, mp, myoffset)
  899. Expr *ex;
  900. Meaning *mp;
  901. int myoffset;
  902. {
  903.     int i, nextoffset = 0;
  904.     Expr *ex2;
  905.  
  906.     if (!ex)
  907.     return;
  908.     switch (ex->kind) {
  909.  
  910.       case EK_VAR:
  911.     if (ex->val.i == (long)mp) {
  912.         if (myoffset == 0)
  913.         numzerooffsets++;
  914.         else if (numoffsets == 0 || myoffset == theoffset) {
  915.         theoffset = myoffset;
  916.         numoffsets++;
  917.         } else
  918.         theoffset = BadOffset;
  919.     }
  920.     break;
  921.  
  922.       case EK_PLUS:
  923.     ex2 = ex->args[ex->nargs-1];
  924.     if (ex2->kind == EK_CONST &&
  925.         ex2->val.type->kind == TK_INTEGER) {
  926.         nextoffset = ex2->val.i;
  927.     }
  928.     break;
  929.  
  930.       case EK_HAT:
  931.       case EK_POSTINC:
  932.       case EK_POSTDEC:
  933.     nextoffset = BadOffset;
  934.     break;
  935.  
  936.       case EK_ASSIGN:
  937.     checkvaroffsetexpr(ex->args[0], mp, BadOffset);
  938.     checkvaroffsetexpr(ex->args[1], mp, 0);
  939.     return;
  940.  
  941.       default:
  942.     break;
  943.     }
  944.     i = ex->nargs;
  945.     while (--i >= 0)
  946.     checkvaroffsetexpr(ex->args[i], mp, nextoffset);
  947. }
  948.  
  949.  
  950. void checkvaroffsetstmt(sp, mp)
  951. Stmt *sp;
  952. Meaning *mp;
  953. {
  954.     while (sp) {
  955.     checkvaroffsetstmt(sp->stm1, mp);
  956.     checkvaroffsetstmt(sp->stm1, mp);
  957.     checkvaroffsetexpr(sp->exp1, mp, 0);
  958.     checkvaroffsetexpr(sp->exp2, mp, 0);
  959.     checkvaroffsetexpr(sp->exp3, mp, 0);
  960.     sp = sp->next;
  961.     }
  962. }
  963.  
  964.  
  965. int checkvaroffset(sp, mp)
  966. Stmt *sp;
  967. Meaning *mp;
  968. {
  969.     if (mp->varstructflag || !mp->ctx || mp->ctx->kind != MK_FUNCTION)
  970.     return 0;
  971.     numoffsets = 0;
  972.     numzerooffsets = 0;
  973.     checkvaroffsetstmt(sp, mp);
  974.     if (numoffsets == 0 || theoffset == BadOffset ||
  975.     numoffsets <= numzerooffsets * 3)
  976.     return 0;
  977.     else
  978.     return theoffset;
  979. }
  980.  
  981.