home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 379a.lha / p2c1_13a / src / src.zoo / funcs1.c < prev    next >
C/C++ Source or Header  |  1990-03-11  |  26KB  |  960 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_FUNCS1_C
  19. #include "trans.h"
  20.  
  21. Static Strlist *enumnames;
  22. Static int enumnamecount;
  23.  
  24. void setup_funcs()
  25. {
  26.     enumnames = NULL;
  27.     enumnamecount = 0;
  28. }
  29.  
  30.  
  31.  
  32.  
  33.  
  34. int isvar(ex, mp)
  35. Expr *ex;
  36. Meaning *mp;
  37. {
  38.     return (ex->kind == EK_VAR && (Meaning *)ex->val.i == mp);
  39. }
  40.  
  41.  
  42.  
  43.  
  44. char *getstring(ex)
  45. Expr *ex;
  46. {
  47.     ex = makeexpr_stringify(ex);
  48.     if (ex->kind != EK_CONST || ex->val.type->kind != TK_STRING) {
  49.         intwarning("getstring", "Not a string literal [206]");
  50.     return "";
  51.     }
  52.     return ex->val.s;
  53. }
  54.  
  55.  
  56.  
  57.  
  58. Expr *p_parexpr(target)
  59. Type *target;
  60. {
  61.     Expr *ex;
  62.  
  63.     if (wneedtok(TOK_LPAR)) {
  64.     ex = p_expr(target);
  65.     if (!wneedtok(TOK_RPAR))
  66.         skippasttotoken(TOK_RPAR, TOK_SEMI);
  67.     } else
  68.     ex = p_expr(target);
  69.     return ex;
  70. }
  71.  
  72.  
  73.  
  74. Type *argbasetype(ex)
  75. Expr *ex;
  76. {
  77.     if (ex->kind == EK_CAST)
  78.         ex = ex->args[0];
  79.     if (ex->val.type->kind == TK_POINTER)
  80.         return ex->val.type->basetype;
  81.     else
  82.         return ex->val.type;
  83. }
  84.  
  85.  
  86.  
  87. Type *choosetype(t1, t2)
  88. Type *t1, *t2;
  89. {
  90.     if (t1 == tp_void ||
  91.         (type_sizeof(t2, 1) && !type_sizeof(t1, 1)))
  92.         return t2;
  93.     else
  94.         return t1;
  95. }
  96.  
  97.  
  98.  
  99. Expr *convert_offset(type, ex2)
  100. Type *type;
  101. Expr *ex2;
  102. {
  103.     long size;
  104.     int i;
  105.     Value val;
  106.     Expr *ex3;
  107.  
  108.     if (type->kind == TK_POINTER ||
  109.         type->kind == TK_ARRAY ||
  110.         type->kind == TK_SET ||
  111.         type->kind == TK_STRING)
  112.         type = type->basetype;
  113.     size = type_sizeof(type, 1);
  114.     if (size == 1)
  115.         return ex2;
  116.     val = eval_expr_pasc(ex2);
  117.     if (val.type) {
  118.         if (val.i == 0)
  119.             return ex2;
  120.         if (size && val.i % size == 0) {
  121.             freeexpr(ex2);
  122.             return makeexpr_long(val.i / size);
  123.         }
  124.     } else {     /* look for terms like "n*sizeof(foo)" */
  125.     while (ex2->kind == EK_CAST || ex2->kind == EK_ACTCAST)
  126.         ex2 = ex2->args[0];
  127.         if (ex2->kind == EK_TIMES) {
  128.         for (i = 0; i < ex2->nargs; i++) {
  129.         ex3 = convert_offset(type, ex2->args[i]);
  130.         if (ex3) {
  131.             ex2->args[i] = ex3;
  132.             return resimplify(ex2);
  133.         }
  134.         }
  135.             for (i = 0;
  136.                  i < ex2->nargs && ex2->args[i]->kind != EK_SIZEOF;
  137.                  i++) ;
  138.             if (i < ex2->nargs) {
  139.                 if (ex2->args[i]->args[0]->val.type == type) {
  140.                     delfreearg(&ex2, i);
  141.                     if (ex2->nargs == 1)
  142.                         return ex2->args[0];
  143.                     else
  144.                         return ex2;
  145.                 }
  146.             }
  147.         } else if (ex2->kind == EK_PLUS) {
  148.         ex3 = copyexpr(ex2);
  149.         for (i = 0; i < ex2->nargs; i++) {
  150.         ex3->args[i] = convert_offset(type, ex3->args[i]);
  151.         if (!ex3->args[i]) {
  152.             freeexpr(ex3);
  153.             return NULL;
  154.         }
  155.         }
  156.         freeexpr(ex2);
  157.         return resimplify(ex3);
  158.         } else if (ex2->kind == EK_SIZEOF) {
  159.             if (ex2->args[0]->val.type == type) {
  160.                 freeexpr(ex2);
  161.                 return makeexpr_long(1);
  162.             }
  163.         } else if (ex2->kind == EK_NEG) {
  164.         ex3 = convert_offset(type, ex2->args[0]);
  165.         if (ex3)
  166.                 return makeexpr_neg(ex3);
  167.         }
  168.     }
  169.     return NULL;
  170. }
  171.  
  172.  
  173.  
  174. Expr *convert_size(type, ex, name)
  175. Type *type;
  176. Expr *ex;
  177. char *name;
  178. {
  179.     long size;
  180.     Expr *ex2;
  181.     int i, okay;
  182.     Value val;
  183.  
  184.     if (debug>2) { fprintf(outf,"convert_size("); dumpexpr(ex); fprintf(outf,")\n"); }
  185.     while (type->kind == TK_ARRAY || type->kind == TK_STRING)
  186.         type = type->basetype;
  187.     if (type == tp_void)
  188.         return ex;
  189.     size = type_sizeof(type, 1);
  190.     if (size == 1)
  191.         return ex;
  192.     while (ex->kind == EK_CAST || ex->kind == EK_ACTCAST)
  193.     ex = ex->args[0];
  194.     switch (ex->kind) {
  195.  
  196.         case EK_TIMES:
  197.             for (i = 0; i < ex->nargs; i++) {
  198.                 ex2 = convert_size(type, ex->args[i], NULL);
  199.                 if (ex2) {
  200.                     ex->args[i] = ex2;
  201.                     return resimplify(ex);
  202.                 }
  203.             }
  204.             break;
  205.  
  206.         case EK_PLUS:
  207.             okay = 1;
  208.             for (i = 0; i < ex->nargs; i++) {
  209.                 ex2 = convert_size(type, ex->args[i], NULL);
  210.                 if (ex2)
  211.                     ex->args[i] = ex2;
  212.                 else
  213.                     okay = 0;
  214.             }
  215.             ex = distribute_plus(ex);
  216.             if ((ex->kind != EK_TIMES || !okay) && name)
  217.                 note(format_s("Suspicious mixture of sizes in %s [173]", name));
  218.             return ex;
  219.  
  220.         case EK_SIZEOF:
  221.             return ex;
  222.  
  223.     default:
  224.         break;
  225.     }
  226.     val = eval_expr_pasc(ex);
  227.     if (val.type) {
  228.         if (val.i == 0)
  229.             return ex;
  230.         if (size && val.i % size == 0) {
  231.             freeexpr(ex);
  232.             return makeexpr_times(makeexpr_long(val.i / size),
  233.                                   makeexpr_sizeof(makeexpr_type(type), 0));
  234.         }
  235.     }
  236.     if (name) {
  237.         note(format_s("Can't interpret size in %s [174]", name));
  238.         return ex;
  239.     } else
  240.         return NULL;
  241. }
  242.  
  243. Expr *func_abs()
  244. {
  245.     Expr *ex;
  246.     Meaning *tvar;
  247.     int lness;
  248.  
  249.     ex = p_parexpr(tp_integer);
  250.     if (ex->val.type->kind == TK_REAL)
  251.         return makeexpr_bicall_1("fabs", tp_longreal, ex);
  252.     else {
  253.         lness = exprlongness(ex);
  254.         if (lness < 0)
  255.             return makeexpr_bicall_1("abs", tp_int, ex);
  256.         else if (lness > 0 && *absname) {
  257.             if (ansiC > 0) {
  258.                 return makeexpr_bicall_1("labs", tp_integer, ex);
  259.             } else if (*absname == '*' && (exprspeed(ex) >= 5 || !nosideeffects(ex, 0))) {
  260.                 tvar = makestmttempvar(tp_integer, name_TEMP);
  261.                 return makeexpr_comma(makeexpr_assign(makeexpr_var(tvar),
  262.                                                       ex),
  263.                                       makeexpr_bicall_1(absname, tp_integer,
  264.                                                         makeexpr_var(tvar)));
  265.             } else {
  266.                 return makeexpr_bicall_1(absname, tp_integer, ex);
  267.             }
  268.         } else if (exprspeed(ex) < 5 && nosideeffects(ex, 0)) {
  269.             return makeexpr_cond(makeexpr_rel(EK_LT, copyexpr(ex),
  270.                                                      makeexpr_long(0)),
  271.                                  makeexpr_neg(copyexpr(ex)),
  272.                                  ex);
  273.         } else {
  274.             tvar = makestmttempvar(tp_integer, name_TEMP);
  275.             return makeexpr_cond(makeexpr_rel(EK_LT, makeexpr_assign(makeexpr_var(tvar),
  276.                                                                      ex),
  277.                                                      makeexpr_long(0)),
  278.                                  makeexpr_neg(makeexpr_var(tvar)),
  279.                                  makeexpr_var(tvar));
  280.         }
  281.     }
  282. }
  283.  
  284. Expr *func_addr()
  285. {
  286.     Expr *ex, *ex2, *ex3;
  287.     Type *type, *tp2;
  288.     int haspar;
  289.  
  290.     haspar = wneedtok(TOK_LPAR);
  291.     ex = p_expr(tp_proc);
  292.     if (curtok == TOK_COMMA) {
  293.         gettok();
  294.         ex2 = p_expr(tp_integer);
  295.         ex3 = convert_offset(ex->val.type, ex2);
  296.         if (checkconst(ex3, 0)) {
  297.             ex = makeexpr_addrf(ex);
  298.         } else {
  299.             ex = makeexpr_addrf(ex);
  300.             if (ex3) {
  301.                 ex = makeexpr_plus(ex, ex3);
  302.             } else {
  303.                 note("Don't know how to reduce offset for ADDR [175]");
  304.                 type = makepointertype(tp_abyte);
  305.         tp2 = ex->val.type;
  306.                 ex = makeexpr_cast(makeexpr_plus(makeexpr_cast(ex, type), ex2), tp2);
  307.             }
  308.         }
  309.     } else {
  310.     if ((ex->val.type->kind != TK_PROCPTR &&
  311.          ex->val.type->kind != TK_CPROCPTR) ||
  312.         (ex->kind == EK_VAR &&
  313.          ex->val.type == ((Meaning *)ex->val.i)->type))
  314.         ex = makeexpr_addrf(ex);
  315.     }
  316.     if (haspar) {
  317.     if (!wneedtok(TOK_RPAR))
  318.         skippasttotoken(TOK_RPAR, TOK_SEMI);
  319.     }
  320.     return ex;
  321. }
  322.  
  323. Expr *func_iaddress()
  324. {
  325.     return makeexpr_cast(func_addr(), tp_integer);
  326. }
  327.  
  328. Expr *func_addtopointer()
  329. {
  330.     Expr *ex, *ex2, *ex3;
  331.     Type *type, *tp2;
  332.  
  333.     if (!skipopenparen())
  334.     return NULL;
  335.     ex = p_expr(tp_anyptr);
  336.     if (skipcomma()) {
  337.     ex2 = p_expr(tp_integer);
  338.     } else
  339.     ex2 = makeexpr_long(0);
  340.     skipcloseparen();
  341.     ex3 = convert_offset(ex->val.type, ex2);
  342.     if (!checkconst(ex3, 0)) {
  343.     if (ex3) {
  344.         ex = makeexpr_plus(ex, ex3);
  345.     } else {
  346.         note("Don't know how to reduce offset for ADDTOPOINTER [175]");
  347.         type = makepointertype(tp_abyte);
  348.         tp2 = ex->val.type;
  349.         ex = makeexpr_cast(makeexpr_plus(makeexpr_cast(ex, type), ex2), tp2);
  350.     }
  351.     }
  352.     return ex;
  353. }
  354.  
  355. Stmt *proc_assert()
  356. {
  357.     Expr *ex;
  358.  
  359.     ex = p_parexpr(tp_boolean);
  360.     return makestmt_call(makeexpr_bicall_1("assert", tp_void, ex));
  361. }
  362.  
  363. Stmt *wrapopencheck(sp, fex)
  364. Stmt *sp;
  365. Expr *fex;
  366. {
  367.     Stmt *sp2;
  368.  
  369.     if (FCheck(checkfileisopen) && !is_std_file(fex)) {
  370.         sp2 = makestmt(SK_IF);
  371.         sp2->exp1 = makeexpr_rel(EK_NE, fex, makeexpr_nil());
  372.         sp2->stm1 = sp;
  373.         if (iocheck_flag) {
  374.             sp2->stm2 = makestmt_call(makeexpr_bicall_1(name_ESCIO, tp_integer,
  375.                             makeexpr_name(filenotopenname, tp_int)));
  376.         } else {
  377.             sp2->stm2 = makestmt_assign(makeexpr_var(mp_ioresult),
  378.                     makeexpr_name(filenotopenname, tp_int));
  379.         }
  380.         return sp2;
  381.     } else {
  382.         freeexpr(fex);
  383.         return sp;
  384.     }
  385. }
  386.  
  387.  
  388.  
  389. Static Expr *checkfilename(nex)
  390. Expr *nex;
  391. {
  392.     Expr *ex;
  393.  
  394.     nex = makeexpr_stringcast(nex);
  395.     if (nex->kind == EK_CONST && nex->val.type->kind == TK_STRING) {
  396.         switch (which_lang) {
  397.  
  398.             case LANG_HP:
  399.                 if (!strncmp(nex->val.s, "#1:", 3) ||
  400.                     !strncmp(nex->val.s, "console:", 8) ||
  401.                     !strncmp(nex->val.s, "CONSOLE:", 8)) {
  402.                     freeexpr(nex);
  403.                     nex = makeexpr_string("/dev/tty");
  404.                 } else if (!strncmp(nex->val.s, "#2:", 3) ||
  405.                            !strncmp(nex->val.s, "systerm:", 8) ||
  406.                            !strncmp(nex->val.s, "SYSTERM:", 8)) {
  407.                     freeexpr(nex);
  408.                     nex = makeexpr_string("/dev/tty");     /* should do more? */
  409.                 } else if (!strncmp(nex->val.s, "#6:", 3) ||
  410.                            !strncmp(nex->val.s, "printer:", 8) ||
  411.                            !strncmp(nex->val.s, "PRINTER:", 8)) {
  412.                     note("Opening a file named PRINTER: [176]");
  413.                 } else if (my_strchr(nex->val.s, ':')) {
  414.                     note("Opening a file whose name contains a ':' [177]");
  415.                 }
  416.                 break;
  417.  
  418.             case LANG_TURBO:
  419.                 if (checkstring(nex, "con") ||
  420.                     checkstring(nex, "CON") ||
  421.                     checkstring(nex, "")) {
  422.                     freeexpr(nex);
  423.                     nex = makeexpr_string("/dev/tty");
  424.                 } else if (checkstring(nex, "nul") ||
  425.                            checkstring(nex, "NUL")) {
  426.                     freeexpr(nex);
  427.                     nex = makeexpr_string("/dev/null");
  428.                 } else if (checkstring(nex, "lpt1") ||
  429.                            checkstring(nex, "LPT1") ||
  430.                            checkstring(nex, "lpt2") ||
  431.                            checkstring(nex, "LPT2") ||
  432.                            checkstring(nex, "lpt3") ||
  433.                            checkstring(nex, "LPT3") ||
  434.                            checkstring(nex, "com1") ||
  435.                            checkstring(nex, "COM1") ||
  436.                            checkstring(nex, "com2") ||
  437.                            checkstring(nex, "COM2")) {
  438.                     note("Opening a DOS device file name [178]");
  439.                 }
  440.                 break;
  441.  
  442.         default:
  443.         break;
  444.         }
  445.     } else {
  446.     if (*filenamefilter && strcmp(filenamefilter, "0")) {
  447.         ex = makeexpr_sizeof(copyexpr(nex), 0);
  448.         nex = makeexpr_bicall_2(filenamefilter, tp_str255, nex, ex);
  449.     } else
  450.         nex = makeexpr_stringify(nex);
  451.     }
  452.     return nex;
  453. }
  454.  
  455.  
  456.  
  457. Static Stmt *assignfilename(fex, nex)
  458. Expr *fex, *nex;
  459. {
  460.     Meaning *mp;
  461.  
  462.     mp = isfilevar(fex);
  463.     if (mp && mp->namedfile) {
  464.         freeexpr(fex);
  465.         return makestmt_call(makeexpr_assign(makeexpr_name(format_s(name_FNVAR, mp->name),
  466.                                                            tp_str255),
  467.                                              nex));
  468.     } else {
  469.         if (mp)
  470.             warning("Don't know how to ASSIGN to a non-explicit file variable [207]");
  471.         else
  472.             note("Encountered an ASSIGN statement [179]");
  473.         return makestmt_call(makeexpr_bicall_2("assign", tp_void, fex, nex));
  474.     }
  475. }
  476.  
  477.  
  478.  
  479. Stmt *proc_assign()
  480. {
  481.     Expr *fex, *nex;
  482.  
  483.     if (!skipopenparen())
  484.     return NULL;
  485.     fex = p_expr(tp_text);
  486.     if (!skipcomma())
  487.     return NULL;
  488.     nex = checkfilename(p_expr(tp_str255));
  489.     skipcloseparen();
  490.     return assignfilename(fex, nex);
  491. }
  492.  
  493. Stmt *handleopen(code)
  494. int code;
  495. {
  496.     Stmt *sp, *spassign;
  497.     Expr *fex, *nex, *ex;
  498.     Meaning *fmp;
  499.     int storefilename, needcheckopen = 1;
  500.     char modebuf[5], *cp;
  501.  
  502.     if (!skipopenparen())
  503.     return NULL;
  504.     fex = p_expr(tp_text);
  505.     fmp = isfilevar(fex);
  506.     storefilename = (fmp && fmp->namedfile);
  507.     spassign = NULL;
  508.     if (curtok == TOK_COMMA) {
  509.         gettok();
  510.         ex = p_expr(tp_str255);
  511.     } else
  512.         ex = NULL;
  513.     if (ex && (ex->val.type->kind == TK_STRING ||
  514.            ex->val.type->kind == TK_ARRAY)) {
  515.         nex = checkfilename(ex);
  516.         if (storefilename) {
  517.             spassign = assignfilename(copyexpr(fex), nex);
  518.             nex = makeexpr_name(format_s(name_FNVAR, fmp->name), tp_str255);
  519.         }
  520.         if (curtok == TOK_COMMA) {
  521.             gettok();
  522.             ex = p_expr(tp_str255);
  523.         } else
  524.             ex = NULL;
  525.     } else if (storefilename) {
  526.         nex = makeexpr_name(format_s(name_FNVAR, fmp->name), tp_str255);
  527.     } else {
  528.     switch (code) {
  529.         case 0:
  530.             if (ex)
  531.             note("Can't interpret name argument in RESET [180]");
  532.         break;
  533.           case 1:
  534.             note("REWRITE does not specify a name [181]");
  535.         break;
  536.         case 2:
  537.         note("OPEN does not specify a name [181]");
  538.         break;
  539.         case 3:
  540.         note("APPEND does not specify a name [181]");
  541.         break;
  542.     }
  543.     nex = NULL;
  544.     }
  545.     if (ex) {
  546.         if (ord_type(ex->val.type)->kind == TK_INTEGER) {
  547.         if (!checkconst(ex, 1))
  548.         note("Ignoring block size in binary file [182]");
  549.             freeexpr(ex);
  550.         } else {
  551.         if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING) {
  552.         cp = getstring(ex);
  553.         if (strcicmp(cp, "SHARED"))
  554.             note(format_s("Ignoring option string \"%s\" in open [183]", cp));
  555.         } else
  556.         note("Ignoring option string in open [183]");
  557.         }
  558.     }
  559.     switch (code) {
  560.  
  561.         case 0:  /* reset */
  562.             strcpy(modebuf, "r");
  563.             break;
  564.  
  565.         case 1:  /* rewrite */
  566.             strcpy(modebuf, "w");
  567.             break;
  568.  
  569.         case 2:  /* open */
  570.             strcpy(modebuf, openmode);
  571.             break;
  572.  
  573.         case 3:  /* append */
  574.             strcpy(modebuf, "a");
  575.             break;
  576.  
  577.     }
  578.     if (!*modebuf) {
  579.         strcpy(modebuf, "r+");
  580.     }
  581.     if (readwriteopen == 2 ||
  582.     (readwriteopen && fex->val.type != tp_text)) {
  583.     if (!my_strchr(modebuf, '+'))
  584.         strcat(modebuf, "+");
  585.     }
  586.     if (fex->val.type != tp_text && binarymode != 0) {
  587.         if (binarymode == 1)
  588.             strcat(modebuf, "b");
  589.         else
  590.             note("Opening a binary file [184]");
  591.     }
  592.     if (!nex && fmp &&
  593.     !is_std_file(fex) &&
  594.     (literalfilesflag == 1 ||
  595.      strlist_cifind(literalfiles, fmp->name))) {
  596.     nex = makeexpr_string(fmp->name);
  597.     }
  598.     if (!nex) {
  599.     if (isvar(fex, mp_output)) {
  600.         note("RESET/REWRITE ignored for file OUTPUT [319]");
  601.         sp = NULL;
  602.     } else {
  603.         sp = makestmt_call(makeexpr_bicall_1("rewind", tp_void,
  604.                          copyexpr(fex)));
  605.         if (code == 0 || is_std_file(fex)) {
  606.         sp = wrapopencheck(sp, copyexpr(fex));
  607.         needcheckopen = 0;
  608.         } else
  609.         sp = makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex),
  610.                           makeexpr_nil()),
  611.                  sp,
  612.                  makestmt_assign(copyexpr(fex),
  613.                          makeexpr_bicall_0("tmpfile",
  614.                                    tp_text)));
  615.     }
  616.     } else if (!strcmp(freopenname, "fclose") ||
  617.            !strcmp(freopenname, "fopen")) {
  618.         sp = makestmt_assign(copyexpr(fex),
  619.                              makeexpr_bicall_2("fopen", tp_text,
  620.                                                copyexpr(nex),
  621.                                                makeexpr_string(modebuf)));
  622.         if (!strcmp(freopenname, "fclose")) {
  623.             sp = makestmt_seq(makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  624.                                           makestmt_call(makeexpr_bicall_1("fclose", tp_void,
  625.                                                                           copyexpr(fex))),
  626.                                           NULL),
  627.                               sp);
  628.         }
  629.     } else {
  630.         sp = makestmt_assign(copyexpr(fex),
  631.                              makeexpr_bicall_3((*freopenname) ? freopenname : "freopen",
  632.                                                tp_text,
  633.                                                copyexpr(nex),
  634.                                                makeexpr_string(modebuf),
  635.                                                copyexpr(fex)));
  636.         if (!*freopenname) {
  637.             sp = makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  638.                              sp,
  639.                              makestmt_assign(copyexpr(fex),
  640.                                              makeexpr_bicall_2("fopen", tp_text,
  641.                                                                copyexpr(nex),
  642.                                                                makeexpr_string(modebuf))));
  643.         }
  644.     }
  645.     if (code == 2 && !*openmode && nex) {
  646.         sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ, copyexpr(fex), makeexpr_nil()),
  647.                                           makestmt_assign(copyexpr(fex),
  648.                                                           makeexpr_bicall_2("fopen", tp_text,
  649.                                                                             copyexpr(nex),
  650.                                                                             makeexpr_string("w+"))),
  651.                                           NULL));
  652.     }
  653.     if (nex)
  654.     freeexpr(nex);
  655.     if (FCheck(checkfileopen) && needcheckopen) {
  656.         sp = makestmt_seq(sp, makestmt_call(makeexpr_bicall_2("~SETIO", tp_void,
  657.                                                               makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  658.                                   makeexpr_name(filenotfoundname, tp_int))));
  659.     }
  660.     sp = makestmt_seq(spassign, sp);
  661.     cp = (code == 0) ? resetbufname : setupbufname;
  662.     if (*cp && fmp)   /* (may be eaten later, if buffering isn't needed) */
  663.     sp = makestmt_seq(sp,
  664.              makestmt_call(
  665.                      makeexpr_bicall_2(cp, tp_void, fex,
  666.              makeexpr_type(fex->val.type->basetype->basetype))));
  667.     else
  668.     freeexpr(fex);
  669.     skipcloseparen();
  670.     return sp;
  671. }
  672.  
  673. Stmt *proc_append()
  674. {
  675.     return handleopen(3);
  676. }
  677.  
  678. Expr *func_arccos(ex)
  679. Expr *ex;
  680. {
  681.     return makeexpr_bicall_1("acos", tp_longreal, grabarg(ex, 0));
  682. }
  683.  
  684. Expr *func_arcsin(ex)
  685. Expr *ex;
  686. {
  687.     return makeexpr_bicall_1("asin", tp_longreal, grabarg(ex, 0));
  688. }
  689.  
  690. Expr *func_arctan(ex)
  691. Expr *ex;
  692. {
  693.     ex = grabarg(ex, 0);
  694.     if (atan2flag && ex->kind == EK_DIVIDE)
  695.         return makeexpr_bicall_2("atan2", tp_longreal, 
  696.                                  ex->args[0], ex->args[1]);
  697.     return makeexpr_bicall_1("atan", tp_longreal, ex);
  698. }
  699.  
  700. Expr *func_arctanh(ex)
  701. Expr *ex;
  702. {
  703.     return makeexpr_bicall_1("atanh", tp_longreal, grabarg(ex, 0));
  704. }
  705.  
  706. Stmt *proc_argv()
  707. {
  708.     Expr *ex, *aex, *lex;
  709.  
  710.     if (!skipopenparen())
  711.     return NULL;
  712.     ex = p_expr(tp_integer);
  713.     if (skipcomma()) {
  714.     aex = p_expr(tp_str255);
  715.     } else
  716.     return NULL;
  717.     skipcloseparen();
  718.     lex = makeexpr_sizeof(copyexpr(aex), 0);
  719.     aex = makeexpr_addrstr(aex);
  720.     return makestmt_call(makeexpr_bicall_3("P_sun_argv", tp_void,
  721.                        aex, lex, makeexpr_arglong(ex, 0)));
  722. }
  723.  
  724. Expr *func_asr()
  725. {
  726.     Expr *ex;
  727.  
  728.     if (!skipopenparen())
  729.     return NULL;
  730.     ex = p_expr(tp_integer);
  731.     if (skipcomma()) {
  732.         if (signedshift == 0 || signedshift == 2) {
  733.             ex = makeexpr_bicall_2("P_asr", ex->val.type, ex,
  734.                    p_expr(tp_unsigned));
  735.     } else {
  736.         ex = force_signed(ex);
  737.         ex = makeexpr_bin(EK_RSH, ex->val.type, ex, p_expr(tp_unsigned));
  738.         if (signedshift != 1)
  739.         note("Assuming >> is an arithmetic shift [320]");
  740.     }
  741.     skipcloseparen();
  742.     }
  743.     return ex;
  744. }
  745.  
  746. Expr *func_lsl()
  747. {
  748.     Expr *ex;
  749.  
  750.     if (!skipopenparen())
  751.     return NULL;
  752.     ex = p_expr(tp_integer);
  753.     if (skipcomma()) {
  754.     ex = makeexpr_bin(EK_LSH, ex->val.type, ex, p_expr(tp_unsigned));
  755.     skipcloseparen();
  756.     }
  757.     return ex;
  758. }
  759.  
  760. Expr *func_lsr()
  761. {
  762.     Expr *ex;
  763.  
  764.     if (!skipopenparen())
  765.     return NULL;
  766.     ex = p_expr(tp_integer);
  767.     if (skipcomma()) {
  768.     ex = force_unsigned(ex);
  769.     ex = makeexpr_bin(EK_RSH, ex->val.type, ex, p_expr(tp_unsigned));
  770.     skipcloseparen();
  771.     }
  772.     return ex;
  773. }
  774.  
  775. Expr *func_bin()
  776. {
  777.     note("Using %b for binary printf format [185]");
  778.     return handle_vax_hex(NULL, "b", 1);
  779. }
  780.  
  781. Expr *func_binary(ex)
  782. Expr *ex;
  783. {
  784.     char *cp;
  785.  
  786.     ex = grabarg(ex, 0);
  787.     if (ex->kind == EK_CONST) {
  788.         cp = getstring(ex);
  789.         ex = makeexpr_long(my_strtol(cp, NULL, 2));
  790.         insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer));
  791.         return ex;
  792.     } else {
  793.         return makeexpr_bicall_3("strtol", tp_integer, 
  794.                                  ex, makeexpr_nil(), makeexpr_long(2));
  795.     }
  796. }
  797.  
  798. Static Expr *handle_bitsize(next)
  799. int next;
  800. {
  801.     Expr *ex;
  802.     Type *type;
  803.     int lpar;
  804.     long psize;
  805.  
  806.     lpar = (curtok == TOK_LPAR);
  807.     if (lpar)
  808.     gettok();
  809.     if (curtok == TOK_IDENT && curtokmeaning &&
  810.     curtokmeaning->kind == MK_TYPE) {
  811.         ex = makeexpr_type(curtokmeaning->type);
  812.         gettok();
  813.     } else
  814.         ex = p_expr(NULL);
  815.     type = ex->val.type;
  816.     if (lpar)
  817.     skipcloseparen();
  818.     psize = 0;
  819.     packedsize(NULL, &type, &psize, 0);
  820.     if (psize > 0 && psize < 32 && next) {
  821.     if (psize > 16)
  822.         psize = 32;
  823.     else if (psize > 8)
  824.         psize = 16;
  825.     else if (psize > 4)
  826.         psize = 8;
  827.     else if (psize > 2)
  828.         psize = 4;
  829.     else if (psize > 1)
  830.         psize = 2;
  831.     else
  832.         psize = 1;
  833.     }
  834.     if (psize)
  835.     return makeexpr_long(psize);
  836.     else
  837.     return makeexpr_times(makeexpr_sizeof(ex, 0),
  838.                   makeexpr_long(sizeof_char ? sizeof_char : 8));
  839. }
  840.  
  841. Expr *func_bitsize()
  842. {
  843.     return handle_bitsize(0);
  844. }
  845.  
  846. Expr *func_bitnext()
  847. {
  848.     return handle_bitsize(1);
  849. }
  850.  
  851. Expr *func_blockread()
  852. {
  853.     Expr *ex, *ex2, *vex, *sex, *fex;
  854.     Type *type;
  855.  
  856.     if (!skipopenparen())
  857.     return NULL;
  858.     fex = p_expr(tp_text);
  859.     if (!skipcomma())
  860.     return NULL;
  861.     vex = p_expr(NULL);
  862.     if (!skipcomma())
  863.     return NULL;
  864.     ex2 = p_expr(tp_integer);
  865.     if (curtok == TOK_COMMA) {
  866.         gettok();
  867.         sex = p_expr(tp_integer);
  868.     sex = doseek(copyexpr(fex),
  869.              makeexpr_times(sex, makeexpr_long(512)))->exp1;
  870.     } else
  871.         sex = NULL;
  872.     skipcloseparen();
  873.     type = vex->val.type;
  874.     ex = makeexpr_bicall_4("fread", tp_integer,
  875.                makeexpr_addr(vex),
  876.                makeexpr_long(512),
  877.                convert_size(type, ex2, "BLOCKREAD"),
  878.                copyexpr(fex));
  879.     return makeexpr_comma(sex, ex);
  880. }
  881.  
  882. Expr *func_blockwrite()
  883. {
  884.     Expr *ex, *ex2, *vex, *sex, *fex;
  885.     Type *type;
  886.  
  887.     if (!skipopenparen())
  888.     return NULL;
  889.     fex = p_expr(tp_text);
  890.     if (!skipcomma())
  891.     return NULL;
  892.     vex = p_expr(NULL);
  893.     if (!skipcomma())
  894.     return NULL;
  895.     ex2 = p_expr(tp_integer);
  896.     if (curtok == TOK_COMMA) {
  897.         gettok();
  898.         sex = p_expr(tp_integer);
  899.     sex = doseek(copyexpr(fex),
  900.              makeexpr_times(sex, makeexpr_long(512)))->exp1;
  901.     } else
  902.         sex = NULL;
  903.     skipcloseparen();
  904.     type = vex->val.type;
  905.     ex = makeexpr_bicall_4("fwrite", tp_integer,
  906.                makeexpr_addr(vex),
  907.                makeexpr_long(512),
  908.                convert_size(type, ex2, "BLOCKWRITE"),
  909.                copyexpr(fex));
  910.     return makeexpr_comma(sex, ex);
  911. }
  912.  
  913. Stmt *proc_blockread()
  914. {
  915.     Expr *ex, *ex2, *vex, *rex, *fex;
  916.     Type *type;
  917.  
  918.     if (!skipopenparen())
  919.     return NULL;
  920.     fex = p_expr(tp_text);
  921.     if (!skipcomma())
  922.     return NULL;
  923.     vex = p_expr(NULL);
  924.     if (!skipcomma())
  925.     return NULL;
  926.     ex2 = p_expr(tp_integer);
  927.     if (curtok == TOK_COMMA) {
  928.         gettok();
  929.         rex = p_expr(tp_integer);
  930.     } else
  931.         rex = NULL;
  932.     skipcloseparen();
  933.     type = vex->val.type;
  934.     if (rex) {
  935.         ex = makeexpr_bicall_4("fread", tp_integer,
  936.                                makeexpr_addr(vex),
  937.                                makeexpr_long(1),
  938.                                convert_size(type, ex2, "BLOCKREAD"),
  939.                                copyexpr(fex));
  940.         ex = makeexpr_assign(rex, ex);
  941.         if (!iocheck_flag)
  942.             ex = makeexpr_comma(ex,
  943.                                 makeexpr_assign(makeexpr_var(mp_ioresult),
  944.                                                 makeexpr_long(0)));
  945.     } else {
  946.         ex = makeexpr_bicall_4("fread", tp_integer,
  947.                                makeexpr_addr(vex),
  948.                                convert_size(type, ex2, "BLOCKREAD"),
  949.                                makeexpr_long(1),
  950.                                copyexpr(fex));
  951.         if (checkeof(fex)) {
  952.             ex = makeexpr_bicall_2(name_SETIO, tp_void,
  953.                                    makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
  954.                    makeexpr_name(endoffilename, tp_int));
  955.         }
  956.     }
  957.     return wrapopencheck(makestmt_call(ex), fex);
  958. }
  959.  
  960.