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

编译器/解释器

开发平台:

C/C++

  1. return makestmt_call(makeexpr_bicall_2(getname, tp_void, ex,
  2.        makeexpr_type(type->basetype->basetype)));
  3. }
  4. Static Stmt *proc_getmem(ex)
  5. Expr *ex;
  6. {
  7.     Expr *vex, *ex2, *sz = NULL;
  8.     Stmt *sp;
  9.     vex = makeexpr_hat(eatcasts(ex->args[0]), 0);
  10.     ex2 = ex->args[1];
  11.     if (vex->val.type->kind == TK_POINTER)
  12.         ex2 = convert_size(vex->val.type->basetype, ex2, "GETMEM");
  13.     if (alloczeronil)
  14.         sz = copyexpr(ex2);
  15.     ex2 = makeexpr_bicall_1(mallocname, tp_anyptr, ex2);
  16.     sp = makestmt_assign(copyexpr(vex), ex2);
  17.     if (malloccheck) {
  18.         sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ, copyexpr(vex), makeexpr_nil()),
  19.                                           makestmt_call(makeexpr_bicall_0(name_OUTMEM, tp_int)),
  20.                                           NULL));
  21.     }
  22.     if (sz && !isconstantexpr(sz)) {
  23.         if (alloczeronil == 2)
  24.             note("Called GETMEM with variable argument [189]");
  25.         sp = makestmt_if(makeexpr_rel(EK_NE, sz, makeexpr_long(0)),
  26.                          sp,
  27.                          makestmt_assign(vex, makeexpr_nil()));
  28.     } else
  29.         freeexpr(vex);
  30.     return sp;
  31. }
  32. Static Stmt *proc_gotoxy(ex)
  33. Expr *ex;
  34. {
  35.     return makestmt_call(makeexpr_bicall_2("gotoxy", tp_void,
  36.                                            makeexpr_arglong(ex->args[0], 0),
  37.                                            makeexpr_arglong(ex->args[1], 0)));
  38. }
  39. Static Expr *handle_vax_hex(ex, fmt, scale)
  40. Expr *ex;
  41. char *fmt;
  42. int scale;
  43. {
  44.     Expr *lex, *dex, *vex;
  45.     Meaning *tvar;
  46.     Type *tp;
  47.     long smin, smax;
  48.     int bits;
  49.     if (!ex) {
  50. if (!skipopenparen())
  51.     return NULL;
  52. ex = p_expr(tp_integer);
  53.     }
  54.     tp = true_type(ex);
  55.     if (ord_range(tp, &smin, &smax))
  56. bits = typebits(smin, smax);
  57.     else
  58. bits = 32;
  59.     if (curtok == TOK_COMMA) {
  60. gettok();
  61. if (curtok != TOK_COMMA)
  62.     lex = makeexpr_arglong(p_expr(tp_integer), 0);
  63. else
  64.     lex = NULL;
  65.     } else
  66. lex = NULL;
  67.     if (!lex) {
  68. if (!scale)
  69.     lex = makeexpr_long(11);
  70. else
  71.     lex = makeexpr_long((bits+scale-1) / scale + 1);
  72.     }
  73.     if (curtok == TOK_COMMA) {
  74. gettok();
  75. dex = makeexpr_arglong(p_expr(tp_integer), 0);
  76.     } else {
  77. if (!scale)
  78.     dex = makeexpr_long(10);
  79. else
  80.     dex = makeexpr_long((bits+scale-1) / scale);
  81.     }
  82.     if (lex->kind == EK_CONST && dex->kind == EK_CONST &&
  83. lex->val.i < dex->val.i)
  84. lex = NULL;
  85.     skipcloseparen();
  86.     tvar = makestmttempvar(tp_str255, name_STRING);
  87.     vex = makeexpr_var(tvar);
  88.     ex = makeexpr_forcelongness(ex);
  89.     if (exprlongness(ex) > 0)
  90. fmt = format_s("l%s", fmt);
  91.     if (checkconst(lex, 0) || checkconst(lex, 1))
  92. lex = NULL;
  93.     if (checkconst(dex, 0) || checkconst(dex, 1))
  94. dex = NULL;
  95.     if (lex) {
  96. if (dex)
  97.     ex = makeexpr_bicall_5("sprintf", tp_str255, vex,
  98.    makeexpr_string(format_s("%%*.*%s", fmt)),
  99.    lex, dex, ex);
  100. else
  101.     ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
  102.    makeexpr_string(format_s("%%*%s", fmt)),
  103.    lex, ex);
  104.     } else {
  105. if (dex)
  106.     ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
  107.    makeexpr_string(format_s("%%.*%s", fmt)),
  108.    dex, ex);
  109. else
  110.     ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
  111.    makeexpr_string(format_s("%%%s", fmt)),
  112.    ex);
  113.     }
  114.     return ex;
  115. }
  116. Static Expr *func_hex()
  117. {
  118.     Expr *ex;
  119.     char *cp;
  120.     if (!skipopenparen())
  121. return NULL;
  122.     ex = makeexpr_stringcast(p_expr(tp_integer));
  123.     if ((ex->val.type->kind == TK_STRING ||
  124.  ex->val.type == tp_strptr) &&
  125. curtok != TOK_COMMA) {
  126. skipcloseparen();
  127. if (ex->kind == EK_CONST) {    /* HP Pascal */
  128.     cp = getstring(ex);
  129.     ex = makeexpr_long(my_strtol(cp, NULL, 16));
  130.     insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer));
  131.     return ex;
  132. } else {
  133.     return makeexpr_bicall_3("strtol", tp_integer, 
  134.      ex, makeexpr_nil(), makeexpr_long(16));
  135. }
  136.     } else {    /* VAX Pascal */
  137. return handle_vax_hex(ex, "x", 4);
  138.     }
  139. }
  140. Static Expr *func_hi()
  141. {
  142.     Expr *ex;
  143.     ex = force_unsigned(p_parexpr(tp_integer));
  144.     return makeexpr_bin(EK_RSH, tp_ubyte,
  145.                         ex, makeexpr_long(8));
  146. }
  147. Static Expr *func_high()
  148. {
  149.     Expr *ex;
  150.     Type *type;
  151.     ex = p_parexpr(tp_integer);
  152.     type = ex->val.type;
  153.     if (type->kind == TK_POINTER)
  154. type = type->basetype;
  155.     if (type->kind == TK_ARRAY ||
  156. type->kind == TK_SMALLARRAY) {
  157. ex = makeexpr_minus(copyexpr(type->indextype->smax),
  158.     copyexpr(type->indextype->smin));
  159.     } else {
  160. warning("HIGH requires an array name parameter [210]");
  161. ex = makeexpr_bicall_1("HIGH", tp_int, ex);
  162.     }
  163.     return ex;
  164. }
  165. Static Expr *func_hiword()
  166. {
  167.     Expr *ex;
  168.     ex = force_unsigned(p_parexpr(tp_unsigned));
  169.     return makeexpr_bin(EK_RSH, tp_unsigned,
  170.                         ex, makeexpr_long(16));
  171. }
  172. Static Stmt *proc_inc()
  173. {
  174.     Expr *vex, *ex;
  175.     if (!skipopenparen())
  176. return NULL;
  177.     vex = p_expr(NULL);
  178.     if (curtok == TOK_COMMA) {
  179.         gettok();
  180.         ex = p_expr(tp_integer);
  181.     } else
  182.         ex = makeexpr_long(1);
  183.     skipcloseparen();
  184.     return makestmt_assign(vex, makeexpr_plus(copyexpr(vex), ex));
  185. }
  186. Static Stmt *proc_incl()
  187. {
  188.     Expr *vex, *ex;
  189.     if (!skipopenparen())
  190. return NULL;
  191.     vex = p_expr(NULL);
  192.     if (!skipcomma())
  193. return NULL;
  194.     ex = p_expr(vex->val.type->indextype);
  195.     skipcloseparen();
  196.     if (vex->val.type->kind == TK_SMALLSET)
  197. return makestmt_assign(vex, makeexpr_bin(EK_BOR, vex->val.type,
  198.  copyexpr(vex),
  199.  makeexpr_bin(EK_LSH, vex->val.type,
  200.       makeexpr_longcast(makeexpr_long(1), 1),
  201.       ex)));
  202.     else
  203. return makestmt_call(makeexpr_bicall_2(setaddname, tp_void, vex,
  204.        makeexpr_arglong(enum_to_int(ex), 0)));
  205. }
  206. Static Stmt *proc_insert(ex)
  207. Expr *ex;
  208. {
  209.     return makestmt_call(makeexpr_bicall_3(strinsertname, tp_void,
  210.                                            ex->args[0], 
  211.                                            ex->args[1],
  212.                                            makeexpr_arglong(ex->args[2], 0)));
  213. }
  214. Static Expr *func_int()
  215. {
  216.     Expr *ex;
  217.     Meaning *tvar;
  218.     ex = p_parexpr(tp_integer);
  219.     if (ex->val.type->kind == TK_REAL) {    /* Turbo Pascal INT */
  220. tvar = makestmttempvar(tp_longreal, name_TEMP);
  221. return makeexpr_comma(makeexpr_bicall_2("modf", tp_longreal,
  222. grabarg(ex, 0),
  223. makeexpr_addr(makeexpr_var(tvar))),
  224.       makeexpr_var(tvar));
  225.     } else {     /* VAX Pascal INT */
  226. return makeexpr_ord(ex);
  227.     }
  228. }
  229. Static Expr *func_uint()
  230. {
  231.     Expr *ex;
  232.     ex = p_parexpr(tp_integer);
  233.     return makeexpr_cast(ex, tp_unsigned);
  234. }
  235. Static Stmt *proc_leave()
  236. {
  237.     return makestmt(SK_BREAK);
  238. }
  239. Static Expr *func_lo()
  240. {
  241.     Expr *ex;
  242.     ex = gentle_cast(p_parexpr(tp_integer), tp_ushort);
  243.     return makeexpr_bin(EK_BAND, tp_ubyte,
  244.                         ex, makeexpr_long(255));
  245. }
  246. Static Expr *func_loophole()
  247. {
  248.     Type *type;
  249.     Expr *ex;
  250.     if (!skipopenparen())
  251. return NULL;
  252.     type = p_type(NULL);
  253.     if (!skipcomma())
  254. return NULL;
  255.     ex = p_expr(tp_integer);
  256.     skipcloseparen();
  257.     return pascaltypecast(type, ex);
  258. }
  259. Static Expr *func_lower()
  260. {
  261.     Expr *ex;
  262.     Value val;
  263.     if (!skipopenparen())
  264. return NULL;
  265.     ex = p_expr(tp_integer);
  266.     if (curtok == TOK_COMMA) {
  267. gettok();
  268. val = p_constant(tp_integer);
  269. if (!val.type || val.i != 1)
  270.     note("LOWER(v,n) not supported for n>1 [190]");
  271.     }
  272.     skipcloseparen();
  273.     return copyexpr(ex->val.type->indextype->smin);
  274. }
  275. Static Expr *func_loword()
  276. {
  277.     Expr *ex;
  278.     ex = p_parexpr(tp_integer);
  279.     return makeexpr_bin(EK_BAND, tp_ushort,
  280.                         ex, makeexpr_long(65535));
  281. }
  282. Static Expr *func_ln(ex)
  283. Expr *ex;
  284. {
  285.     return makeexpr_bicall_1("log", tp_longreal, grabarg(ex, 0));
  286. }
  287. Static Expr *func_log(ex)
  288. Expr *ex;
  289. {
  290.     return makeexpr_bicall_1("log10", tp_longreal, grabarg(ex, 0));
  291. }
  292. Static Expr *func_max()
  293. {
  294.     Type *tp;
  295.     Expr *ex, *ex2;
  296.     if (!skipopenparen())
  297. return NULL;
  298.     if (curtok == TOK_IDENT && curtokmeaning &&
  299. curtokmeaning->kind == MK_TYPE) {
  300. tp = curtokmeaning->type;
  301. gettok();
  302. skipcloseparen();
  303. return copyexpr(tp->smax);
  304.     }
  305.     ex = p_expr(tp_integer);
  306.     while (curtok == TOK_COMMA) {
  307. gettok();
  308. ex2 = p_expr(ex->val.type);
  309. if (ex->val.type->kind == TK_REAL) {
  310.     tp = ex->val.type;
  311.     if (ex2->val.type->kind != TK_REAL)
  312. ex2 = makeexpr_cast(ex2, tp);
  313. } else {
  314.     tp = ex2->val.type;
  315.     if (ex->val.type->kind != TK_REAL)
  316. ex = makeexpr_cast(ex, tp);
  317. }
  318. ex = makeexpr_bicall_2((tp->kind == TK_REAL) ? "P_rmax" : "P_imax",
  319.        tp, ex, ex2);
  320.     }
  321.     skipcloseparen();
  322.     return ex;
  323. }
  324. Static Expr *func_maxavail(ex)
  325. Expr *ex;
  326. {
  327.     freeexpr(ex);
  328.     return makeexpr_bicall_0("maxavail", tp_integer);
  329. }
  330. Static Expr *func_maxpos()
  331. {
  332.     return file_iofunc(3, seek_base);
  333. }
  334. Static Expr *func_memavail(ex)
  335. Expr *ex;
  336. {
  337.     freeexpr(ex);
  338.     return makeexpr_bicall_0("memavail", tp_integer);
  339. }
  340. Static Expr *var_mem()
  341. {
  342.     Expr *ex, *ex2;
  343.     if (!wneedtok(TOK_LBR))
  344. return makeexpr_name("MEM", tp_integer);
  345.     ex = p_expr(tp_integer);
  346.     if (curtok == TOK_COLON) {
  347. gettok();
  348. ex2 = p_expr(tp_integer);
  349. ex = makeexpr_bicall_2("MEM", tp_ubyte, ex, ex2);
  350.     } else {
  351. ex = makeexpr_bicall_1("MEM", tp_ubyte, ex);
  352.     }
  353.     if (!wneedtok(TOK_RBR))
  354. skippasttotoken(TOK_RBR, TOK_SEMI);
  355.     note("Reference to MEM [191]");
  356.     return ex;
  357. }
  358. Static Expr *var_memw()
  359. {
  360.     Expr *ex, *ex2;
  361.     if (!wneedtok(TOK_LBR))
  362. return makeexpr_name("MEMW", tp_integer);
  363.     ex = p_expr(tp_integer);
  364.     if (curtok == TOK_COLON) {
  365. gettok();
  366. ex2 = p_expr(tp_integer);
  367. ex = makeexpr_bicall_2("MEMW", tp_ushort, ex, ex2);
  368.     } else {
  369. ex = makeexpr_bicall_1("MEMW", tp_ushort, ex);
  370.     }
  371.     if (!wneedtok(TOK_RBR))
  372. skippasttotoken(TOK_RBR, TOK_SEMI);
  373.     note("Reference to MEMW [191]");
  374.     return ex;
  375. }
  376. Static Expr *var_meml()
  377. {
  378.     Expr *ex, *ex2;
  379.     if (!wneedtok(TOK_LBR))
  380. return makeexpr_name("MEML", tp_integer);
  381.     ex = p_expr(tp_integer);
  382.     if (curtok == TOK_COLON) {
  383. gettok();
  384. ex2 = p_expr(tp_integer);
  385. ex = makeexpr_bicall_2("MEML", tp_integer, ex, ex2);
  386.     } else {
  387. ex = makeexpr_bicall_1("MEML", tp_integer, ex);
  388.     }
  389.     if (!wneedtok(TOK_RBR))
  390. skippasttotoken(TOK_RBR, TOK_SEMI);
  391.     note("Reference to MEML [191]");
  392.     return ex;
  393. }
  394. Static Expr *func_min()
  395. {
  396.     Type *tp;
  397.     Expr *ex, *ex2;
  398.     if (!skipopenparen())
  399. return NULL;
  400.     if (curtok == TOK_IDENT && curtokmeaning &&
  401. curtokmeaning->kind == MK_TYPE) {
  402. tp = curtokmeaning->type;
  403. gettok();
  404. skipcloseparen();
  405. return copyexpr(tp->smin);
  406.     }
  407.     ex = p_expr(tp_integer);
  408.     while (curtok == TOK_COMMA) {
  409. gettok();
  410. ex2 = p_expr(ex->val.type);
  411. if (ex->val.type->kind == TK_REAL) {
  412.     tp = ex->val.type;
  413.     if (ex2->val.type->kind != TK_REAL)
  414. ex2 = makeexpr_cast(ex2, tp);
  415. } else {
  416.     tp = ex2->val.type;
  417.     if (ex->val.type->kind != TK_REAL)
  418. ex = makeexpr_cast(ex, tp);
  419. }
  420. ex = makeexpr_bicall_2((tp->kind == TK_REAL) ? "P_rmin" : "P_imin",
  421.        tp, ex, ex2);
  422.     }
  423.     skipcloseparen();
  424.     return ex;
  425. }
  426. Static Stmt *proc_move(ex)
  427. Expr *ex;
  428. {
  429.     ex->args[0] = gentle_cast(ex->args[0], tp_anyptr);    /* source */
  430.     ex->args[1] = gentle_cast(ex->args[1], tp_anyptr);    /* dest */
  431.     ex->args[2] = convert_size(choosetype(argbasetype(ex->args[0]),
  432.                                           argbasetype(ex->args[1])), ex->args[2], "MOVE");
  433.     return makestmt_call(makeexpr_bicall_3("memmove", tp_void,
  434.                                            ex->args[1],
  435.                                            ex->args[0],
  436.                                            makeexpr_arglong(ex->args[2], (size_t_long != 0))));
  437. }
  438. Static Stmt *proc_move_fast()
  439. {
  440.     Expr *ex, *ex2, *ex3, *ex4;
  441.     if (!skipopenparen())
  442. return NULL;
  443.     ex = p_expr(tp_integer);
  444.     if (!skipcomma())
  445. return NULL;
  446.     ex2 = p_expr(tp_integer);
  447.     if (!skipcomma())
  448. return NULL;
  449.     ord_range_expr(ex2->val.type->indextype, &ex4, NULL);
  450.     ex2 = makeexpr_index(ex2, p_expr(tp_integer), copyexpr(ex4));
  451.     if (!skipcomma())
  452. return NULL;
  453.     ex3 = p_expr(tp_integer);
  454.     if (!skipcomma())
  455. return NULL;
  456.     ord_range_expr(ex3->val.type->indextype, &ex4, NULL);
  457.     ex3 = makeexpr_index(ex3, p_expr(tp_integer), copyexpr(ex4));
  458.     skipcloseparen();
  459.     ex = convert_size(choosetype(argbasetype(ex2),
  460.  argbasetype(ex3)), ex, "MOVE_FAST");
  461.     return makestmt_call(makeexpr_bicall_3("memmove", tp_void,
  462.    makeexpr_addr(ex3),
  463.    makeexpr_addr(ex2),
  464.    makeexpr_arglong(ex, (size_t_long != 0))));
  465. }
  466. Static Stmt *proc_new()
  467. {
  468.     Expr *ex, *ex2;
  469.     Stmt *sp, **spp;
  470.     Type *type;
  471.     char *name, *name2 = NULL, vbuf[1000];
  472.     if (!skipopenparen())
  473. return NULL;
  474.     ex = p_expr(tp_anyptr);
  475.     type = ex->val.type;
  476.     if (type->kind == TK_POINTER)
  477. type = type->basetype;
  478.     parse_special_variant(type, vbuf);
  479.     skipcloseparen();
  480.     name = find_special_variant(vbuf, NULL, specialmallocs, 3);
  481.     if (!name) {
  482.         name2 = find_special_variant(vbuf, NULL, specialsizeofs, 3);
  483. if (!name2) {
  484.     name = find_special_variant(vbuf, NULL, specialmallocs, 1);
  485.     name2 = find_special_variant(vbuf, NULL, specialsizeofs, 1);
  486.     if (name || !name2)
  487. name = find_special_variant(vbuf, "SpecialMalloc", specialmallocs, 1);
  488.     else
  489. name2 = find_special_variant(vbuf, "SpecialSizeOf", specialsizeofs, 1);
  490. }
  491.     }
  492.     if (name) {
  493. ex2 = makeexpr_bicall_0(name, ex->val.type);
  494.     } else if (name2) {
  495. ex2 = makeexpr_bicall_1(mallocname, tp_anyptr, pc_expr_str(name2));
  496.     } else {
  497. ex2 = makeexpr_bicall_1(mallocname, tp_anyptr,
  498. makeexpr_sizeof(makeexpr_type(type), 1));
  499.     }
  500.     sp = makestmt_assign(copyexpr(ex), ex2);
  501.     if (malloccheck) {
  502.         sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ,
  503.        copyexpr(ex),
  504.        makeexpr_nil()),
  505.                                           makestmt_call(makeexpr_bicall_0(name_OUTMEM, tp_int)),
  506.                                           NULL));
  507.     }
  508.     spp = &sp->next;
  509.     while (*spp)
  510. spp = &(*spp)->next;
  511.     if (type->kind == TK_RECORD)
  512. initfilevars(type->fbase, &spp, makeexpr_hat(copyexpr(ex), 0));
  513.     else if (isfiletype(type))
  514. sp = makestmt_seq(sp, makestmt_assign(makeexpr_hat(copyexpr(ex), 0),
  515.       makeexpr_nil()));
  516.     freeexpr(ex);
  517.     return sp;
  518. }
  519. Static Expr *func_oct()
  520. {
  521.     return handle_vax_hex(NULL, "o", 3);
  522. }
  523. Static Expr *func_octal(ex)
  524. Expr *ex;
  525. {
  526.     char *cp;
  527.     ex = grabarg(ex, 0);
  528.     if (ex->kind == EK_CONST) {
  529.         cp = getstring(ex);
  530.         ex = makeexpr_long(my_strtol(cp, NULL, 8));
  531.         insertarg(&ex, 0, makeexpr_name("0%lo", tp_integer));
  532.         return ex;
  533.     } else {
  534.         return makeexpr_bicall_3("strtol", tp_integer, 
  535.                                  ex, makeexpr_nil(), makeexpr_long(8));
  536.     }
  537. }
  538. Static Expr *func_odd(ex)
  539. Expr *ex;
  540. {
  541.     ex = makeexpr_unlongcast(grabarg(ex, 0));
  542.     if (*oddname)
  543.         return makeexpr_bicall_1(oddname, tp_boolean, ex);
  544.     else
  545.         return makeexpr_bin(EK_BAND, tp_boolean, ex, makeexpr_long(1));
  546. }
  547. Static Stmt *proc_open()
  548. {
  549.     return handleopen(2);
  550. }
  551. Static Expr *func_ord()
  552. {
  553.     Expr *ex;
  554.     if (wneedtok(TOK_LPAR)) {
  555. ex = p_ord_expr();
  556. skipcloseparen();
  557.     } else
  558. ex = p_ord_expr();
  559.     return makeexpr_ord(ex);
  560. }
  561. Static Expr *func_ord4()
  562. {
  563.     Expr *ex;
  564.     if (wneedtok(TOK_LPAR)) {
  565. ex = p_ord_expr();
  566. skipcloseparen();
  567.     } else
  568. ex = p_ord_expr();
  569.     return makeexpr_longcast(makeexpr_ord(ex), 1);
  570. }
  571. Static Expr *func_pad(ex)
  572. Expr *ex;
  573. {
  574.     if (checkconst(ex->args[1], 0) ||    /* "s" is null string */
  575. checkconst(ex->args[2], ' ')) {
  576.         return makeexpr_bicall_4("sprintf", tp_strptr, ex->args[0],
  577.                                  makeexpr_string("%*s"),
  578.                                  makeexpr_longcast(ex->args[3], 0),
  579.                                  makeexpr_string(""));
  580.     }
  581.     return makeexpr_bicall_4(strpadname, tp_strptr,
  582.      ex->args[0], ex->args[1], ex->args[2],
  583.      makeexpr_arglong(ex->args[3], 0));
  584. }
  585. Static Stmt *proc_page()
  586. {
  587.     Expr *fex, *ex;
  588.     if (curtok == TOK_LPAR) {
  589.         fex = p_parexpr(tp_text);
  590.         ex = makeexpr_bicall_2("fprintf", tp_int,
  591.                                copyexpr(fex),
  592.                                makeexpr_string("f"));
  593.     } else {
  594.         fex = makeexpr_var(mp_output);
  595.         ex = makeexpr_bicall_1("printf", tp_int,
  596.                                makeexpr_string("f"));
  597.     }
  598.     if (FCheck(checkfilewrite)) {
  599.         ex = makeexpr_bicall_2("~SETIO", tp_void,
  600.                                makeexpr_rel(EK_GE, ex, makeexpr_long(0)),
  601.        makeexpr_name(filewriteerrorname, tp_int));
  602.     }
  603.     return wrapopencheck(makestmt_call(ex), fex);
  604. }
  605. Static Expr *func_paramcount(ex)
  606. Expr *ex;
  607. {
  608.     freeexpr(ex);
  609.     return makeexpr_minus(makeexpr_name(name_ARGC, tp_int),
  610.                           makeexpr_long(1));
  611. }
  612. Static Expr *func_paramstr(ex)
  613. Expr *ex;
  614. {
  615.     Expr *ex2;
  616.     ex2 = makeexpr_index(makeexpr_name(name_ARGV,
  617.        makepointertype(tp_strptr)),
  618.  makeexpr_unlongcast(ex->args[1]),
  619.  makeexpr_long(0));
  620.     ex2->val.type = tp_str255;
  621.     return makeexpr_bicall_3("sprintf", tp_strptr,
  622.      ex->args[0],
  623.      makeexpr_string("%s"),
  624.      ex2);
  625. }
  626. Static Expr *func_pi()
  627. {
  628.     return makeexpr_name("M_PI", tp_longreal);
  629. }
  630. Static Expr *var_port()
  631. {
  632.     Expr *ex;
  633.     if (!wneedtok(TOK_LBR))
  634. return makeexpr_name("PORT", tp_integer);
  635.     ex = p_expr(tp_integer);
  636.     if (!wneedtok(TOK_RBR))
  637. skippasttotoken(TOK_RBR, TOK_SEMI);
  638.     note("Reference to PORT [191]");
  639.     return makeexpr_bicall_1("PORT", tp_ubyte, ex);
  640. }
  641. Static Expr *var_portw()
  642. {
  643.     Expr *ex;
  644.     if (!wneedtok(TOK_LBR))
  645. return makeexpr_name("PORTW", tp_integer);
  646.     ex = p_expr(tp_integer);
  647.     if (!wneedtok(TOK_RBR))
  648. skippasttotoken(TOK_RBR, TOK_SEMI);
  649.     note("Reference to PORTW [191]");
  650.     return makeexpr_bicall_1("PORTW", tp_ushort, ex);
  651. }
  652. Static Expr *func_pos(ex)
  653. Expr *ex;
  654. {
  655.     char *cp;
  656.     cp = strposname;
  657.     if (!*cp) {
  658.         note("POS function used [192]");
  659.         cp = "POS";
  660.     } 
  661.     return makeexpr_bicall_3(cp, tp_int,
  662.                              ex->args[1], 
  663.                              ex->args[0],
  664.                              makeexpr_long(1));
  665. }
  666. Static Expr *func_ptr(ex)
  667. Expr *ex;
  668. {
  669.     note("PTR function was used [193]");
  670.     return ex;
  671. }
  672. Static Expr *func_position()
  673. {
  674.     return file_iofunc(2, seek_base);
  675. }
  676. Static Expr *func_pred()
  677. {
  678.     Expr *ex;
  679.     if (wneedtok(TOK_LPAR)) {
  680. ex = p_ord_expr();
  681. skipcloseparen();
  682.     } else
  683. ex = p_ord_expr();
  684. #if 1
  685.     ex = makeexpr_inc(ex, makeexpr_long(-1));
  686. #else
  687.     ex = makeexpr_cast(makeexpr_plus(ex, makeexpr_long(-1)), ex->val.type);
  688. #endif
  689.     return ex;
  690. }
  691. Static Stmt *proc_put()
  692. {
  693.     Expr *ex;
  694.     Type *type;
  695.     if (curtok == TOK_LPAR)
  696. ex = p_parexpr(tp_text);
  697.     else
  698. ex = makeexpr_var(mp_output);
  699.     requirefilebuffer(ex);
  700.     type = ex->val.type;
  701.     if (isfiletype(type) && *charputname &&
  702. type->basetype->basetype->kind == TK_CHAR)
  703. return makestmt_call(makeexpr_bicall_1(charputname, tp_void, ex));
  704.     else if (isfiletype(type) && *arrayputname &&
  705.      type->basetype->basetype->kind == TK_ARRAY)
  706. return makestmt_call(makeexpr_bicall_2(arrayputname, tp_void, ex,
  707.        makeexpr_type(type->basetype->basetype)));
  708.     else
  709. return makestmt_call(makeexpr_bicall_2(putname, tp_void, ex,
  710.        makeexpr_type(type->basetype->basetype)));
  711. }
  712. Static Expr *func_pwroften(ex)
  713. Expr *ex;
  714. {
  715.     return makeexpr_bicall_2("pow", tp_longreal,
  716.      makeexpr_real("10.0"), grabarg(ex, 0));
  717. }
  718. Static Stmt *proc_reset()
  719. {
  720.     return handleopen(0);
  721. }
  722. Static Stmt *proc_rewrite()
  723. {
  724.     return handleopen(1);
  725. }
  726. Stmt *doseek(fex, ex)
  727. Expr *fex, *ex;
  728. {
  729.     Expr *ex2;
  730.     Type *basetype = fex->val.type->basetype->basetype;
  731.     if (ansiC == 1)
  732.         ex2 = makeexpr_name("SEEK_SET", tp_int);
  733.     else
  734.         ex2 = makeexpr_long(0);
  735.     ex = makeexpr_bicall_3("fseek", tp_int, 
  736.                            copyexpr(fex),
  737.                            makeexpr_arglong(
  738.                                makeexpr_times(makeexpr_minus(ex,
  739.                                                              makeexpr_long(seek_base)),
  740.                                               makeexpr_sizeof(makeexpr_type(basetype), 0)),
  741.                                1),
  742.                            ex2);
  743.     if (FCheck(checkfileseek)) {
  744.         ex = makeexpr_bicall_2("~SETIO", tp_void,
  745.                                makeexpr_rel(EK_EQ, ex, makeexpr_long(0)),
  746.        makeexpr_name(endoffilename, tp_int));
  747.     }
  748.     return makestmt_call(ex);
  749. }
  750. Static Expr *makegetchar(fex)
  751. Expr *fex;
  752. {
  753.     if (isvar(fex, mp_input))
  754.         return makeexpr_bicall_0("getchar", tp_char);
  755.     else
  756.         return makeexpr_bicall_1("getc", tp_char, copyexpr(fex));
  757. }
  758. Static Stmt *fixscanf(sp, fex)
  759. Stmt *sp;
  760. Expr *fex;
  761. {
  762.     int nargs, i, isstrread;
  763.     char *cp;
  764.     Expr *ex;
  765.     Stmt *sp2;
  766.     isstrread = (fex->val.type->kind == TK_STRING);
  767.     if (sp->kind == SK_ASSIGN && sp->exp1->kind == EK_BICALL &&
  768.         !strcmp(sp->exp1->val.s, "scanf")) {
  769.         if (sp->exp1->args[0]->kind == EK_CONST &&
  770.             !(sp->exp1->args[0]->val.i&1) && !isstrread) {
  771.             cp = sp->exp1->args[0]->val.s;    /* scanf("%c%c") -> getchar;getchar */
  772.             for (i = 0; cp[i] == '%' && cp[i+1] == 'c'; ) {
  773.                 i += 2;
  774.                 if (i == sp->exp1->args[0]->val.i) {
  775.                     sp2 = NULL;
  776.                     for (i = 1; i < sp->exp1->nargs; i++) {
  777.                         ex = makeexpr_hat(sp->exp1->args[i], 0);
  778.                         sp2 = makestmt_seq(sp2,
  779.                                            makestmt_assign(copyexpr(ex),
  780.                                                            makegetchar(fex)));
  781.                         if (checkeof(fex)) {
  782.                             sp2 = makestmt_seq(sp2,
  783.                                 makestmt_call(makeexpr_bicall_2("~SETIO", tp_void,
  784.                                                                 makeexpr_rel(EK_NE,
  785.                                                                              ex,
  786.                                                                              makeexpr_name("EOF", tp_char)),
  787. makeexpr_name(endoffilename, tp_int))));
  788.                         } else
  789.                             freeexpr(ex);
  790.                     }
  791.                     return sp2;
  792.                 }
  793.             }
  794.         }
  795.         nargs = sp->exp1->nargs - 1;
  796.         if (isstrread) {
  797.             strchange(&sp->exp1->val.s, "sscanf");
  798.             insertarg(&sp->exp1, 0, copyexpr(fex));
  799.         } else if (!isvar(fex, mp_input)) {
  800.             strchange(&sp->exp1->val.s, "fscanf");
  801.             insertarg(&sp->exp1, 0, copyexpr(fex));
  802.         }
  803.         if (FCheck(checkreadformat)) {
  804.             if (checkeof(fex) && !isstrread)
  805.                 ex = makeexpr_cond(makeexpr_rel(EK_NE,
  806.                                                 makeexpr_bicall_1("feof", tp_int, copyexpr(fex)),
  807.                                                 makeexpr_long(0)),
  808.    makeexpr_name(endoffilename, tp_int),
  809.    makeexpr_name(badinputformatname, tp_int));
  810.             else
  811. ex = makeexpr_name(badinputformatname, tp_int);
  812.             sp->exp1 = makeexpr_bicall_2("~SETIO", tp_void,
  813.                                          makeexpr_rel(EK_EQ,
  814.                                                       sp->exp1,
  815.                                                       makeexpr_long(nargs)),
  816.                                          ex);
  817.         } else if (checkeof(fex) && !isstrread) {
  818.             sp->exp1 = makeexpr_bicall_2("~SETIO", tp_void,
  819.                                          makeexpr_rel(EK_NE,
  820.                                                       sp->exp1,
  821.                                                       makeexpr_name("EOF", tp_int)),
  822.  makeexpr_name(endoffilename, tp_int));
  823.         }
  824.     }
  825.     return sp;
  826. }
  827. Static Expr *makefgets(vex, lex, fex)
  828. Expr *vex, *lex, *fex;
  829. {
  830.     Expr *ex;
  831.     ex = makeexpr_bicall_3("fgets", tp_strptr,
  832.                            vex,
  833.                            lex,
  834.                            copyexpr(fex));
  835.     if (checkeof(fex)) {
  836.         ex = makeexpr_bicall_2("~SETIO", tp_void,
  837.                                makeexpr_rel(EK_NE, ex, makeexpr_nil()),
  838.        makeexpr_name(endoffilename, tp_int));
  839.     }
  840.     return ex;
  841. }
  842. Static Stmt *skipeoln(fex)
  843. Expr *fex;
  844. {
  845.     Meaning *tvar;
  846.     Expr *ex;
  847.     if (!strcmp(readlnname, "fgets")) {
  848.         tvar = makestmttempvar(tp_str255, name_STRING);
  849.         return makestmt_call(makefgets(makeexpr_var(tvar),
  850.                                        makeexpr_long(stringceiling+1),
  851.                                        fex));
  852.     } else if (!strcmp(readlnname, "scanf") || !*readlnname) {
  853.         if (checkeof(fex))
  854.             ex = makeexpr_bicall_2("~SETIO", tp_void,
  855.                                    makeexpr_rel(EK_NE,
  856.                                                 makegetchar(fex),
  857.                                                 makeexpr_name("EOF", tp_char)),
  858.    makeexpr_name(endoffilename, tp_int));
  859.         else
  860.             ex = makegetchar(fex);
  861.         return makestmt_seq(fixscanf(
  862.                     makestmt_call(makeexpr_bicall_1("scanf", tp_int,
  863.                                                     makeexpr_string("%*[^n]"))), fex),
  864.                     makestmt_call(ex));
  865.     } else {
  866.         return makestmt_call(makeexpr_bicall_1(readlnname, tp_void,
  867.                                                copyexpr(fex)));
  868.     }
  869. }
  870. Static Stmt *handleread_text(fex, var, isreadln)
  871. Expr *fex, *var;
  872. int isreadln;
  873. {
  874.     Stmt *spbase, *spafter, *sp;
  875.     Expr *ex = NULL, *exj = NULL;
  876.     Type *type;
  877.     Meaning *tvar, *tempcp, *mp;
  878.     int i, isstrread, scanfmode, readlnflag, varstring, maxstring;
  879.     int longstrsize = (longstringsize > 0) ? longstringsize : stringceiling;
  880.     long rmin, rmax;
  881.     char *fmt;
  882.     spbase = NULL;
  883.     spafter = NULL;
  884.     sp = NULL;
  885.     tempcp = NULL;
  886.     isstrread = (fex->val.type->kind == TK_STRING);
  887.     if (isstrread) {
  888.         exj = var;
  889.         var = p_expr(NULL);
  890.     }
  891.     scanfmode = !strcmp(readlnname, "scanf") || !*readlnname || isstrread;
  892.     for (;;) {
  893.         readlnflag = isreadln && curtok == TOK_RPAR;
  894.         if (var->val.type->kind == TK_STRING && !isstrread) {
  895.             if (sp)
  896.                 spbase = makestmt_seq(spbase, fixscanf(sp, fex));
  897.             spbase = makestmt_seq(spbase, spafter);
  898.             varstring = (varstrings && var->kind == EK_VAR &&
  899.                          (mp = (Meaning *)var->val.i)->kind == MK_VARPARAM &&
  900.                          mp->type == tp_strptr);
  901.             maxstring = (strmax(var) >= longstrsize && !varstring);
  902.             if (isvar(fex, mp_input) && maxstring && usegets && readlnflag) {
  903.                 spbase = makestmt_seq(spbase,
  904.                                       makestmt_call(makeexpr_bicall_1("gets", tp_str255,
  905.                                                                       makeexpr_addr(var))));
  906.                 isreadln = 0;
  907.             } else if (scanfmode && !varstring &&
  908.                        (*readlnname || !isreadln)) {
  909.                 spbase = makestmt_seq(spbase, makestmt_assign(makeexpr_hat(copyexpr(var), 0),
  910.                                                               makeexpr_char(0)));
  911.                 if (maxstring && usegets)
  912.                     ex = makeexpr_string("%[^n]");
  913.                 else
  914.                     ex = makeexpr_string(format_d("%%%d[^n]", strmax(var)));
  915.                 ex = makeexpr_bicall_2("scanf", tp_int, ex, makeexpr_addr(var));
  916.                 spbase = makestmt_seq(spbase, fixscanf(makestmt_call(ex), fex));
  917.                 if (readlnflag && maxstring && usegets) {
  918.                     spbase = makestmt_seq(spbase, makestmt_call(makegetchar(fex)));
  919.                     isreadln = 0;
  920.                 }
  921.             } else {
  922.                 ex = makeexpr_plus(strmax_func(var), makeexpr_long(1));
  923.                 spbase = makestmt_seq(spbase,
  924.                                       makestmt_call(makefgets(makeexpr_addr(copyexpr(var)),
  925.                                                               ex,
  926.                                                               fex)));
  927.                 if (!tempcp)
  928.                     tempcp = makestmttempvar(tp_charptr, name_TEMP);
  929.                 spbase = makestmt_seq(spbase,
  930.                                       makestmt_assign(makeexpr_var(tempcp),
  931.                                                       makeexpr_bicall_2("strchr", tp_charptr,
  932.                                                                         makeexpr_addr(copyexpr(var)),
  933.                                                                         makeexpr_char('n'))));
  934.                 sp = makestmt_assign(makeexpr_hat(makeexpr_var(tempcp), 0),
  935.                                      makeexpr_long(0));
  936.                 if (readlnflag)
  937.                     isreadln = 0;
  938.                 else
  939.                     sp = makestmt_seq(sp,
  940.                                       makestmt_call(makeexpr_bicall_2("ungetc", tp_void,
  941.                                                                       makeexpr_char('n'),
  942.                                                                       copyexpr(fex))));
  943.                 spbase = makestmt_seq(spbase, makestmt_if(makeexpr_rel(EK_NE,
  944.                                                                        makeexpr_var(tempcp),
  945.                                                                        makeexpr_nil()),
  946.                                                           sp,
  947.                                                           NULL));
  948.             }
  949.             sp = NULL;
  950.             spafter = NULL;
  951.         } else if (var->val.type->kind == TK_ARRAY && !isstrread) {
  952.             if (sp)
  953.                 spbase = makestmt_seq(spbase, fixscanf(sp, fex));
  954.             spbase = makestmt_seq(spbase, spafter);
  955.     ex = makeexpr_sizeof(copyexpr(var), 0);
  956.     if (readlnflag) {
  957. spbase = makestmt_seq(spbase,
  958.      makestmt_call(
  959.  makeexpr_bicall_3("P_readlnpaoc", tp_void,
  960.    copyexpr(fex),
  961.    makeexpr_addr(var),
  962.    makeexpr_arglong(ex, 0))));
  963. isreadln = 0;
  964.     } else {
  965. spbase = makestmt_seq(spbase,
  966.      makestmt_call(
  967.  makeexpr_bicall_3("P_readpaoc", tp_void,
  968.    copyexpr(fex),
  969.    makeexpr_addr(var),
  970.    makeexpr_arglong(ex, 0))));
  971.     }
  972.             sp = NULL;
  973.             spafter = NULL;
  974.         } else {
  975.             switch (ord_type(var->val.type)->kind) {
  976.                 case TK_INTEGER:
  977.     fmt = "d";
  978.     if (curtok == TOK_COLON) {
  979. gettok();
  980. if (curtok == TOK_IDENT &&
  981.     !strcicmp(curtokbuf, "HEX")) {
  982.     fmt = "x";
  983. } else if (curtok == TOK_IDENT &&
  984.     !strcicmp(curtokbuf, "OCT")) {
  985.     fmt = "o";
  986. } else if (curtok == TOK_IDENT &&
  987.     !strcicmp(curtokbuf, "BIN")) {
  988.     fmt = "b";
  989.     note("Using %b for binary format in scanf [194]");
  990. } else
  991.     warning("Unrecognized format specified in READ [212]");
  992. gettok();
  993.     }
  994.                     type = findbasetype(var->val.type, 0);
  995.                     if (exprlongness(var) > 0)
  996.                         ex = makeexpr_string(format_s("%%l%s", fmt));
  997.                     else if (type == tp_integer || type == tp_int ||
  998.                              type == tp_uint || type == tp_sint)
  999.                         ex = makeexpr_string(format_s("%%%s", fmt));
  1000.                     else if (type == tp_sshort || type == tp_ushort)
  1001.                         ex = makeexpr_string(format_s("%%h%s", fmt));
  1002.                     else {
  1003.                         tvar = makestmttempvar(tp_int, name_TEMP);
  1004.                         spafter = makestmt_seq(spafter,
  1005.                                                makestmt_assign(var,
  1006.                                                                makeexpr_var(tvar)));
  1007.                         var = makeexpr_var(tvar);
  1008.                         ex = makeexpr_string(format_s("%%%s", fmt));
  1009.                     }
  1010.                     break;
  1011.                 case TK_CHAR:
  1012.                     ex = makeexpr_string("%c");
  1013.                     if (newlinespace && !isstrread) {
  1014.                         spafter = makestmt_seq(spafter,
  1015.                                                makestmt_if(makeexpr_rel(EK_EQ,
  1016.                                                                         copyexpr(var),
  1017.                                                                         makeexpr_char('n')),
  1018.                                                            makestmt_assign(copyexpr(var),
  1019.                                                                            makeexpr_char(' ')),
  1020.                                                            NULL));
  1021.                     }
  1022.                     break;
  1023.                 case TK_BOOLEAN:
  1024.                     tvar = makestmttempvar(tp_str255, name_STRING);
  1025.                     spafter = makestmt_seq(spafter,
  1026.                         makestmt_assign(var,
  1027.                                         makeexpr_or(makeexpr_rel(EK_EQ,
  1028.                                                                  makeexpr_hat(makeexpr_var(tvar), 0),
  1029.                                                                  makeexpr_char('T')),
  1030.                                                     makeexpr_rel(EK_EQ,
  1031.                                                                  makeexpr_hat(makeexpr_var(tvar), 0),
  1032.                                                                  makeexpr_char('t')))));
  1033.                     var = makeexpr_var(tvar);
  1034.                     ex = makeexpr_string(" %[a-zA-Z]");
  1035.                     break;
  1036.                 case TK_ENUM:
  1037.                     warning("READ on enumerated types not yet supported [213]");
  1038.                     if (useenum)
  1039.                         ex = makeexpr_string("%d");
  1040.                     else
  1041.                         ex = makeexpr_string("%hd");
  1042.                     break;
  1043.                 case TK_REAL:
  1044.                     ex = makeexpr_string("%lg");
  1045.                     break;
  1046.                 case TK_STRING:     /* strread only */
  1047.                     ex = makeexpr_string(format_d("%%%dc", strmax(fex)));
  1048.                     break;
  1049.                 case TK_ARRAY:      /* strread only */
  1050.                     if (!ord_range(ex->val.type->indextype, &rmin, &rmax)) {
  1051.                         rmin = 1;
  1052.                         rmax = 1;
  1053.                         note("Can't determine length of packed array of chars [195]");
  1054.                     }
  1055.                     ex = makeexpr_string(format_d("%%%ldc", rmax-rmin+1));
  1056.                     break;
  1057.                 default:
  1058.                     note("Element has wrong type for WRITE statement [196]");
  1059.                     ex = NULL;
  1060.                     break;
  1061.             }
  1062.             if (ex) {
  1063.                 var = makeexpr_addr(var);
  1064.                 if (sp) {
  1065.                     sp->exp1->args[0] = makeexpr_concat(sp->exp1->args[0], ex, 0);
  1066.                     insertarg(&sp->exp1, sp->exp1->nargs, var);
  1067.                 } else {
  1068.                     sp = makestmt_call(makeexpr_bicall_2("scanf", tp_int, ex, var));
  1069.                 }
  1070.             }
  1071.         }
  1072.         if (curtok == TOK_COMMA) {
  1073.             gettok();
  1074.             var = p_expr(NULL);
  1075.         } else
  1076.             break;
  1077.     }
  1078.     if (sp) {
  1079.         if (isstrread && !FCheck(checkreadformat) &&
  1080.             ((i=0, checkstring(sp->exp1->args[0], "%d")) ||
  1081.              (i++, checkstring(sp->exp1->args[0], "%ld")) ||
  1082.              (i++, checkstring(sp->exp1->args[0], "%hd")) ||
  1083.              (i++, checkstring(sp->exp1->args[0], "%lg")))) {
  1084.             if (fullstrread != 0 && exj) {
  1085.                 tvar = makestmttempvar(tp_strptr, name_STRING);
  1086.                 sp->exp1 = makeexpr_assign(makeexpr_hat(sp->exp1->args[1], 0),
  1087.                                            (i == 3) ? makeexpr_bicall_2("strtod", tp_longreal,
  1088.                                                                         copyexpr(fex),
  1089.                                                                         makeexpr_addr(makeexpr_var(tvar)))
  1090.                                                     : makeexpr_bicall_3("strtol", tp_integer,
  1091.                                                                         copyexpr(fex),
  1092.                                                                         makeexpr_addr(makeexpr_var(tvar)),
  1093.                                                                         makeexpr_long(10)));
  1094. spafter = makestmt_seq(spafter,
  1095.        makestmt_assign(copyexpr(exj),
  1096.        makeexpr_minus(makeexpr_var(tvar),
  1097.       makeexpr_addr(copyexpr(fex)))));
  1098.             } else {
  1099.                 sp->exp1 = makeexpr_assign(makeexpr_hat(sp->exp1->args[1], 0),
  1100.                                            makeexpr_bicall_1((i == 1) ? "atol" : (i == 3) ? "atof" : "atoi",
  1101.                                                              (i == 1) ? tp_integer : (i == 3) ? tp_longreal : tp_int,
  1102.                                                              copyexpr(fex)));
  1103.             }
  1104.         } else if (isstrread && fullstrread != 0 && exj) {
  1105.             sp->exp1->args[0] = makeexpr_concat(sp->exp1->args[0],
  1106.                                                 makeexpr_string(sizeof_int >= 32 ? "%n" : "%ln"), 0);
  1107.             insertarg(&sp->exp1, sp->exp1->nargs, makeexpr_addr(copyexpr(exj)));
  1108.         } else if (isreadln && scanfmode && !FCheck(checkreadformat)) {
  1109.             isreadln = 0;
  1110.             sp->exp1->args[0] = makeexpr_concat(sp->exp1->args[0],
  1111.                                                 makeexpr_string("%*[^n]"), 0);
  1112.             spafter = makestmt_seq(makestmt_call(makegetchar(fex)), spafter);
  1113.         }
  1114.         spbase = makestmt_seq(spbase, fixscanf(sp, fex));
  1115.     }
  1116.     spbase = makestmt_seq(spbase, spafter);
  1117.     if (isreadln)
  1118.         spbase = makestmt_seq(spbase, skipeoln(fex));
  1119.     return spbase;
  1120. }
  1121. Static Stmt *handleread_bin(fex, var)
  1122. Expr *fex, *var;
  1123. {
  1124.     Type *basetype;
  1125.     Stmt *sp;
  1126.     Expr *ex, *tvardef = NULL;
  1127.     sp = NULL;
  1128.     basetype = fex->val.type->basetype->basetype;
  1129.     for (;;) {
  1130.         ex = makeexpr_bicall_4("fread", tp_integer, makeexpr_addr(var),
  1131.                                                     makeexpr_sizeof(makeexpr_type(basetype), 0),
  1132.                                                     makeexpr_long(1),
  1133.                                                     copyexpr(fex));
  1134.         if (checkeof(fex)) {
  1135.             ex = makeexpr_bicall_2("~SETIO", tp_void,
  1136.                                    makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
  1137.    makeexpr_name(endoffilename, tp_int));
  1138.         }
  1139.         sp = makestmt_seq(sp, makestmt_call(ex));
  1140.         if (curtok == TOK_COMMA) {
  1141.             gettok();
  1142.             var = p_expr(NULL);
  1143.         } else
  1144.             break;
  1145.     }
  1146.     freeexpr(tvardef);
  1147.     return sp;
  1148. }
  1149. Static Stmt *proc_read()
  1150. {
  1151.     Expr *fex, *ex;
  1152.     Stmt *sp;
  1153.     if (!skipopenparen())
  1154. return NULL;
  1155.     ex = p_expr(NULL);
  1156.     if (isfiletype(ex->val.type) && wneedtok(TOK_COMMA)) {
  1157.         fex = ex;
  1158.         ex = p_expr(NULL);
  1159.     } else {
  1160.         fex = makeexpr_var(mp_input);
  1161.     }
  1162.     if (fex->val.type == tp_text)
  1163.         sp = handleread_text(fex, ex, 0);
  1164.     else
  1165.         sp = handleread_bin(fex, ex);
  1166.     skipcloseparen();
  1167.     return wrapopencheck(sp, fex);
  1168. }
  1169. Static Stmt *proc_readdir()
  1170. {
  1171.     Expr *fex, *ex;
  1172.     Stmt *sp;
  1173.     if (!skipopenparen())
  1174. return NULL;
  1175.     fex = p_expr(tp_text);
  1176.     if (!skipcomma())
  1177. return NULL;
  1178.     ex = p_expr(tp_integer);
  1179.     sp = doseek(fex, ex);
  1180.     if (!skipopenparen())
  1181. return sp;
  1182.     sp = makestmt_seq(sp, handleread_bin(fex, p_expr(NULL)));
  1183.     skipcloseparen();
  1184.     return wrapopencheck(sp, fex);
  1185. }
  1186. Static Stmt *proc_readln()
  1187. {
  1188.     Expr *fex, *ex;
  1189.     Stmt *sp;
  1190.     if (curtok != TOK_LPAR) {
  1191.         fex = makeexpr_var(mp_input);
  1192.         return wrapopencheck(skipeoln(copyexpr(fex)), fex);
  1193.     } else {
  1194.         gettok();
  1195.         ex = p_expr(NULL);
  1196.         if (isfiletype(ex->val.type)) {
  1197.             fex = ex;
  1198.             if (curtok == TOK_RPAR || !wneedtok(TOK_COMMA)) {
  1199.                 skippasttotoken(TOK_RPAR, TOK_SEMI);
  1200.                 return wrapopencheck(skipeoln(copyexpr(fex)), fex);
  1201.             } else {
  1202.                 ex = p_expr(NULL);
  1203.             }
  1204.         } else {
  1205.             fex = makeexpr_var(mp_input);
  1206.         }
  1207.         sp = handleread_text(fex, ex, 1);
  1208.         skipcloseparen();
  1209.     }
  1210.     return wrapopencheck(sp, fex);
  1211. }
  1212. Static Stmt *proc_readv()
  1213. {
  1214.     Expr *vex;
  1215.     Stmt *sp;
  1216.     if (!skipopenparen())
  1217. return NULL;
  1218.     vex = p_expr(tp_str255);
  1219.     if (!skipcomma())
  1220. return NULL;
  1221.     sp = handleread_text(vex, NULL, 0);
  1222.     skipcloseparen();
  1223.     return sp;
  1224. }
  1225. Static Stmt *proc_strread()
  1226. {
  1227.     Expr *vex, *exi, *exj, *exjj, *ex;
  1228.     Stmt *sp, *sp2;
  1229.     Meaning *tvar, *jvar;
  1230.     if (!skipopenparen())
  1231. return NULL;
  1232.     vex = p_expr(tp_str255);
  1233.     if (vex->kind != EK_VAR) {
  1234.         tvar = makestmttempvar(tp_str255, name_STRING);
  1235.         sp = makestmt_assign(makeexpr_var(tvar), vex);
  1236.         vex = makeexpr_var(tvar);
  1237.     } else
  1238.         sp = NULL;
  1239.     if (!skipcomma())
  1240. return NULL;
  1241.     exi = p_expr(tp_integer);
  1242.     if (!skipcomma())
  1243. return NULL;
  1244.     exj = p_expr(tp_integer);
  1245.     if (!skipcomma())
  1246. return NULL;
  1247.     if (exprspeed(exi) >= 5 || !nosideeffects(exi, 0)) {
  1248.         sp = makestmt_seq(sp, makestmt_assign(copyexpr(exj), exi));
  1249.         exi = copyexpr(exj);
  1250.     }
  1251.     if (fullstrread != 0 &&
  1252.         ((ex = singlevar(exj)) == NULL || exproccurs(exi, ex))) {
  1253.         jvar = makestmttempvar(exj->val.type, name_TEMP);
  1254.         exjj = makeexpr_var(jvar);
  1255.     } else {
  1256.         exjj = copyexpr(exj);
  1257.         jvar = (exj->kind == EK_VAR) ? (Meaning *)exj->val.i : NULL;
  1258.     }
  1259.     sp2 = handleread_text(bumpstring(copyexpr(vex),
  1260.                                      copyexpr(exi), 1),
  1261.                           exjj, 0);
  1262.     sp = makestmt_seq(sp, sp2);
  1263.     skipcloseparen();
  1264.     if (fullstrread == 0) {
  1265.         sp = makestmt_seq(sp, makestmt_assign(exj,
  1266.                                               makeexpr_plus(makeexpr_bicall_1("strlen", tp_int,
  1267.                                                                               vex),
  1268.                                                             makeexpr_long(1))));
  1269.         freeexpr(exjj);
  1270.         freeexpr(exi);
  1271.     } else {
  1272.         sp = makestmt_seq(sp, makestmt_assign(exj,
  1273.                                               makeexpr_plus(exjj, exi)));
  1274.         if (fullstrread == 2)
  1275.             note("STRREAD was used [197]");
  1276.         freeexpr(vex);
  1277.     }
  1278.     return mixassignments(sp, jvar);
  1279. }
  1280. Static Expr *func_random()
  1281. {
  1282.     Expr *ex;
  1283.     if (curtok == TOK_LPAR) {
  1284.         gettok();
  1285.         ex = p_expr(tp_integer);
  1286.         skipcloseparen();
  1287.         return makeexpr_bicall_1(randintname, tp_integer, makeexpr_arglong(ex, 1));
  1288.     } else {
  1289.         return makeexpr_bicall_0(randrealname, tp_longreal);
  1290.     }
  1291. }
  1292. Static Stmt *proc_randomize()
  1293. {
  1294.     if (*randomizename)
  1295.         return makestmt_call(makeexpr_bicall_0(randomizename, tp_void));
  1296.     else
  1297.         return NULL;
  1298. }
  1299. Static Expr *func_round(ex)
  1300. Expr *ex;
  1301. {
  1302.     Meaning *tvar;
  1303.     ex = grabarg(ex, 0);
  1304.     if (ex->val.type->kind != TK_REAL)
  1305. return ex;
  1306.     if (*roundname) {
  1307.         if (*roundname != '*' || (exprspeed(ex) < 5 && nosideeffects(ex, 0))) {
  1308.             return makeexpr_bicall_1(roundname, tp_integer, ex);
  1309.         } else {
  1310.             tvar = makestmttempvar(tp_longreal, name_TEMP);
  1311.             return makeexpr_comma(makeexpr_assign(makeexpr_var(tvar), ex),
  1312.                                   makeexpr_bicall_1(roundname, tp_integer, makeexpr_var(tvar)));
  1313.         }
  1314.     } else {
  1315.         return makeexpr_actcast(makeexpr_bicall_1("floor", tp_longreal,
  1316.   makeexpr_plus(ex, makeexpr_real("0.5"))),
  1317.                                 tp_integer);
  1318.     }
  1319. }
  1320. Static Expr *func_uround(ex)
  1321. Expr *ex;
  1322. {
  1323.     ex = grabarg(ex, 0);
  1324.     if (ex->val.type->kind != TK_REAL)
  1325. return ex;
  1326.     return makeexpr_actcast(makeexpr_bicall_1("floor", tp_longreal,
  1327.       makeexpr_plus(ex, makeexpr_real("0.5"))),
  1328.     tp_unsigned);
  1329. }
  1330. Static Expr *func_scan()
  1331. {
  1332.     Expr *ex, *ex2, *ex3;
  1333.     char *name;
  1334.     if (!skipopenparen())
  1335. return NULL;
  1336.     ex = p_expr(tp_integer);
  1337.     if (!skipcomma())
  1338. return NULL;
  1339.     if (curtok == TOK_EQ)
  1340. name = "P_scaneq";
  1341.     else 
  1342. name = "P_scanne";
  1343.     gettok();
  1344.     ex2 = p_expr(tp_char);
  1345.     if (!skipcomma())
  1346. return NULL;
  1347.     ex3 = p_expr(tp_str255);
  1348.     skipcloseparen();
  1349.     return makeexpr_bicall_3(name, tp_int,
  1350.      makeexpr_arglong(ex, 0),
  1351.      makeexpr_charcast(ex2), ex3);
  1352. }
  1353. Static Expr *func_scaneq(ex)
  1354. Expr *ex;
  1355. {
  1356.     return makeexpr_bicall_3("P_scaneq", tp_int,
  1357.      makeexpr_arglong(ex->args[0], 0),
  1358.      makeexpr_charcast(ex->args[1]),
  1359.      ex->args[2]);
  1360. }
  1361. Static Expr *func_scanne(ex)
  1362. Expr *ex;
  1363. {
  1364.     return makeexpr_bicall_3("P_scanne", tp_int,
  1365.      makeexpr_arglong(ex->args[0], 0),
  1366.      makeexpr_charcast(ex->args[1]),
  1367.      ex->args[2]);
  1368. }
  1369. Static Stmt *proc_seek()
  1370. {
  1371.     Expr *fex, *ex;
  1372.     Stmt *sp;
  1373.     if (!skipopenparen())
  1374. return NULL;
  1375.     fex = p_expr(tp_text);
  1376.     if (!skipcomma())
  1377. return NULL;
  1378.     ex = p_expr(tp_integer);
  1379.     skipcloseparen();
  1380.     sp = wrapopencheck(doseek(fex, ex), copyexpr(fex));
  1381.     if (*setupbufname && isfilevar(fex))
  1382. sp = makestmt_seq(sp,
  1383.  makestmt_call(
  1384.      makeexpr_bicall_2(setupbufname, tp_void, fex,
  1385.  makeexpr_type(fex->val.type->basetype->basetype))));
  1386.     else
  1387. freeexpr(fex);
  1388.     return sp;
  1389. }
  1390. Static Expr *func_seekeof()
  1391. {
  1392.     Expr *ex;
  1393.     if (curtok == TOK_LPAR)
  1394.         ex = p_parexpr(tp_text);
  1395.     else
  1396.         ex = makeexpr_var(mp_input);
  1397.     if (*skipspacename)
  1398.         ex = makeexpr_bicall_1(skipspacename, tp_text, ex);
  1399.     else
  1400.         note("SEEKEOF was used [198]");
  1401.     return iofunc(ex, 0);
  1402. }
  1403. Static Expr *func_seekeoln()
  1404. {
  1405.     Expr *ex;
  1406.     if (curtok == TOK_LPAR)
  1407.         ex = p_parexpr(tp_text);
  1408.     else
  1409.         ex = makeexpr_var(mp_input);
  1410.     if (*skipspacename)
  1411.         ex = makeexpr_bicall_1(skipspacename, tp_text, ex);
  1412.     else
  1413.         note("SEEKEOLN was used [199]");
  1414.     return iofunc(ex, 1);
  1415. }
  1416. Static Stmt *proc_setstrlen()
  1417. {
  1418.     Expr *ex, *ex2;
  1419.     if (!skipopenparen())
  1420. return NULL;
  1421.     ex = p_expr(tp_str255);
  1422.     if (!skipcomma())
  1423. return NULL;
  1424.     ex2 = p_expr(tp_integer);
  1425.     skipcloseparen();
  1426.     return makestmt_assign(makeexpr_bicall_1("strlen", tp_int, ex),
  1427.                            ex2);
  1428. }
  1429. Static Stmt *proc_settextbuf()
  1430. {
  1431.     Expr *fex, *bex, *sex;
  1432.     if (!skipopenparen())
  1433. return NULL;
  1434.     fex = p_expr(tp_text);
  1435.     if (!skipcomma())
  1436. return NULL;
  1437.     bex = p_expr(NULL);
  1438.     if (curtok == TOK_COMMA) {
  1439.         gettok();
  1440.         sex = p_expr(tp_integer);
  1441.     } else
  1442.         sex = makeexpr_sizeof(copyexpr(bex), 0);
  1443.     skipcloseparen();
  1444.     note("Make sure setvbuf() call occurs when file is open [200]");
  1445.     return makestmt_call(makeexpr_bicall_4("setvbuf", tp_void,
  1446.                                            fex,
  1447.                                            makeexpr_addr(bex),
  1448.                                            makeexpr_name("_IOFBF", tp_integer),
  1449.                                            sex));
  1450. }
  1451. Static Expr *func_sin(ex)
  1452. Expr *ex;
  1453. {
  1454.     return makeexpr_bicall_1("sin", tp_longreal, grabarg(ex, 0));
  1455. }
  1456. Static Expr *func_sinh(ex)
  1457. Expr *ex;
  1458. {
  1459.     return makeexpr_bicall_1("sinh", tp_longreal, grabarg(ex, 0));
  1460. }
  1461. Static Expr *func_sizeof()
  1462. {
  1463.     Expr *ex;
  1464.     Type *type;
  1465.     char *name, vbuf[1000];
  1466.     int lpar;
  1467.     lpar = (curtok == TOK_LPAR);
  1468.     if (lpar)
  1469. gettok();
  1470.     if (curtok == TOK_IDENT && curtokmeaning && curtokmeaning->kind == MK_TYPE) {
  1471.         ex = makeexpr_type(curtokmeaning->type);
  1472.         gettok();
  1473.     } else
  1474.         ex = p_expr(NULL);
  1475.     type = ex->val.type;
  1476.     parse_special_variant(type, vbuf);
  1477.     if (lpar)
  1478. skipcloseparen();
  1479.     name = find_special_variant(vbuf, "SpecialSizeOf", specialsizeofs, 1);
  1480.     if (name) {
  1481. freeexpr(ex);
  1482. return pc_expr_str(name);
  1483.     } else
  1484. return makeexpr_sizeof(ex, 0);
  1485. }
  1486. Static Expr *func_statusv()
  1487. {
  1488.     return makeexpr_name(name_IORESULT, tp_integer);
  1489. }
  1490. Static Expr *func_str_hp(ex)
  1491. Expr *ex;
  1492. {
  1493.     return makeexpr_addr(makeexpr_substring(ex->args[0], ex->args[1], 
  1494.                                             ex->args[2], ex->args[3]));
  1495. }
  1496. Static Stmt *proc_strappend()
  1497. {
  1498.     Expr *ex, *ex2;
  1499.     if (!skipopenparen())
  1500. return NULL;
  1501.     ex = p_expr(tp_str255);
  1502.     if (!skipcomma())
  1503. return NULL;