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

编译器/解释器

开发平台:

C/C++

  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. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation (any version).
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; see the file COPYING.  If not, write to
  13. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  14. #define PROTO_FUNCS_C
  15. #include "trans.h"
  16. Static Strlist *enumnames;
  17. Static int enumnamecount;
  18. void setup_funcs()
  19. {
  20.     enumnames = NULL;
  21.     enumnamecount = 0;
  22. }
  23. int isvar(ex, mp)
  24. Expr *ex;
  25. Meaning *mp;
  26. {
  27.     return (ex->kind == EK_VAR && (Meaning *)ex->val.i == mp);
  28. }
  29. char *getstring(ex)
  30. Expr *ex;
  31. {
  32.     ex = makeexpr_stringify(ex);
  33.     if (ex->kind != EK_CONST || ex->val.type->kind != TK_STRING) {
  34.         intwarning("getstring", "Not a string literal [206]");
  35. return "";
  36.     }
  37.     return ex->val.s;
  38. }
  39. Expr *p_parexpr(target)
  40. Type *target;
  41. {
  42.     Expr *ex;
  43.     if (wneedtok(TOK_LPAR)) {
  44. ex = p_expr(target);
  45. if (!wneedtok(TOK_RPAR))
  46.     skippasttotoken(TOK_RPAR, TOK_SEMI);
  47.     } else
  48. ex = p_expr(target);
  49.     return ex;
  50. }
  51. Type *argbasetype(ex)
  52. Expr *ex;
  53. {
  54.     if (ex->kind == EK_CAST)
  55.         ex = ex->args[0];
  56.     if (ex->val.type->kind == TK_POINTER)
  57.         return ex->val.type->basetype;
  58.     else
  59.         return ex->val.type;
  60. }
  61. Type *choosetype(t1, t2)
  62. Type *t1, *t2;
  63. {
  64.     if (t1 == tp_void ||
  65.         (type_sizeof(t2, 1) && !type_sizeof(t1, 1)))
  66.         return t2;
  67.     else
  68.         return t1;
  69. }
  70. Expr *convert_offset(type, ex2)
  71. Type *type;
  72. Expr *ex2;
  73. {
  74.     long size;
  75.     int i;
  76.     Value val;
  77.     Expr *ex3;
  78.     if (type->kind == TK_POINTER ||
  79.         type->kind == TK_ARRAY ||
  80.         type->kind == TK_SET ||
  81.         type->kind == TK_STRING)
  82.         type = type->basetype;
  83.     size = type_sizeof(type, 1);
  84.     if (size == 1)
  85.         return ex2;
  86.     val = eval_expr_pasc(ex2);
  87.     if (val.type) {
  88.         if (val.i == 0)
  89.             return ex2;
  90.         if (size && val.i % size == 0) {
  91.             freeexpr(ex2);
  92.             return makeexpr_long(val.i / size);
  93.         }
  94.     } else {     /* look for terms like "n*sizeof(foo)" */
  95. while (ex2->kind == EK_CAST || ex2->kind == EK_ACTCAST)
  96.     ex2 = ex2->args[0];
  97.         if (ex2->kind == EK_TIMES) {
  98.     for (i = 0; i < ex2->nargs; i++) {
  99. ex3 = convert_offset(type, ex2->args[i]);
  100. if (ex3) {
  101.     ex2->args[i] = ex3;
  102.     return resimplify(ex2);
  103. }
  104.     }
  105.             for (i = 0;
  106.                  i < ex2->nargs && ex2->args[i]->kind != EK_SIZEOF;
  107.                  i++) ;
  108.             if (i < ex2->nargs) {
  109.                 if (ex2->args[i]->args[0]->val.type == type) {
  110.                     delfreearg(&ex2, i);
  111.                     if (ex2->nargs == 1)
  112.                         return ex2->args[0];
  113.                     else
  114.                         return ex2;
  115.                 }
  116.             }
  117.         } else if (ex2->kind == EK_PLUS) {
  118.     ex3 = copyexpr(ex2);
  119.     for (i = 0; i < ex2->nargs; i++) {
  120. ex3->args[i] = convert_offset(type, ex3->args[i]);
  121. if (!ex3->args[i]) {
  122.     freeexpr(ex3);
  123.     return NULL;
  124. }
  125.     }
  126.     freeexpr(ex2);
  127.     return resimplify(ex3);
  128.         } else if (ex2->kind == EK_SIZEOF) {
  129.             if (ex2->args[0]->val.type == type) {
  130.                 freeexpr(ex2);
  131.                 return makeexpr_long(1);
  132.             }
  133.         } else if (ex2->kind == EK_NEG) {
  134.     ex3 = convert_offset(type, ex2->args[0]);
  135.     if (ex3)
  136.                 return makeexpr_neg(ex3);
  137.         }
  138.     }
  139.     return NULL;
  140. }
  141. Expr *convert_size(type, ex, name)
  142. Type *type;
  143. Expr *ex;
  144. char *name;
  145. {
  146.     long size;
  147.     Expr *ex2;
  148.     int i, okay;
  149.     Value val;
  150.     if (debug>2) { fprintf(outf,"convert_size("); dumpexpr(ex); fprintf(outf,")n"); }
  151.     while (type->kind == TK_ARRAY || type->kind == TK_STRING)
  152.         type = type->basetype;
  153.     if (type == tp_void)
  154.         return ex;
  155.     size = type_sizeof(type, 1);
  156.     if (size == 1)
  157.         return ex;
  158.     while (ex->kind == EK_CAST || ex->kind == EK_ACTCAST)
  159. ex = ex->args[0];
  160.     switch (ex->kind) {
  161.         case EK_TIMES:
  162.             for (i = 0; i < ex->nargs; i++) {
  163.                 ex2 = convert_size(type, ex->args[i], NULL);
  164.                 if (ex2) {
  165.                     ex->args[i] = ex2;
  166.                     return resimplify(ex);
  167.                 }
  168.             }
  169.             break;
  170.         case EK_PLUS:
  171.             okay = 1;
  172.             for (i = 0; i < ex->nargs; i++) {
  173.                 ex2 = convert_size(type, ex->args[i], NULL);
  174.                 if (ex2)
  175.                     ex->args[i] = ex2;
  176.                 else
  177.                     okay = 0;
  178.             }
  179.             ex = distribute_plus(ex);
  180.             if ((ex->kind != EK_TIMES || !okay) && name)
  181.                 note(format_s("Suspicious mixture of sizes in %s [173]", name));
  182.             return ex;
  183.         case EK_SIZEOF:
  184.             return ex;
  185. default:
  186.     break;
  187.     }
  188.     val = eval_expr_pasc(ex);
  189.     if (val.type) {
  190.         if (val.i == 0)
  191.             return ex;
  192.         if (size && val.i % size == 0) {
  193.             freeexpr(ex);
  194.             return makeexpr_times(makeexpr_long(val.i / size),
  195.                                   makeexpr_sizeof(makeexpr_type(type), 0));
  196.         }
  197.     }
  198.     if (name) {
  199.         note(format_s("Can't interpret size in %s [174]", name));
  200.         return ex;
  201.     } else
  202.         return NULL;
  203. }
  204. Static Expr *func_abs()
  205. {
  206.     Expr *ex;
  207.     Meaning *tvar;
  208.     int lness;
  209.     ex = p_parexpr(tp_integer);
  210.     if (ex->val.type->kind == TK_REAL)
  211.         return makeexpr_bicall_1("fabs", tp_longreal, ex);
  212.     else {
  213.         lness = exprlongness(ex);
  214.         if (lness < 0)
  215.             return makeexpr_bicall_1("abs", tp_int, ex);
  216.         else if (lness > 0 && *absname) {
  217.             if (ansiC > 0) {
  218.                 return makeexpr_bicall_1("labs", tp_integer, ex);
  219.             } else if (*absname == '*' && (exprspeed(ex) >= 5 || !nosideeffects(ex, 0))) {
  220.                 tvar = makestmttempvar(tp_integer, name_TEMP);
  221.                 return makeexpr_comma(makeexpr_assign(makeexpr_var(tvar),
  222.                                                       ex),
  223.                                       makeexpr_bicall_1(absname, tp_integer,
  224.                                                         makeexpr_var(tvar)));
  225.             } else {
  226.                 return makeexpr_bicall_1(absname, tp_integer, ex);
  227.             }
  228.         } else if (exprspeed(ex) < 5 && nosideeffects(ex, 0)) {
  229.             return makeexpr_cond(makeexpr_rel(EK_LT, copyexpr(ex),
  230.                                                      makeexpr_long(0)),
  231.                                  makeexpr_neg(copyexpr(ex)),
  232.                                  ex);
  233.         } else {
  234.             tvar = makestmttempvar(tp_integer, name_TEMP);
  235.             return makeexpr_cond(makeexpr_rel(EK_LT, makeexpr_assign(makeexpr_var(tvar),
  236.                                                                      ex),
  237.                                                      makeexpr_long(0)),
  238.                                  makeexpr_neg(makeexpr_var(tvar)),
  239.                                  makeexpr_var(tvar));
  240.         }
  241.     }
  242. }
  243. Static Expr *func_addr()
  244. {
  245.     Expr *ex, *ex2, *ex3;
  246.     Type *type, *tp2;
  247.     int haspar;
  248.     haspar = wneedtok(TOK_LPAR);
  249.     ex = p_expr(tp_proc);
  250.     if (curtok == TOK_COMMA) {
  251.         gettok();
  252.         ex2 = p_expr(tp_integer);
  253.         ex3 = convert_offset(ex->val.type, ex2);
  254.         if (checkconst(ex3, 0)) {
  255.             ex = makeexpr_addrf(ex);
  256.         } else {
  257.             ex = makeexpr_addrf(ex);
  258.             if (ex3) {
  259.                 ex = makeexpr_plus(ex, ex3);
  260.             } else {
  261.                 note("Don't know how to reduce offset for ADDR [175]");
  262.                 type = makepointertype(tp_abyte);
  263. tp2 = ex->val.type;
  264.                 ex = makeexpr_cast(makeexpr_plus(makeexpr_cast(ex, type), ex2), tp2);
  265.             }
  266.         }
  267.     } else {
  268. if ((ex->val.type->kind != TK_PROCPTR &&
  269.      ex->val.type->kind != TK_CPROCPTR) ||
  270.     (ex->kind == EK_VAR &&
  271.      ex->val.type == ((Meaning *)ex->val.i)->type))
  272.     ex = makeexpr_addrf(ex);
  273.     }
  274.     if (haspar) {
  275. if (!wneedtok(TOK_RPAR))
  276.     skippasttotoken(TOK_RPAR, TOK_SEMI);
  277.     }
  278.     return ex;
  279. }
  280. Static Expr *func_iaddress()
  281. {
  282.     return makeexpr_cast(func_addr(), tp_integer);
  283. }
  284. Static Expr *func_addtopointer()
  285. {
  286.     Expr *ex, *ex2, *ex3;
  287.     Type *type, *tp2;
  288.     if (!skipopenparen())
  289. return NULL;
  290.     ex = p_expr(tp_anyptr);
  291.     if (skipcomma()) {
  292. ex2 = p_expr(tp_integer);
  293.     } else
  294. ex2 = makeexpr_long(0);
  295.     skipcloseparen();
  296.     ex3 = convert_offset(ex->val.type, ex2);
  297.     if (!checkconst(ex3, 0)) {
  298. if (ex3) {
  299.     ex = makeexpr_plus(ex, ex3);
  300. } else {
  301.     note("Don't know how to reduce offset for ADDTOPOINTER [175]");
  302.     type = makepointertype(tp_abyte);
  303.     tp2 = ex->val.type;
  304.     ex = makeexpr_cast(makeexpr_plus(makeexpr_cast(ex, type), ex2), tp2);
  305. }
  306.     }
  307.     return ex;
  308. }
  309. Stmt *proc_assert()
  310. {
  311.     Expr *ex;
  312.     ex = p_parexpr(tp_boolean);
  313.     return makestmt_call(makeexpr_bicall_1("assert", tp_void, ex));
  314. }
  315. Stmt *wrapopencheck(sp, fex)
  316. Stmt *sp;
  317. Expr *fex;
  318. {
  319.     Stmt *sp2;
  320.     if (FCheck(checkfileisopen) && !is_std_file(fex)) {
  321.         sp2 = makestmt(SK_IF);
  322.         sp2->exp1 = makeexpr_rel(EK_NE, fex, makeexpr_nil());
  323.         sp2->stm1 = sp;
  324.         if (iocheck_flag) {
  325.             sp2->stm2 = makestmt_call(makeexpr_bicall_1(name_ESCIO, tp_integer,
  326. makeexpr_name(filenotopenname, tp_int)));
  327.         } else {
  328.             sp2->stm2 = makestmt_assign(makeexpr_var(mp_ioresult),
  329. makeexpr_name(filenotopenname, tp_int));
  330.         }
  331.         return sp2;
  332.     } else {
  333.         freeexpr(fex);
  334.         return sp;
  335.     }
  336. }
  337. Static Expr *checkfilename(nex)
  338. Expr *nex;
  339. {
  340.     Expr *ex;
  341.     nex = makeexpr_stringcast(nex);
  342.     if (nex->kind == EK_CONST && nex->val.type->kind == TK_STRING) {
  343.         switch (which_lang) {
  344.             case LANG_HP:
  345.                 if (!strncmp(nex->val.s, "#1:", 3) ||
  346.                     !strncmp(nex->val.s, "console:", 8) ||
  347.                     !strncmp(nex->val.s, "CONSOLE:", 8)) {
  348.                     freeexpr(nex);
  349.                     nex = makeexpr_string("/dev/tty");
  350.                 } else if (!strncmp(nex->val.s, "#2:", 3) ||
  351.                            !strncmp(nex->val.s, "systerm:", 8) ||
  352.                            !strncmp(nex->val.s, "SYSTERM:", 8)) {
  353.                     freeexpr(nex);
  354.                     nex = makeexpr_string("/dev/tty");     /* should do more? */
  355.                 } else if (!strncmp(nex->val.s, "#6:", 3) ||
  356.                            !strncmp(nex->val.s, "printer:", 8) ||
  357.                            !strncmp(nex->val.s, "PRINTER:", 8)) {
  358.                     note("Opening a file named PRINTER: [176]");
  359.                 } else if (my_strchr(nex->val.s, ':')) {
  360.                     note("Opening a file whose name contains a ':' [177]");
  361.                 }
  362.                 break;
  363.             case LANG_TURBO:
  364.                 if (checkstring(nex, "con") ||
  365.                     checkstring(nex, "CON") ||
  366.                     checkstring(nex, "")) {
  367.                     freeexpr(nex);
  368.                     nex = makeexpr_string("/dev/tty");
  369.                 } else if (checkstring(nex, "nul") ||
  370.                            checkstring(nex, "NUL")) {
  371.                     freeexpr(nex);
  372.                     nex = makeexpr_string("/dev/null");
  373.                 } else if (checkstring(nex, "lpt1") ||
  374.                            checkstring(nex, "LPT1") ||
  375.                            checkstring(nex, "lpt2") ||
  376.                            checkstring(nex, "LPT2") ||
  377.                            checkstring(nex, "lpt3") ||
  378.                            checkstring(nex, "LPT3") ||
  379.                            checkstring(nex, "com1") ||
  380.                            checkstring(nex, "COM1") ||
  381.                            checkstring(nex, "com2") ||
  382.                            checkstring(nex, "COM2")) {
  383.                     note("Opening a DOS device file name [178]");
  384.                 }
  385.                 break;
  386.     default:
  387. break;
  388.         }
  389.     } else {
  390. if (*filenamefilter && strcmp(filenamefilter, "0")) {
  391.     ex = makeexpr_sizeof(copyexpr(nex), 0);
  392.     nex = makeexpr_bicall_2(filenamefilter, tp_str255, nex, ex);
  393. } else
  394.     nex = makeexpr_stringify(nex);
  395.     }
  396.     return nex;
  397. }
  398. Static Stmt *assignfilename(fex, nex)
  399. Expr *fex, *nex;
  400. {
  401.     Meaning *mp;
  402.     mp = isfilevar(fex);
  403.     if (mp && mp->namedfile) {
  404.         freeexpr(fex);
  405.         return makestmt_call(makeexpr_assign(makeexpr_name(format_s(name_FNVAR, mp->name),
  406.                                                            tp_str255),
  407.                                              nex));
  408.     } else {
  409.         if (mp)
  410.             warning("Don't know how to ASSIGN to a non-explicit file variable [207]");
  411.         else
  412.             note("Encountered an ASSIGN statement [179]");
  413.         return makestmt_call(makeexpr_bicall_2("assign", tp_void, fex, nex));
  414.     }
  415. }
  416. Static Stmt *proc_assign()
  417. {
  418.     Expr *fex, *nex;
  419.     if (!skipopenparen())
  420. return NULL;
  421.     fex = p_expr(tp_text);
  422.     if (!skipcomma())
  423. return NULL;
  424.     nex = checkfilename(p_expr(tp_str255));
  425.     skipcloseparen();
  426.     return assignfilename(fex, nex);
  427. }
  428. Static Stmt *handleopen(code)
  429. int code;
  430. {
  431.     Stmt *sp, *spassign;
  432.     Expr *fex, *nex, *ex;
  433.     Meaning *fmp;
  434.     int storefilename, needcheckopen = 1;
  435.     char modebuf[5], *cp;
  436.     if (!skipopenparen())
  437. return NULL;
  438.     fex = p_expr(tp_text);
  439.     fmp = isfilevar(fex);
  440.     storefilename = (fmp && fmp->namedfile);
  441.     spassign = NULL;
  442.     if (curtok == TOK_COMMA) {
  443.         gettok();
  444.         ex = p_expr(tp_str255);
  445.     } else
  446.         ex = NULL;
  447.     if (ex && (ex->val.type->kind == TK_STRING ||
  448.        ex->val.type->kind == TK_ARRAY)) {
  449.         nex = checkfilename(ex);
  450.         if (storefilename) {
  451.             spassign = assignfilename(copyexpr(fex), nex);
  452.             nex = makeexpr_name(format_s(name_FNVAR, fmp->name), tp_str255);
  453.         }
  454.         if (curtok == TOK_COMMA) {
  455.             gettok();
  456.             ex = p_expr(tp_str255);
  457.         } else
  458.             ex = NULL;
  459.     } else if (storefilename) {
  460.         nex = makeexpr_name(format_s(name_FNVAR, fmp->name), tp_str255);
  461.     } else {
  462. switch (code) {
  463.     case 0:
  464.         if (ex)
  465.     note("Can't interpret name argument in RESET [180]");
  466. break;
  467.        case 1:
  468.         note("REWRITE does not specify a name [181]");
  469. break;
  470.     case 2:
  471. note("OPEN does not specify a name [181]");
  472. break;
  473.     case 3:
  474. note("APPEND does not specify a name [181]");
  475. break;
  476. }
  477. nex = NULL;
  478.     }
  479.     if (ex) {
  480.         if (ord_type(ex->val.type)->kind == TK_INTEGER) {
  481.     if (!checkconst(ex, 1))
  482. note("Ignoring block size in binary file [182]");
  483.             freeexpr(ex);
  484.         } else {
  485.     if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING) {
  486. cp = getstring(ex);
  487. if (strcicmp(cp, "SHARED"))
  488.     note(format_s("Ignoring option string "%s" in open [183]", cp));
  489.     } else
  490. note("Ignoring option string in open [183]");
  491.         }
  492.     }
  493.     switch (code) {
  494.         case 0:  /* reset */
  495.             strcpy(modebuf, "r");
  496.             break;
  497.         case 1:  /* rewrite */
  498.             strcpy(modebuf, "w");
  499.             break;
  500.         case 2:  /* open */
  501.             strcpy(modebuf, openmode);
  502.             break;
  503.         case 3:  /* append */
  504.             strcpy(modebuf, "a");
  505.             break;
  506.     }
  507.     if (!*modebuf) {
  508.         strcpy(modebuf, "r+");
  509.     }
  510.     if (readwriteopen == 2 ||
  511. (readwriteopen && fex->val.type != tp_text)) {
  512. if (!my_strchr(modebuf, '+'))
  513.     strcat(modebuf, "+");
  514.     }
  515.     if (fex->val.type != tp_text && binarymode != 0) {
  516.         if (binarymode == 1)
  517.             strcat(modebuf, "b");
  518.         else
  519.             note("Opening a binary file [184]");
  520.     }
  521.     if (!nex && fmp &&
  522. !is_std_file(fex) &&
  523. (literalfilesflag == 1 ||
  524.  strlist_cifind(literalfiles, fmp->name))) {
  525. nex = makeexpr_string(fmp->name);
  526.     }
  527.     if (!nex) {
  528. if (isvar(fex, mp_output)) {
  529.     note("RESET/REWRITE ignored for file OUTPUT [319]");
  530.     sp = NULL;
  531. } else {
  532.     sp = makestmt_call(makeexpr_bicall_1("rewind", tp_void,
  533.  copyexpr(fex)));
  534.     if (code == 0 || is_std_file(fex)) {
  535. sp = wrapopencheck(sp, copyexpr(fex));
  536. needcheckopen = 0;
  537.     } else
  538. sp = makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex),
  539.       makeexpr_nil()),
  540.  sp,
  541.  makestmt_assign(copyexpr(fex),
  542.  makeexpr_bicall_0("tmpfile",
  543.    tp_text)));
  544. }
  545.     } else if (!strcmp(freopenname, "fclose") ||
  546.        !strcmp(freopenname, "fopen")) {
  547.         sp = makestmt_assign(copyexpr(fex),
  548.                              makeexpr_bicall_2("fopen", tp_text,
  549.                                                copyexpr(nex),
  550.                                                makeexpr_string(modebuf)));
  551.         if (!strcmp(freopenname, "fclose")) {
  552.             sp = makestmt_seq(makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  553.                                           makestmt_call(makeexpr_bicall_1("fclose", tp_void,
  554.                                                                           copyexpr(fex))),
  555.                                           NULL),
  556.                               sp);
  557.         }
  558.     } else {
  559.         sp = makestmt_assign(copyexpr(fex),
  560.                              makeexpr_bicall_3((*freopenname) ? freopenname : "freopen",
  561.                                                tp_text,
  562.                                                copyexpr(nex),
  563.                                                makeexpr_string(modebuf),
  564.                                                copyexpr(fex)));
  565.         if (!*freopenname) {
  566.             sp = makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  567.                              sp,
  568.                              makestmt_assign(copyexpr(fex),
  569.                                              makeexpr_bicall_2("fopen", tp_text,
  570.                                                                copyexpr(nex),
  571.                                                                makeexpr_string(modebuf))));
  572.         }
  573.     }
  574.     if (code == 2 && !*openmode && nex) {
  575.         sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ, copyexpr(fex), makeexpr_nil()),
  576.                                           makestmt_assign(copyexpr(fex),
  577.                                                           makeexpr_bicall_2("fopen", tp_text,
  578.                                                                             copyexpr(nex),
  579.                                                                             makeexpr_string("w+"))),
  580.                                           NULL));
  581.     }
  582.     if (nex)
  583. freeexpr(nex);
  584.     if (FCheck(checkfileopen) && needcheckopen) {
  585.         sp = makestmt_seq(sp, makestmt_call(makeexpr_bicall_2("~SETIO", tp_void,
  586.                                                               makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  587.       makeexpr_name(filenotfoundname, tp_int))));
  588.     }
  589.     sp = makestmt_seq(spassign, sp);
  590.     cp = (code == 0) ? resetbufname : setupbufname;
  591.     if (*cp && fmp)   /* (may be eaten later, if buffering isn't needed) */
  592. sp = makestmt_seq(sp,
  593.          makestmt_call(
  594.                      makeexpr_bicall_2(cp, tp_void, fex,
  595.  makeexpr_type(fex->val.type->basetype->basetype))));
  596.     else
  597. freeexpr(fex);
  598.     skipcloseparen();
  599.     return sp;
  600. }
  601. Static Stmt *proc_append()
  602. {
  603.     return handleopen(3);
  604. }
  605. Static Expr *func_arccos(ex)
  606. Expr *ex;
  607. {
  608.     return makeexpr_bicall_1("acos", tp_longreal, grabarg(ex, 0));
  609. }
  610. Static Expr *func_arcsin(ex)
  611. Expr *ex;
  612. {
  613.     return makeexpr_bicall_1("asin", tp_longreal, grabarg(ex, 0));
  614. }
  615. Static Expr *func_arctan(ex)
  616. Expr *ex;
  617. {
  618.     ex = grabarg(ex, 0);
  619.     if (atan2flag && ex->kind == EK_DIVIDE)
  620.         return makeexpr_bicall_2("atan2", tp_longreal, 
  621.                                  ex->args[0], ex->args[1]);
  622.     return makeexpr_bicall_1("atan", tp_longreal, ex);
  623. }
  624. Static Expr *func_arctanh(ex)
  625. Expr *ex;
  626. {
  627.     return makeexpr_bicall_1("atanh", tp_longreal, grabarg(ex, 0));
  628. }
  629. Static Stmt *proc_argv()
  630. {
  631.     Expr *ex, *aex, *lex;
  632.     if (!skipopenparen())
  633. return NULL;
  634.     ex = p_expr(tp_integer);
  635.     if (skipcomma()) {
  636. aex = p_expr(tp_str255);
  637.     } else
  638. return NULL;
  639.     skipcloseparen();
  640.     lex = makeexpr_sizeof(copyexpr(aex), 0);
  641.     aex = makeexpr_addrstr(aex);
  642.     return makestmt_call(makeexpr_bicall_3("P_sun_argv", tp_void,
  643.    aex, lex, makeexpr_arglong(ex, 0)));
  644. }
  645. Static Expr *func_asr()
  646. {
  647.     Expr *ex;
  648.     if (!skipopenparen())
  649. return NULL;
  650.     ex = p_expr(tp_integer);
  651.     if (skipcomma()) {
  652.         if (signedshift == 0 || signedshift == 2) {
  653.             ex = makeexpr_bicall_2("P_asr", ex->val.type, ex,
  654.    p_expr(tp_unsigned));
  655. } else {
  656.     ex = force_signed(ex);
  657.     ex = makeexpr_bin(EK_RSH, ex->val.type, ex, p_expr(tp_unsigned));
  658.     if (signedshift != 1)
  659. note("Assuming >> is an arithmetic shift [320]");
  660. }
  661. skipcloseparen();
  662.     }
  663.     return ex;
  664. }
  665. Static Expr *func_lsl()
  666. {
  667.     Expr *ex;
  668.     if (!skipopenparen())
  669. return NULL;
  670.     ex = p_expr(tp_integer);
  671.     if (skipcomma()) {
  672. ex = makeexpr_bin(EK_LSH, ex->val.type, ex, p_expr(tp_unsigned));
  673. skipcloseparen();
  674.     }
  675.     return ex;
  676. }
  677. Static Expr *func_lsr()
  678. {
  679.     Expr *ex;
  680.     if (!skipopenparen())
  681. return NULL;
  682.     ex = p_expr(tp_integer);
  683.     if (skipcomma()) {
  684. ex = force_unsigned(ex);
  685. ex = makeexpr_bin(EK_RSH, ex->val.type, ex, p_expr(tp_unsigned));
  686. skipcloseparen();
  687.     }
  688.     return ex;
  689. }
  690. Static Expr *func_bin()
  691. {
  692.     note("Using %b for binary printf format [185]");
  693.     return handle_vax_hex(NULL, "b", 1);
  694. }
  695. Static Expr *func_binary(ex)
  696. Expr *ex;
  697. {
  698.     char *cp;
  699.     ex = grabarg(ex, 0);
  700.     if (ex->kind == EK_CONST) {
  701.         cp = getstring(ex);
  702.         ex = makeexpr_long(my_strtol(cp, NULL, 2));
  703.         insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer));
  704.         return ex;
  705.     } else {
  706.         return makeexpr_bicall_3("strtol", tp_integer, 
  707.                                  ex, makeexpr_nil(), makeexpr_long(2));
  708.     }
  709. }
  710. Static Expr *handle_bitsize(next)
  711. int next;
  712. {
  713.     Expr *ex;
  714.     Type *type;
  715.     int lpar;
  716.     long psize;
  717.     lpar = (curtok == TOK_LPAR);
  718.     if (lpar)
  719. gettok();
  720.     if (curtok == TOK_IDENT && curtokmeaning &&
  721. curtokmeaning->kind == MK_TYPE) {
  722.         ex = makeexpr_type(curtokmeaning->type);
  723.         gettok();
  724.     } else
  725.         ex = p_expr(NULL);
  726.     type = ex->val.type;
  727.     if (lpar)
  728. skipcloseparen();
  729.     psize = 0;
  730.     packedsize(NULL, &type, &psize, 0);
  731.     if (psize > 0 && psize < 32 && next) {
  732. if (psize > 16)
  733.     psize = 32;
  734. else if (psize > 8)
  735.     psize = 16;
  736. else if (psize > 4)
  737.     psize = 8;
  738. else if (psize > 2)
  739.     psize = 4;
  740. else if (psize > 1)
  741.     psize = 2;
  742. else
  743.     psize = 1;
  744.     }
  745.     if (psize)
  746. return makeexpr_long(psize);
  747.     else
  748. return makeexpr_times(makeexpr_sizeof(ex, 0),
  749.       makeexpr_long(sizeof_char ? sizeof_char : 8));
  750. }
  751. Static Expr *func_bitsize()
  752. {
  753.     return handle_bitsize(0);
  754. }
  755. Static Expr *func_bitnext()
  756. {
  757.     return handle_bitsize(1);
  758. }
  759. Static Expr *func_blockread()
  760. {
  761.     Expr *ex, *ex2, *vex, *sex, *fex;
  762.     Type *type;
  763.     if (!skipopenparen())
  764. return NULL;
  765.     fex = p_expr(tp_text);
  766.     if (!skipcomma())
  767. return NULL;
  768.     vex = p_expr(NULL);
  769.     if (!skipcomma())
  770. return NULL;
  771.     ex2 = p_expr(tp_integer);
  772.     if (curtok == TOK_COMMA) {
  773.         gettok();
  774.         sex = p_expr(tp_integer);
  775. sex = doseek(copyexpr(fex),
  776.      makeexpr_times(sex, makeexpr_long(512)))->exp1;
  777.     } else
  778.         sex = NULL;
  779.     skipcloseparen();
  780.     type = vex->val.type;
  781.     ex = makeexpr_bicall_4("fread", tp_integer,
  782.    makeexpr_addr(vex),
  783.    makeexpr_long(512),
  784.    convert_size(type, ex2, "BLOCKREAD"),
  785.    copyexpr(fex));
  786.     return makeexpr_comma(sex, ex);
  787. }
  788. Static Expr *func_blockwrite()
  789. {
  790.     Expr *ex, *ex2, *vex, *sex, *fex;
  791.     Type *type;
  792.     if (!skipopenparen())
  793. return NULL;
  794.     fex = p_expr(tp_text);
  795.     if (!skipcomma())
  796. return NULL;
  797.     vex = p_expr(NULL);
  798.     if (!skipcomma())
  799. return NULL;
  800.     ex2 = p_expr(tp_integer);
  801.     if (curtok == TOK_COMMA) {
  802.         gettok();
  803.         sex = p_expr(tp_integer);
  804. sex = doseek(copyexpr(fex),
  805.      makeexpr_times(sex, makeexpr_long(512)))->exp1;
  806.     } else
  807.         sex = NULL;
  808.     skipcloseparen();
  809.     type = vex->val.type;
  810.     ex = makeexpr_bicall_4("fwrite", tp_integer,
  811.    makeexpr_addr(vex),
  812.    makeexpr_long(512),
  813.    convert_size(type, ex2, "BLOCKWRITE"),
  814.    copyexpr(fex));
  815.     return makeexpr_comma(sex, ex);
  816. }
  817. Static Stmt *proc_blockread()
  818. {
  819.     Expr *ex, *ex2, *vex, *rex, *fex;
  820.     Type *type;
  821.     if (!skipopenparen())
  822. return NULL;
  823.     fex = p_expr(tp_text);
  824.     if (!skipcomma())
  825. return NULL;
  826.     vex = p_expr(NULL);
  827.     if (!skipcomma())
  828. return NULL;
  829.     ex2 = p_expr(tp_integer);
  830.     if (curtok == TOK_COMMA) {
  831.         gettok();
  832.         rex = p_expr(tp_integer);
  833.     } else
  834.         rex = NULL;
  835.     skipcloseparen();
  836.     type = vex->val.type;
  837.     if (rex) {
  838.         ex = makeexpr_bicall_4("fread", tp_integer,
  839.                                makeexpr_addr(vex),
  840.                                makeexpr_long(1),
  841.                                convert_size(type, ex2, "BLOCKREAD"),
  842.                                copyexpr(fex));
  843.         ex = makeexpr_assign(rex, ex);
  844.         if (!iocheck_flag)
  845.             ex = makeexpr_comma(ex,
  846.                                 makeexpr_assign(makeexpr_var(mp_ioresult),
  847.                                                 makeexpr_long(0)));
  848.     } else {
  849.         ex = makeexpr_bicall_4("fread", tp_integer,
  850.                                makeexpr_addr(vex),
  851.                                convert_size(type, ex2, "BLOCKREAD"),
  852.                                makeexpr_long(1),
  853.                                copyexpr(fex));
  854.         if (checkeof(fex)) {
  855.             ex = makeexpr_bicall_2(name_SETIO, tp_void,
  856.                                    makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
  857.    makeexpr_name(endoffilename, tp_int));
  858.         }
  859.     }
  860.     return wrapopencheck(makestmt_call(ex), fex);
  861. }
  862. Static Stmt *proc_blockwrite()
  863. {
  864.     Expr *ex, *ex2, *vex, *rex, *fex;
  865.     Type *type;
  866.     if (!skipopenparen())
  867. return NULL;
  868.     fex = p_expr(tp_text);
  869.     if (!skipcomma())
  870. return NULL;
  871.     vex = p_expr(NULL);
  872.     if (!skipcomma())
  873. return NULL;
  874.     ex2 = p_expr(tp_integer);
  875.     if (curtok == TOK_COMMA) {
  876.         gettok();
  877.         rex = p_expr(tp_integer);
  878.     } else
  879.         rex = NULL;
  880.     skipcloseparen();
  881.     type = vex->val.type;
  882.     if (rex) {
  883.         ex = makeexpr_bicall_4("fwrite", tp_integer,
  884.                                makeexpr_addr(vex),
  885.                                makeexpr_long(1),
  886.                                convert_size(type, ex2, "BLOCKWRITE"),
  887.                                copyexpr(fex));
  888.         ex = makeexpr_assign(rex, ex);
  889.         if (!iocheck_flag)
  890.             ex = makeexpr_comma(ex,
  891.                                 makeexpr_assign(makeexpr_var(mp_ioresult),
  892.                                                 makeexpr_long(0)));
  893.     } else {
  894.         ex = makeexpr_bicall_4("fwrite", tp_integer,
  895.                                makeexpr_addr(vex),
  896.                                convert_size(type, ex2, "BLOCKWRITE"),
  897.                                makeexpr_long(1),
  898.                                copyexpr(fex));
  899.         if (FCheck(checkfilewrite)) {
  900.             ex = makeexpr_bicall_2(name_SETIO, tp_void,
  901.                                    makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
  902.    makeexpr_name(filewriteerrorname, tp_int));
  903.         }
  904.     }
  905.     return wrapopencheck(makestmt_call(ex), fex);
  906. }
  907. Static Stmt *proc_bclr()
  908. {
  909.     Expr *ex, *ex2;
  910.     if (!skipopenparen())
  911. return NULL;
  912.     ex = p_expr(tp_integer);
  913.     if (!skipcomma())
  914. return NULL;
  915.     ex2 = p_expr(tp_integer);
  916.     skipcloseparen();
  917.     return makestmt_assign(ex,
  918.    makeexpr_bin(EK_BAND, ex->val.type,
  919. copyexpr(ex),
  920. makeexpr_un(EK_BNOT, ex->val.type,
  921. makeexpr_bin(EK_LSH, tp_integer,
  922.      makeexpr_arglong(
  923.          makeexpr_long(1), 1),
  924.      ex2))));
  925. }
  926. Static Stmt *proc_bset()
  927. {
  928.     Expr *ex, *ex2;
  929.     if (!skipopenparen())
  930. return NULL;
  931.     ex = p_expr(tp_integer);
  932.     if (!skipcomma())
  933. return NULL;
  934.     ex2 = p_expr(tp_integer);
  935.     skipcloseparen();
  936.     return makestmt_assign(ex,
  937.    makeexpr_bin(EK_BOR, ex->val.type,
  938. copyexpr(ex),
  939. makeexpr_bin(EK_LSH, tp_integer,
  940.      makeexpr_arglong(
  941.          makeexpr_long(1), 1),
  942.      ex2)));
  943. }
  944. Static Expr *func_bsl()
  945. {
  946.     Expr *ex, *ex2;
  947.     if (!skipopenparen())
  948. return NULL;
  949.     ex = p_expr(tp_integer);
  950.     if (!skipcomma())
  951. return NULL;
  952.     ex2 = p_expr(tp_integer);
  953.     skipcloseparen();
  954.     return makeexpr_bin(EK_LSH, tp_integer, ex, ex2);
  955. }
  956. Static Expr *func_bsr()
  957. {
  958.     Expr *ex, *ex2;
  959.     if (!skipopenparen())
  960. return NULL;
  961.     ex = p_expr(tp_integer);
  962.     if (!skipcomma())
  963. return NULL;
  964.     ex2 = p_expr(tp_integer);
  965.     skipcloseparen();
  966.     return makeexpr_bin(EK_RSH, tp_integer, force_unsigned(ex), ex2);
  967. }
  968. Static Expr *func_btst()
  969. {
  970.     Expr *ex, *ex2;
  971.     if (!skipopenparen())
  972. return NULL;
  973.     ex = p_expr(tp_integer);
  974.     if (!skipcomma())
  975. return NULL;
  976.     ex2 = p_expr(tp_integer);
  977.     skipcloseparen();
  978.     return makeexpr_rel(EK_NE,
  979. makeexpr_bin(EK_BAND, tp_integer,
  980.      ex,
  981.      makeexpr_bin(EK_LSH, tp_integer,
  982.   makeexpr_arglong(
  983.       makeexpr_long(1), 1),
  984.   ex2)),
  985. makeexpr_long(0));
  986. }
  987. Static Expr *func_byteread()
  988. {
  989.     Expr *ex, *ex2, *vex, *sex, *fex;
  990.     Type *type;
  991.     if (!skipopenparen())
  992. return NULL;
  993.     fex = p_expr(tp_text);
  994.     if (!skipcomma())
  995. return NULL;
  996.     vex = p_expr(NULL);
  997.     if (!skipcomma())
  998. return NULL;
  999.     ex2 = p_expr(tp_integer);
  1000.     if (curtok == TOK_COMMA) {
  1001.         gettok();
  1002.         sex = p_expr(tp_integer);
  1003. sex = doseek(copyexpr(fex), sex)->exp1;
  1004.     } else
  1005.         sex = NULL;
  1006.     skipcloseparen();
  1007.     type = vex->val.type;
  1008.     ex = makeexpr_bicall_4("fread", tp_integer,
  1009.    makeexpr_addr(vex),
  1010.    makeexpr_long(1),
  1011.    convert_size(type, ex2, "BYTEREAD"),
  1012.    copyexpr(fex));
  1013.     return makeexpr_comma(sex, ex);
  1014. }
  1015. Static Expr *func_bytewrite()
  1016. {
  1017.     Expr *ex, *ex2, *vex, *sex, *fex;
  1018.     Type *type;
  1019.     if (!skipopenparen())
  1020. return NULL;
  1021.     fex = p_expr(tp_text);
  1022.     if (!skipcomma())
  1023. return NULL;
  1024.     vex = p_expr(NULL);
  1025.     if (!skipcomma())
  1026. return NULL;
  1027.     ex2 = p_expr(tp_integer);
  1028.     if (curtok == TOK_COMMA) {
  1029.         gettok();
  1030.         sex = p_expr(tp_integer);
  1031. sex = doseek(copyexpr(fex), sex)->exp1;
  1032.     } else
  1033.         sex = NULL;
  1034.     skipcloseparen();
  1035.     type = vex->val.type;
  1036.     ex = makeexpr_bicall_4("fwrite", tp_integer,
  1037.    makeexpr_addr(vex),
  1038.    makeexpr_long(1),
  1039.    convert_size(type, ex2, "BYTEWRITE"),
  1040.    copyexpr(fex));
  1041.     return makeexpr_comma(sex, ex);
  1042. }
  1043. Static Expr *func_byte_offset()
  1044. {
  1045.     Type *tp;
  1046.     Meaning *mp;
  1047.     Expr *ex;
  1048.     if (!skipopenparen())
  1049. return NULL;
  1050.     tp = p_type(NULL);
  1051.     if (!skipcomma())
  1052. return NULL;
  1053.     if (!wexpecttok(TOK_IDENT))
  1054. return NULL;
  1055.     mp = curtoksym->fbase;
  1056.     while (mp && mp->rectype != tp)
  1057. mp = mp->snext;
  1058.     if (!mp)
  1059. ex = makeexpr_name(curtokcase, tp_integer);
  1060.     else
  1061. ex = makeexpr_name(mp->name, tp_integer);
  1062.     gettok();
  1063.     skipcloseparen();
  1064.     return makeexpr_bicall_2("OFFSETOF", (size_t_long) ? tp_integer : tp_int,
  1065.      makeexpr_type(tp), ex);
  1066. }
  1067. Static Stmt *proc_call()
  1068. {
  1069.     Expr *ex, *ex2, *ex3;
  1070.     Type *type, *tp;
  1071.     Meaning *mp;
  1072.     if (!skipopenparen())
  1073. return NULL;
  1074.     ex2 = p_expr(tp_proc);
  1075.     type = ex2->val.type;
  1076.     if (type->kind != TK_PROCPTR && type->kind != TK_CPROCPTR) {
  1077.         warning("CALL requires a procedure variable [208]");
  1078. type = tp_proc;
  1079.     }
  1080.     ex = makeexpr(EK_SPCALL, 1);
  1081.     ex->val.type = tp_void;
  1082.     ex->args[0] = copyexpr(ex2);
  1083.     if (type->escale != 0)
  1084. ex->args[0] = makeexpr_cast(makeexpr_dotq(ex2, "proc", tp_anyptr),
  1085.     makepointertype(type->basetype));
  1086.     mp = type->basetype->fbase;
  1087.     if (mp) {
  1088.         if (wneedtok(TOK_COMMA))
  1089.     ex = p_funcarglist(ex, mp, 0, 0);
  1090.     }
  1091.     skipcloseparen();
  1092.     if (type->escale != 1 || hasstaticlinks == 2) {
  1093. freeexpr(ex2);
  1094. return makestmt_call(ex);
  1095.     }
  1096.     ex2 = makeexpr_dotq(ex2, "link", tp_anyptr),
  1097.     ex3 = copyexpr(ex);
  1098.     insertarg(&ex3, ex3->nargs, copyexpr(ex2));
  1099.     tp = maketype(TK_FUNCTION);
  1100.     tp->basetype = type->basetype->basetype;
  1101.     tp->fbase = type->basetype->fbase;
  1102.     tp->issigned = 1;
  1103.     ex3->args[0]->val.type = makepointertype(tp);
  1104.     return makestmt_if(makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
  1105.                        makestmt_call(ex3),
  1106.                        makestmt_call(ex));
  1107. }
  1108. Static Expr *func_chr()
  1109. {
  1110.     Expr *ex;
  1111.     ex = p_expr(tp_integer);
  1112.     if ((exprlongness(ex) < 0 || ex->kind == EK_CAST) && ex->kind != EK_ACTCAST)
  1113.         ex->val.type = tp_char;
  1114.     else
  1115.         ex = makeexpr_cast(ex, tp_char);
  1116.     return ex;
  1117. }
  1118. Static Stmt *proc_close()
  1119. {
  1120.     Stmt *sp;
  1121.     Expr *fex, *ex;
  1122.     char *opt;
  1123.     if (!skipopenparen())
  1124. return NULL;
  1125.     fex = p_expr(tp_text);
  1126.     sp = makestmt_if(makeexpr_rel(EK_NE, copyexpr(fex), makeexpr_nil()),
  1127.                      makestmt_call(makeexpr_bicall_1("fclose", tp_void,
  1128.                                                      copyexpr(fex))),
  1129.                      (FCheck(checkfileisopen))
  1130.          ? makestmt_call(
  1131.      makeexpr_bicall_1(name_ESCIO,
  1132.        tp_integer,
  1133.        makeexpr_name(filenotopenname,
  1134.      tp_int)))
  1135.                          : NULL);
  1136.     if (curtok == TOK_COMMA) {
  1137.         gettok();
  1138. opt = "";
  1139. if (curtok == TOK_IDENT &&
  1140.     (!strcicmp(curtokbuf, "LOCK") ||
  1141.      !strcicmp(curtokbuf, "PURGE") ||
  1142.      !strcicmp(curtokbuf, "NORMAL") ||
  1143.      !strcicmp(curtokbuf, "CRUNCH"))) {
  1144.     opt = stralloc(curtokbuf);
  1145.     gettok();
  1146. } else {
  1147.     ex = p_expr(tp_str255);
  1148.     if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING)
  1149. opt = ex->val.s;
  1150. }
  1151. if (!strcicmp(opt, "PURGE")) {
  1152.     note("File is being closed with PURGE option [186]");
  1153.         }
  1154.     }
  1155.     sp = makestmt_seq(sp, makestmt_assign(fex, makeexpr_nil()));
  1156.     skipcloseparen();
  1157.     return sp;
  1158. }
  1159. Static Expr *func_concat()
  1160. {
  1161.     Expr *ex;
  1162.     if (!skipopenparen())
  1163. return makeexpr_string("oops");
  1164.     ex = p_expr(tp_str255);
  1165.     while (curtok == TOK_COMMA) {
  1166.         gettok();
  1167.         ex = makeexpr_concat(ex, p_expr(tp_str255), 0);
  1168.     }
  1169.     skipcloseparen();
  1170.     return ex;
  1171. }
  1172. Static Expr *func_copy(ex)
  1173. Expr *ex;
  1174. {
  1175.     if (isliteralconst(ex->args[3], NULL) == 2 &&
  1176.         ex->args[3]->val.i >= stringceiling) {
  1177.         return makeexpr_bicall_3("sprintf", ex->val.type,
  1178.                                  ex->args[0],
  1179.                                  makeexpr_string("%s"),
  1180.                                  bumpstring(ex->args[1], 
  1181.                                             makeexpr_unlongcast(ex->args[2]), 1));
  1182.     }
  1183.     if (checkconst(ex->args[2], 1)) {
  1184.         return makeexpr_addr(makeexpr_substring(ex->args[0], ex->args[1], 
  1185.                                                 ex->args[2], ex->args[3]));
  1186.     }
  1187.     return makeexpr_bicall_4(strsubname, ex->val.type,
  1188.                              ex->args[0],
  1189.                              ex->args[1],
  1190.                              makeexpr_arglong(ex->args[2], 0),
  1191.                              makeexpr_arglong(ex->args[3], 0));
  1192. }
  1193. Static Expr *func_cos(ex)
  1194. Expr *ex;
  1195. {
  1196.     return makeexpr_bicall_1("cos", tp_longreal, grabarg(ex, 0));
  1197. }
  1198. Static Expr *func_cosh(ex)
  1199. Expr *ex;
  1200. {
  1201.     return makeexpr_bicall_1("cosh", tp_longreal, grabarg(ex, 0));
  1202. }
  1203. Static Stmt *proc_cycle()
  1204. {
  1205.     return makestmt(SK_CONTINUE);
  1206. }
  1207. Static Stmt *proc_dec()
  1208. {
  1209.     Expr *vex, *ex;
  1210.     if (!skipopenparen())
  1211. return NULL;
  1212.     vex = p_expr(NULL);
  1213.     if (curtok == TOK_COMMA) {
  1214.         gettok();
  1215.         ex = p_expr(tp_integer);
  1216.     } else
  1217.         ex = makeexpr_long(1);
  1218.     skipcloseparen();
  1219.     return makestmt_assign(vex, makeexpr_minus(copyexpr(vex), ex));
  1220. }
  1221. Static Expr *func_dec()
  1222. {
  1223.     return handle_vax_hex(NULL, "d", 0);
  1224. }
  1225. Static Stmt *proc_delete(ex)
  1226. Expr *ex;
  1227. {
  1228.     if (ex->nargs == 1)   /* Kludge for Oregon Software Pascal's delete(f) */
  1229. return makestmt_call(makeexpr_bicall_1(strdeletename, tp_void, ex->args[0]));
  1230.     return makestmt_call(makeexpr_bicall_3(strdeletename, tp_void,
  1231.                                            ex->args[0], 
  1232.                                            makeexpr_arglong(ex->args[1], 0),
  1233.                                            makeexpr_arglong(ex->args[2], 0)));
  1234. }
  1235. void parse_special_variant(tp, buf)
  1236. Type *tp;
  1237. char *buf;
  1238. {
  1239.     char *cp;
  1240.     Expr *ex;
  1241.     if (!tp)
  1242. intwarning("parse_special_variant", "tp == NULL");
  1243.     if (!tp || tp->meaning == NULL) {
  1244. *buf = 0;
  1245. if (curtok == TOK_COMMA) {
  1246.     skiptotoken(TOK_RPAR);
  1247. }
  1248. return;
  1249.     }
  1250.     strcpy(buf, tp->meaning->name);
  1251.     while (curtok == TOK_COMMA) {
  1252. gettok();
  1253. cp = buf + strlen(buf);
  1254. *cp++ = '.';
  1255. if (curtok == TOK_MINUS) {
  1256.     *cp++ = '-';
  1257.     gettok();
  1258. }
  1259. if (curtok == TOK_INTLIT ||
  1260.     curtok == TOK_HEXLIT ||
  1261.     curtok == TOK_OCTLIT) {
  1262.     sprintf(cp, "%ld", curtokint);
  1263.     gettok();
  1264. } else if (curtok == TOK_HAT || curtok == TOK_STRLIT) {
  1265.     ex = makeexpr_charcast(accumulate_strlit());
  1266.     if (ex->kind == EK_CONST) {
  1267. if (ex->val.i <= 32 || ex->val.i > 126 ||
  1268.     ex->val.i == ''' || ex->val.i == '\' ||
  1269.     ex->val.i == '=' || ex->val.i == '}')
  1270.     sprintf(cp, "%ld", ex->val.i);
  1271. else
  1272.     strcpy(cp, makeCchar(ex->val.i));
  1273.     } else {
  1274. *buf = 0;
  1275. *cp = 0;
  1276.     }
  1277.     freeexpr(ex);
  1278. } else {
  1279.     if (!wexpecttok(TOK_IDENT)) {
  1280. skiptotoken(TOK_RPAR);
  1281. return;
  1282.     }
  1283.     if (curtokmeaning)
  1284. strcpy(cp, curtokmeaning->name);
  1285.     else
  1286. strcpy(cp, curtokbuf);
  1287.     gettok();
  1288. }
  1289.     }
  1290. }
  1291. char *find_special_variant(buf, spname, splist, need)
  1292. char *buf, *spname;
  1293. Strlist *splist;
  1294. int need;
  1295. {
  1296.     Strlist *best = NULL;
  1297.     int len, bestlen = -1;
  1298.     char *cp, *cp2;
  1299.     if (!*buf)
  1300. return NULL;
  1301.     while (splist) {
  1302. cp = splist->s;
  1303. cp2 = buf;
  1304. while (*cp && toupper(*cp) == toupper(*cp2))
  1305.     cp++, cp2++;
  1306. len = cp2 - buf;
  1307. if (!*cp && (!*cp2 || *cp2 == '.') && len > bestlen) {
  1308.     best = splist;
  1309.     bestlen = len;
  1310. }
  1311. splist = splist->next;
  1312.     }
  1313.     if (bestlen != strlen(buf) && my_strchr(buf, '.')) {
  1314. if ((need & 1) || bestlen >= 0) {
  1315.     if (need & 2)
  1316. return NULL;
  1317.     if (spname)
  1318. note(format_ss("No %s form known for %s [187]",
  1319.        spname, strupper(buf)));
  1320. }
  1321.     }
  1322.     if (bestlen >= 0)
  1323. return (char *)best->value;
  1324.     else
  1325. return NULL;
  1326. }
  1327. Static char *choose_free_func(ex)
  1328. Expr *ex;
  1329. {
  1330.     if (!*freename) {
  1331. if (!*freervaluename)
  1332.     return "free";
  1333. else
  1334.     return freervaluename;
  1335.     }
  1336.     if (!*freervaluename)
  1337. return freervaluename;
  1338.     if (expr_is_lvalue(ex))
  1339. return freename;
  1340.     else
  1341. return freervaluename;
  1342. }
  1343. Static Stmt *proc_dispose()
  1344. {
  1345.     Expr *ex;
  1346.     Type *type;
  1347.     char *name, vbuf[1000];
  1348.     if (!skipopenparen())
  1349. return NULL;
  1350.     ex = p_expr(tp_anyptr);
  1351.     type = ex->val.type->basetype;
  1352.     parse_special_variant(type, vbuf);
  1353.     skipcloseparen();
  1354.     name = find_special_variant(vbuf, "SpecialFree", specialfrees, 0);
  1355.     if (!name)
  1356. name = choose_free_func(ex);
  1357.     return makestmt_call(makeexpr_bicall_1(name, tp_void, ex));
  1358. }
  1359. Static Expr *func_exp(ex)
  1360. Expr *ex;
  1361. {
  1362.     return makeexpr_bicall_1("exp", tp_longreal, grabarg(ex, 0));
  1363. }
  1364. Static Expr *func_expo(ex)
  1365. Expr *ex;
  1366. {
  1367.     Meaning *tvar;
  1368.     tvar = makestmttempvar(tp_int, name_TEMP);
  1369.     return makeexpr_comma(makeexpr_bicall_2("frexp", tp_longreal,
  1370.     grabarg(ex, 0),
  1371.     makeexpr_addr(makeexpr_var(tvar))),
  1372.   makeexpr_var(tvar));
  1373. }
  1374. int is_std_file(ex)
  1375. Expr *ex;
  1376. {
  1377.     return isvar(ex, mp_input) || isvar(ex, mp_output) ||
  1378.            isvar(ex, mp_stderr);
  1379. }
  1380. Static Expr *iofunc(ex, code)
  1381. Expr *ex;
  1382. int code;
  1383. {
  1384.     Expr *ex2 = NULL, *ex3 = NULL;
  1385.     Meaning *tvar = NULL;
  1386.     if (FCheck(checkfileisopen) && !is_std_file(ex)) {
  1387.         if (exprspeed(ex) < 5 && nosideeffects(ex, 0)) {
  1388.             ex2 = copyexpr(ex);
  1389.         } else {
  1390.             ex3 = ex;
  1391.             tvar = makestmttempvar(ex->val.type, name_TEMP);
  1392.             ex2 = makeexpr_var(tvar);
  1393.             ex = makeexpr_var(tvar);
  1394.         }
  1395.     }
  1396.     switch (code) {
  1397.         case 0:  /* eof */
  1398.     if (*eofname)
  1399. ex = makeexpr_bicall_1(eofname, tp_boolean, ex);
  1400.     else
  1401. ex = makeexpr_rel(EK_NE, makeexpr_bicall_1("feof", tp_int, ex),
  1402.          makeexpr_long(0));
  1403.             break;
  1404.         case 1:  /* eoln */
  1405.             ex = makeexpr_bicall_1(eolnname, tp_boolean, ex);
  1406.             break;
  1407.         case 2:  /* position or filepos */
  1408.             ex = makeexpr_bicall_1(fileposname, tp_integer, ex);
  1409.             break;
  1410.         case 3:  /* maxpos or filesize */
  1411.             ex = makeexpr_bicall_1(maxposname, tp_integer, ex);
  1412.             break;
  1413.     }
  1414.     if (ex2) {
  1415.         ex = makeexpr_bicall_4("~CHKIO",
  1416.                                (code == 0 || code == 1) ? tp_boolean : tp_integer,
  1417.                                makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
  1418.        makeexpr_name("FileNotOpen", tp_int),
  1419.                                ex, makeexpr_long(0));
  1420.     }
  1421.     if (ex3)
  1422.         ex = makeexpr_comma(makeexpr_assign(makeexpr_var(tvar), ex3), ex);
  1423.     return ex;
  1424. }
  1425. Static Expr *func_eof()
  1426. {
  1427.     Expr *ex;
  1428.     if (curtok == TOK_LPAR)
  1429.         ex = p_parexpr(tp_text);
  1430.     else
  1431.         ex = makeexpr_var(mp_input);
  1432.     return iofunc(ex, 0);
  1433. }
  1434. Static Expr *func_eoln()
  1435. {
  1436.     Expr *ex;
  1437.     if (curtok == TOK_LPAR)
  1438.         ex = p_parexpr(tp_text);
  1439.     else
  1440.         ex = makeexpr_var(mp_input);
  1441.     return iofunc(ex, 1);
  1442. }
  1443. Static Stmt *proc_escape()
  1444. {
  1445.     Expr *ex;
  1446.     if (curtok == TOK_LPAR)
  1447.         ex = p_parexpr(tp_integer);
  1448.     else
  1449.         ex = makeexpr_long(0);
  1450.     return makestmt_call(makeexpr_bicall_1(name_ESCAPE, tp_int, 
  1451.                                            makeexpr_arglong(ex, 0)));
  1452. }
  1453. Static Stmt *proc_excl()
  1454. {
  1455.     Expr *vex, *ex;
  1456.     if (!skipopenparen())
  1457. return NULL;
  1458.     vex = p_expr(NULL);
  1459.     if (!skipcomma())
  1460. return NULL;
  1461.     ex = p_expr(vex->val.type->indextype);
  1462.     skipcloseparen();
  1463.     if (vex->val.type->kind == TK_SMALLSET)
  1464. return makestmt_assign(vex, makeexpr_bin(EK_BAND, vex->val.type,
  1465.  copyexpr(vex),
  1466.  makeexpr_un(EK_BNOT, vex->val.type,
  1467.      makeexpr_bin(EK_LSH, vex->val.type,
  1468.   makeexpr_longcast(makeexpr_long(1), 1),
  1469.   ex))));
  1470.     else
  1471. return makestmt_call(makeexpr_bicall_2(setremname, tp_void, vex,
  1472.        makeexpr_arglong(enum_to_int(ex), 0)));
  1473. }
  1474. Stmt *proc_exit()
  1475. {
  1476.     Stmt *sp;
  1477.     if (modula2) {
  1478. return makestmt(SK_BREAK);
  1479.     }
  1480.     if (curtok == TOK_LPAR) {
  1481.         gettok();
  1482. if (curtok == TOK_PROGRAM ||
  1483.     (curtok == TOK_IDENT && curtokmeaning->kind == MK_MODULE)) {
  1484.     gettok();
  1485.     skipcloseparen();
  1486.     return makestmt_call(makeexpr_bicall_1("exit", tp_void,
  1487.    makeexpr_long(0)));
  1488. }
  1489.         if (curtok != TOK_IDENT || !curtokmeaning || curtokmeaning != curctx)
  1490.             note("Attempting to EXIT beyond this function [188]");
  1491.         gettok();
  1492. skipcloseparen();
  1493.     }
  1494.     sp = makestmt(SK_RETURN);
  1495.     if (curctx->kind == MK_FUNCTION && curctx->isfunction) {
  1496.         sp->exp1 = makeexpr_var(curctx->cbase);
  1497.         curctx->cbase->refcount++;
  1498.     }
  1499.     return sp;
  1500. }
  1501. Static Expr *file_iofunc(code, base)
  1502. int code;
  1503. long base;
  1504. {
  1505.     Expr *ex;
  1506.     Type *basetype;
  1507.     if (curtok == TOK_LPAR)
  1508. ex = p_parexpr(tp_text);
  1509.     else
  1510. ex = makeexpr_var(mp_input);
  1511.     if (!ex->val.type || !ex->val.type->basetype ||
  1512. !ex->val.type->basetype->basetype)
  1513. basetype = tp_char;
  1514.     else
  1515. basetype = ex->val.type->basetype->basetype;
  1516.     return makeexpr_plus(makeexpr_div(iofunc(ex, code),
  1517.                                       makeexpr_sizeof(makeexpr_type(basetype), 0)),
  1518.                          makeexpr_long(base));
  1519. }
  1520. Static Expr *func_fcall()
  1521. {
  1522.     Expr *ex, *ex2, *ex3;
  1523.     Type *type, *tp;
  1524.     Meaning *mp, *tvar = NULL;
  1525.     int firstarg = 0;
  1526.     if (!skipopenparen())
  1527. return NULL;
  1528.     ex2 = p_expr(tp_proc);
  1529.     type = ex2->val.type;
  1530.     if (type->kind != TK_PROCPTR && type->kind != TK_CPROCPTR) {
  1531.         warning("FCALL requires a function variable [209]");
  1532. type = tp_proc;
  1533.     }
  1534.     ex = makeexpr(EK_SPCALL, 1);
  1535.     ex->val.type = type->basetype->basetype;
  1536.     ex->args[0] = copyexpr(ex2);
  1537.     if (type->escale != 0)
  1538. ex->args[0] = makeexpr_cast(makeexpr_dotq(ex2, "proc", tp_anyptr),
  1539.     makepointertype(type->basetype));
  1540.     mp = type->basetype->fbase;
  1541.     if (mp && mp->isreturn) {    /* pointer to buffer for return value */
  1542.         tvar = makestmttempvar(ex->val.type->basetype,
  1543.             (ex->val.type->basetype->kind == TK_STRING) ? name_STRING : name_TEMP);
  1544.         insertarg(&ex, 1, makeexpr_addr(makeexpr_var(tvar)));
  1545.         mp = mp->xnext;
  1546. firstarg++;
  1547.     }
  1548.     if (mp) {
  1549.         if (wneedtok(TOK_COMMA))
  1550.     ex = p_funcarglist(ex, mp, 0, 0);
  1551.     }
  1552.     if (tvar)
  1553. ex = makeexpr_hat(ex, 0);    /* returns pointer to structured result */
  1554.     skipcloseparen();
  1555.     if (type->escale != 1 || hasstaticlinks == 2) {
  1556. freeexpr(ex2);
  1557. return ex;
  1558.     }
  1559.     ex2 = makeexpr_dotq(ex2, "link", tp_anyptr),
  1560.     ex3 = copyexpr(ex);
  1561.     insertarg(&ex3, ex3->nargs, copyexpr(ex2));
  1562.     tp = maketype(TK_FUNCTION);
  1563.     tp->basetype = type->basetype->basetype;
  1564.     tp->fbase = type->basetype->fbase;
  1565.     tp->issigned = 1;
  1566.     ex3->args[0]->val.type = makepointertype(tp);
  1567.     return makeexpr_cond(makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
  1568.  ex3, ex);
  1569. }
  1570. Static Expr *func_filepos()
  1571. {
  1572.     return file_iofunc(2, seek_base);
  1573. }
  1574. Static Expr *func_filesize()
  1575. {
  1576.     return file_iofunc(3, 1L);
  1577. }
  1578. Static Stmt *proc_fillchar()
  1579. {
  1580.     Expr *vex, *ex, *cex;
  1581.     if (!skipopenparen())
  1582. return NULL;
  1583.     vex = gentle_cast(makeexpr_addr(p_expr(NULL)), tp_anyptr);
  1584.     if (!skipcomma())
  1585. return NULL;
  1586.     ex = convert_size(argbasetype(vex), p_expr(tp_integer), "FILLCHAR");
  1587.     if (!skipcomma())
  1588. return NULL;
  1589.     cex = makeexpr_charcast(p_expr(tp_integer));
  1590.     skipcloseparen();
  1591.     return makestmt_call(makeexpr_bicall_3("memset", tp_void,
  1592.                                            vex,
  1593.                                            makeexpr_arglong(cex, 0),
  1594.                                            makeexpr_arglong(ex, (size_t_long != 0))));
  1595. }
  1596. Static Expr *func_sngl()
  1597. {
  1598.     Expr *ex;
  1599.     ex = p_parexpr(tp_real);
  1600.     return makeexpr_cast(ex, tp_real);
  1601. }
  1602. Static Expr *func_float()
  1603. {
  1604.     Expr *ex;
  1605.     ex = p_parexpr(tp_longreal);
  1606.     return makeexpr_cast(ex, tp_longreal);
  1607. }
  1608. Static Stmt *proc_flush()
  1609. {
  1610.     Expr *ex;
  1611.     Stmt *sp;
  1612.     ex = p_parexpr(tp_text);
  1613.     sp = makestmt_call(makeexpr_bicall_1("fflush", tp_void, ex));
  1614.     if (iocheck_flag)
  1615.         sp = makestmt_seq(sp, makestmt_assign(makeexpr_var(mp_ioresult), 
  1616.                                               makeexpr_long(0)));
  1617.     return sp;
  1618. }
  1619. Static Expr *func_frac(ex)
  1620. Expr *ex;
  1621. {
  1622.     Meaning *tvar;
  1623.     tvar = makestmttempvar(tp_longreal, name_DUMMY);
  1624.     return makeexpr_bicall_2("modf", tp_longreal, 
  1625.                              grabarg(ex, 0),
  1626.                              makeexpr_addr(makeexpr_var(tvar)));
  1627. }
  1628. Static Stmt *proc_freemem(ex)
  1629. Expr *ex;
  1630. {
  1631.     Stmt *sp;
  1632.     Expr *vex;
  1633.     vex = makeexpr_hat(eatcasts(ex->args[0]), 0);
  1634.     sp = makestmt_call(makeexpr_bicall_1(choose_free_func(vex),
  1635.  tp_void, copyexpr(vex)));
  1636.     if (alloczeronil) {
  1637.         sp = makestmt_if(makeexpr_rel(EK_NE, vex, makeexpr_nil()),
  1638.                          sp, NULL);
  1639.     } else
  1640.         freeexpr(vex);
  1641.     return sp;
  1642. }
  1643. Static Stmt *proc_get()
  1644. {
  1645.     Expr *ex;
  1646.     Type *type;
  1647.     if (curtok == TOK_LPAR)
  1648. ex = p_parexpr(tp_text);
  1649.     else
  1650. ex = makeexpr_var(mp_input);
  1651.     requirefilebuffer(ex);
  1652.     type = ex->val.type;
  1653.     if (isfiletype(type) && *chargetname &&
  1654. type->basetype->basetype->kind == TK_CHAR)
  1655. return makestmt_call(makeexpr_bicall_1(chargetname, tp_void, ex));
  1656.     else if (isfiletype(type) && *arraygetname &&
  1657.      type->basetype->basetype->kind == TK_ARRAY)
  1658. return makestmt_call(makeexpr_bicall_2(arraygetname, tp_void, ex,
  1659.        makeexpr_type(type->basetype->basetype)));
  1660.     else