blob: 5ec410d78ab84cc8335115948190537c929e0d3e [file] [log] [blame]
/* "p2c", a Pascal to C translator.
Copyright (C) 1989, 1990, 1991 Free Software Foundation.
Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation (any version).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define PROTO_FUNCS_C
#include "trans.h"
Static Strlist *enumnames;
Static int enumnamecount;
void setup_funcs()
{
enumnames = NULL;
enumnamecount = 0;
}
int isvar(ex, mp)
Expr *ex;
Meaning *mp;
{
return (ex->kind == EK_VAR && (Meaning *)ex->val.i == mp);
}
char *getstring(ex)
Expr *ex;
{
ex = makeexpr_stringify(ex);
if (ex->kind != EK_CONST || ex->val.type->kind != TK_STRING) {
intwarning("getstring", "Not a string literal [206]");
return "";
}
return ex->val.s;
}
Expr *p_parexpr(target)
Type *target;
{
Expr *ex;
if (wneedtok(TOK_LPAR)) {
ex = p_expr(target);
if (!wneedtok(TOK_RPAR))
skippasttotoken(TOK_RPAR, TOK_SEMI);
} else
ex = p_expr(target);
return ex;
}
Type *argbasetype(ex)
Expr *ex;
{
if (ex->kind == EK_CAST)
ex = ex->args[0];
if (ex->val.type->kind == TK_POINTER)
return ex->val.type->basetype;
else
return ex->val.type;
}
Type *choosetype(t1, t2)
Type *t1, *t2;
{
if (t1 == tp_void ||
(type_sizeof(t2, 1) && !type_sizeof(t1, 1)))
return t2;
else
return t1;
}
Expr *convert_offset(type, ex2)
Type *type;
Expr *ex2;
{
long size;
int i;
Value val;
Expr *ex3;
if (type->kind == TK_POINTER ||
type->kind == TK_ARRAY ||
type->kind == TK_SET ||
type->kind == TK_STRING)
type = type->basetype;
size = type_sizeof(type, 1);
if (size == 1)
return ex2;
val = eval_expr_pasc(ex2);
if (val.type) {
if (val.i == 0)
return ex2;
if (size && val.i % size == 0) {
freeexpr(ex2);
return makeexpr_long(val.i / size);
}
} else { /* look for terms like "n*sizeof(foo)" */
while (ex2->kind == EK_CAST || ex2->kind == EK_ACTCAST)
ex2 = ex2->args[0];
if (ex2->kind == EK_TIMES) {
for (i = 0; i < ex2->nargs; i++) {
ex3 = convert_offset(type, ex2->args[i]);
if (ex3) {
ex2->args[i] = ex3;
return resimplify(ex2);
}
}
for (i = 0;
i < ex2->nargs && ex2->args[i]->kind != EK_SIZEOF;
i++) ;
if (i < ex2->nargs) {
if (ex2->args[i]->args[0]->val.type == type) {
delfreearg(&ex2, i);
if (ex2->nargs == 1)
return ex2->args[0];
else
return ex2;
}
}
} else if (ex2->kind == EK_PLUS) {
ex3 = copyexpr(ex2);
for (i = 0; i < ex2->nargs; i++) {
ex3->args[i] = convert_offset(type, ex3->args[i]);
if (!ex3->args[i]) {
freeexpr(ex3);
return NULL;
}
}
freeexpr(ex2);
return resimplify(ex3);
} else if (ex2->kind == EK_SIZEOF) {
if (ex2->args[0]->val.type == type) {
freeexpr(ex2);
return makeexpr_long(1);
}
} else if (ex2->kind == EK_NEG) {
ex3 = convert_offset(type, ex2->args[0]);
if (ex3)
return makeexpr_neg(ex3);
}
}
return NULL;
}
Expr *convert_size(type, ex, name)
Type *type;
Expr *ex;
char *name;
{
long size;
Expr *ex2;
int i, okay;
Value val;
if (debug>2) { fprintf(outf,"convert_size("); dumpexpr(ex); fprintf(outf,")\n"); }
while (type->kind == TK_ARRAY || type->kind == TK_STRING)
type = type->basetype;
if (type == tp_void)
return ex;
size = type_sizeof(type, 1);
if (size == 1)
return ex;
while (ex->kind == EK_CAST || ex->kind == EK_ACTCAST)
ex = ex->args[0];
switch (ex->kind) {
case EK_TIMES:
for (i = 0; i < ex->nargs; i++) {
ex2 = convert_size(type, ex->args[i], NULL);
if (ex2) {
ex->args[i] = ex2;
return resimplify(ex);
}
}
break;
case EK_PLUS:
okay = 1;
for (i = 0; i < ex->nargs; i++) {
ex2 = convert_size(type, ex->args[i], NULL);
if (ex2)
ex->args[i] = ex2;
else
okay = 0;
}
ex = distribute_plus(ex);
if ((ex->kind != EK_TIMES || !okay) && name)
note(format_s("Suspicious mixture of sizes in %s [173]", name));
return ex;
case EK_SIZEOF:
return ex;
default:
break;
}
val = eval_expr_pasc(ex);
if (val.type) {
if (val.i == 0)
return ex;
if (size && val.i % size == 0) {
freeexpr(ex);
return makeexpr_times(makeexpr_long(val.i / size),
makeexpr_sizeof(makeexpr_type(type), 0));
}
}
if (name) {
note(format_s("Can't interpret size in %s [174]", name));
return ex;
} else
return NULL;
}
Static Expr *func_abs()
{
Expr *ex;
Meaning *tvar;
int lness;
ex = p_parexpr(tp_integer);
if (ex->val.type->kind == TK_REAL)
return makeexpr_bicall_1("fabs", tp_longreal, ex);
else {
lness = exprlongness(ex);
if (lness < 0)
return makeexpr_bicall_1("abs", tp_int, ex);
else if (lness > 0 && *absname) {
if (ansiC > 0) {
return makeexpr_bicall_1("labs", tp_integer, ex);
} else if (*absname == '*' && (exprspeed(ex) >= 5 || !nosideeffects(ex, 0))) {
tvar = makestmttempvar(tp_integer, name_TEMP);
return makeexpr_comma(makeexpr_assign(makeexpr_var(tvar),
ex),
makeexpr_bicall_1(absname, tp_integer,
makeexpr_var(tvar)));
} else {
return makeexpr_bicall_1(absname, tp_integer, ex);
}
} else if (exprspeed(ex) < 5 && nosideeffects(ex, 0)) {
return makeexpr_cond(makeexpr_rel(EK_LT, copyexpr(ex),
makeexpr_long(0)),
makeexpr_neg(copyexpr(ex)),
ex);
} else {
tvar = makestmttempvar(tp_integer, name_TEMP);
return makeexpr_cond(makeexpr_rel(EK_LT, makeexpr_assign(makeexpr_var(tvar),
ex),
makeexpr_long(0)),
makeexpr_neg(makeexpr_var(tvar)),
makeexpr_var(tvar));
}
}
}
Static Expr *func_addr()
{
Expr *ex, *ex2, *ex3;
Type *type, *tp2;
int haspar;
haspar = wneedtok(TOK_LPAR);
ex = p_expr(tp_proc);
if (curtok == TOK_COMMA) {
gettok();
ex2 = p_expr(tp_integer);
ex3 = convert_offset(ex->val.type, ex2);
if (checkconst(ex3, 0)) {
ex = makeexpr_addrf(ex);
} else {
ex = makeexpr_addrf(ex);
if (ex3) {
ex = makeexpr_plus(ex, ex3);
} else {
note("Don't know how to reduce offset for ADDR [175]");
type = makepointertype(tp_abyte);
tp2 = ex->val.type;
ex = makeexpr_cast(makeexpr_plus(makeexpr_cast(ex, type), ex2), tp2);
}
}
} else {
if ((ex->val.type->kind != TK_PROCPTR &&
ex->val.type->kind != TK_CPROCPTR) ||
(ex->kind == EK_VAR &&
ex->val.type == ((Meaning *)ex->val.i)->type))
ex = makeexpr_addrf(ex);
}
if (haspar) {
if (!wneedtok(TOK_RPAR))
skippasttotoken(TOK_RPAR, TOK_SEMI);
}
return ex;
}
Static Expr *func_iaddress()
{
return makeexpr_cast(func_addr(), tp_integer);
}
Static Expr *func_addtopointer()
{
Expr *ex, *ex2, *ex3;
Type *type, *tp2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_anyptr);
if (skipcomma()) {
ex2 = p_expr(tp_integer);
} else
ex2 = makeexpr_long(0);
skipcloseparen();
ex3 = convert_offset(ex->val.type, ex2);
if (!checkconst(ex3, 0)) {
if (ex3) {
ex = makeexpr_plus(ex, ex3);
} else {
note("Don't know how to reduce offset for ADDTOPOINTER [175]");
type = makepointertype(tp_abyte);
tp2 = ex->val.type;
ex = makeexpr_cast(makeexpr_plus(makeexpr_cast(ex, type), ex2), tp2);
}
}
return ex;
}
Stmt *proc_assert()
{
Expr *ex;
ex = p_parexpr(tp_boolean);
return makestmt_call(makeexpr_bicall_1("assert", tp_void, ex));
}
Stmt *wrapopencheck(sp, fex)
Stmt *sp;
Expr *fex;
{
Stmt *sp2;
if (FCheck(checkfileisopen) && !is_std_file(fex)) {
sp2 = makestmt(SK_IF);
sp2->exp1 = makeexpr_rel(EK_NE, filebasename(fex), makeexpr_nil());
sp2->stm1 = sp;
if (iocheck_flag) {
sp2->stm2 = makestmt_call(makeexpr_bicall_1(name_ESCIO, tp_integer,
makeexpr_name(filenotopenname, tp_int)));
} else {
sp2->stm2 = makestmt_assign(makeexpr_var(mp_ioresult),
makeexpr_name(filenotopenname, tp_int));
}
return sp2;
} else {
freeexpr(fex);
return sp;
}
}
Static Expr *checkfilename(nex)
Expr *nex;
{
Expr *ex;
nex = makeexpr_stringcast(nex);
if (nex->kind == EK_CONST && nex->val.type->kind == TK_STRING) {
switch (which_lang) {
case LANG_HP:
if (!strncmp(nex->val.s, "#1:", 3) ||
!strncmp(nex->val.s, "console:", 8) ||
!strncmp(nex->val.s, "CONSOLE:", 8)) {
freeexpr(nex);
nex = makeexpr_string("/dev/tty");
} else if (!strncmp(nex->val.s, "#2:", 3) ||
!strncmp(nex->val.s, "systerm:", 8) ||
!strncmp(nex->val.s, "SYSTERM:", 8)) {
freeexpr(nex);
nex = makeexpr_string("/dev/tty"); /* should do more? */
} else if (!strncmp(nex->val.s, "#6:", 3) ||
!strncmp(nex->val.s, "printer:", 8) ||
!strncmp(nex->val.s, "PRINTER:", 8)) {
note("Opening a file named PRINTER: [176]");
} else if (my_strchr(nex->val.s, ':')) {
note("Opening a file whose name contains a ':' [177]");
}
break;
case LANG_TURBO:
if (checkstring(nex, "con") ||
checkstring(nex, "CON") ||
checkstring(nex, "")) {
freeexpr(nex);
nex = makeexpr_string("/dev/tty");
} else if (checkstring(nex, "nul") ||
checkstring(nex, "NUL")) {
freeexpr(nex);
nex = makeexpr_string("/dev/null");
} else if (checkstring(nex, "lpt1") ||
checkstring(nex, "LPT1") ||
checkstring(nex, "lpt2") ||
checkstring(nex, "LPT2") ||
checkstring(nex, "lpt3") ||
checkstring(nex, "LPT3") ||
checkstring(nex, "com1") ||
checkstring(nex, "COM1") ||
checkstring(nex, "com2") ||
checkstring(nex, "COM2")) {
note("Opening a DOS device file name [178]");
}
break;
default:
break;
}
} else {
if (*filenamefilter && strcmp(filenamefilter, "0")) {
ex = makeexpr_sizeof(copyexpr(nex), 0);
nex = makeexpr_bicall_2(filenamefilter, tp_str255, nex, ex);
} else
nex = makeexpr_stringify(nex);
}
return nex;
}
Static Stmt *assignfilename(fex, nex)
Expr *fex, *nex;
{
Meaning *mp;
Expr *nvex;
nvex = filenamepart(fex);
if (nvex) {
freeexpr(fex);
return makestmt_call(makeexpr_assign(nvex, nex));
} else {
mp = isfilevar(fex);
if (mp)
warning("Don't know how to ASSIGN to a non-explicit file variable [207]");
else
note("Encountered an ASSIGN statement [179]");
return makestmt_call(makeexpr_bicall_2("assign", tp_void, fex, nex));
}
}
Static Stmt *proc_assign()
{
Expr *fex, *nex;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
nex = checkfilename(p_expr(tp_str255));
skipcloseparen();
return assignfilename(fex, nex);
}
Static Stmt *handleopen(code)
int code;
{
Stmt *sp, *sp1, *sp2, *spassign;
Expr *fex, *nex, *ex, *truenex, *nvex;
Meaning *fmp;
int needcheckopen = 1;
char modebuf[5], *cp;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
fmp = isfilevar(fex);
nvex = filenamepart(fex);
truenex = NULL;
spassign = NULL;
if (curtok == TOK_COMMA) {
gettok();
ex = p_expr(tp_str255);
} else
ex = NULL;
if (ex && (ex->val.type->kind == TK_STRING ||
ex->val.type->kind == TK_ARRAY)) {
nex = checkfilename(ex);
if (nvex) {
spassign = assignfilename(copyexpr(fex), nex);
nex = nvex;
}
truenex = nex;
if (curtok == TOK_COMMA) {
gettok();
ex = p_expr(tp_str255);
} else
ex = NULL;
} else if (nvex) {
nex = nvex;
} else {
switch (code) {
case 0:
if (ex)
note("Can't interpret name argument in RESET [180]");
break;
case 1:
note("REWRITE does not specify a name [181]");
break;
case 2:
note("OPEN does not specify a name [181]");
break;
case 3:
note("APPEND does not specify a name [181]");
break;
}
nex = NULL;
}
if (ex) {
if (ord_type(ex->val.type)->kind == TK_INTEGER) {
if (!checkconst(ex, 1))
note("Ignoring block size in binary file [182]");
freeexpr(ex);
} else {
if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING) {
cp = getstring(ex);
if (strcicmp(cp, "SHARED"))
note(format_s("Ignoring option string \"%s\" in open [183]", cp));
} else
note("Ignoring option string in open [183]");
}
}
switch (code) {
case 0: /* reset */
strcpy(modebuf, "r");
break;
case 1: /* rewrite */
strcpy(modebuf, "w");
break;
case 2: /* open */
strcpy(modebuf, openmode);
break;
case 3: /* append */
strcpy(modebuf, "a");
break;
}
if (!*modebuf) {
strcpy(modebuf, "r+");
}
if (readwriteopen == 2 ||
(readwriteopen &&
fex->val.type != tp_text &&
fex->val.type != tp_bigtext)) {
if (!my_strchr(modebuf, '+'))
strcat(modebuf, "+");
}
if (fex->val.type != tp_text &&
fex->val.type != tp_bigtext &&
binarymode != 0) {
if (binarymode == 1)
strcat(modebuf, "b");
else
note("Opening a binary file [184]");
}
if (!nex && fmp &&
!is_std_file(fex) &&
literalfilesflag > 0 &&
(literalfilesflag == 1 ||
strlist_cifind(literalfiles, fmp->name))) {
nex = makeexpr_string(fmp->name);
}
sp1 = NULL;
sp2 = NULL;
if (!nex || (isfiletype(fex->val.type, 1) && !truenex)) {
if (isvar(fex, mp_output)) {
note("RESET/REWRITE ignored for file OUTPUT [319]");
} else {
sp1 = makestmt_call(makeexpr_bicall_1("rewind", tp_void,
filebasename(copyexpr(fex))));
if (code == 0 || is_std_file(fex)) {
sp1 = wrapopencheck(sp1, copyexpr(fex));
needcheckopen = 0;
} else
sp1 = makestmt_if(makeexpr_rel(EK_NE,
filebasename(copyexpr(fex)),
makeexpr_nil()),
sp1,
makestmt_assign(filebasename(copyexpr(fex)),
makeexpr_bicall_0("tmpfile",
tp_text)));
}
}
if (nex || isfiletype(fex->val.type, 1)) {
needcheckopen = 1;
if (!strcmp(freopenname, "fclose") ||
!strcmp(freopenname, "fopen")) {
sp2 = makestmt_assign(filebasename(copyexpr(fex)),
makeexpr_bicall_2("fopen", tp_text,
copyexpr(nex),
makeexpr_string(modebuf)));
if (!strcmp(freopenname, "fclose")) {
sp2 = makestmt_seq(makestmt_if(makeexpr_rel(EK_NE,
filebasename(copyexpr(fex)),
makeexpr_nil()),
makestmt_call(makeexpr_bicall_1("fclose", tp_void,
filebasename(copyexpr(fex)))),
NULL),
sp2);
}
} else {
sp2 = makestmt_assign(filebasename(copyexpr(fex)),
makeexpr_bicall_3((*freopenname) ? freopenname : "freopen",
tp_text,
copyexpr(nex),
makeexpr_string(modebuf),
filebasename(copyexpr(fex))));
if (!*freopenname) {
sp2 = makestmt_if(makeexpr_rel(EK_NE, filebasename(copyexpr(fex)),
makeexpr_nil()),
sp2,
makestmt_assign(filebasename(copyexpr(fex)),
makeexpr_bicall_2("fopen", tp_text,
copyexpr(nex),
makeexpr_string(modebuf))));
}
}
}
if (!sp1)
sp = sp2;
else if (!sp2)
sp = sp1;
else {
sp = makestmt_if(makeexpr_rel(EK_NE, copyexpr(nex),
makeexpr_string("")),
sp2, sp1);
}
if (code == 2 && !*openmode && nex) {
sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ,
filebasename(copyexpr(fex)),
makeexpr_nil()),
makestmt_assign(filebasename(copyexpr(fex)),
makeexpr_bicall_2("fopen", tp_text,
copyexpr(nex),
makeexpr_string("w+"))),
NULL));
}
if (nex)
freeexpr(nex);
if (FCheck(checkfileopen) && needcheckopen) {
sp = makestmt_seq(sp, makestmt_call(makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_NE, filebasename(copyexpr(fex)), makeexpr_nil()),
makeexpr_name(filenotfoundname, tp_int))));
}
sp = makestmt_seq(spassign, sp);
cp = (code == 0) ? resetbufname : setupbufname;
if (*cp && /* (may be eaten later, if buffering isn't needed) */
fileisbuffered(fex, 1))
sp = makestmt_seq(sp,
makestmt_call(
makeexpr_bicall_2(cp, tp_void, filebasename(fex),
makeexpr_type(filebasetype(fex->val.type)))));
else
freeexpr(fex);
skipcloseparen();
return sp;
}
Static Stmt *proc_append()
{
return handleopen(3);
}
Static Expr *func_arccos(ex)
Expr *ex;
{
return makeexpr_bicall_1("acos", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_arcsin(ex)
Expr *ex;
{
return makeexpr_bicall_1("asin", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_arctan(ex)
Expr *ex;
{
ex = grabarg(ex, 0);
if (atan2flag && ex->kind == EK_DIVIDE)
return makeexpr_bicall_2("atan2", tp_longreal,
ex->args[0], ex->args[1]);
return makeexpr_bicall_1("atan", tp_longreal, ex);
}
Static Expr *func_arctanh(ex)
Expr *ex;
{
return makeexpr_bicall_1("atanh", tp_longreal, grabarg(ex, 0));
}
Static Stmt *proc_argv()
{
Expr *ex, *aex, *lex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (skipcomma()) {
aex = p_expr(tp_str255);
} else
return NULL;
skipcloseparen();
lex = makeexpr_sizeof(copyexpr(aex), 0);
aex = makeexpr_addrstr(aex);
return makestmt_call(makeexpr_bicall_3("P_sun_argv", tp_void,
aex, lex, makeexpr_arglong(ex, 0)));
}
Static Expr *func_asr()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (skipcomma()) {
if (signedshift == 0 || signedshift == 2) {
ex = makeexpr_bicall_2("P_asr", ex->val.type, ex,
p_expr(tp_unsigned));
} else {
ex = force_signed(ex);
ex = makeexpr_bin(EK_RSH, ex->val.type, ex, p_expr(tp_unsigned));
if (signedshift != 1)
note("Assuming >> is an arithmetic shift [320]");
}
skipcloseparen();
}
return ex;
}
Static Expr *func_lsl()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (skipcomma()) {
ex = makeexpr_bin(EK_LSH, ex->val.type, ex, p_expr(tp_unsigned));
skipcloseparen();
}
return ex;
}
Static Expr *func_lsr()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (skipcomma()) {
ex = force_unsigned(ex);
ex = makeexpr_bin(EK_RSH, ex->val.type, ex, p_expr(tp_unsigned));
skipcloseparen();
}
return ex;
}
Static Expr *func_bin()
{
note("Using %b for binary printf format [185]");
return handle_vax_hex(NULL, "b", 1);
}
Static Expr *func_binary(ex)
Expr *ex;
{
char *cp;
ex = grabarg(ex, 0);
if (ex->kind == EK_CONST) {
cp = getstring(ex);
ex = makeexpr_long(my_strtol(cp, NULL, 2));
insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer));
return ex;
} else {
return makeexpr_bicall_3("strtol", tp_integer,
ex, makeexpr_nil(), makeexpr_long(2));
}
}
Static Expr *handle_bitsize(next)
int next;
{
Expr *ex;
Type *type;
int lpar;
long psize;
lpar = (curtok == TOK_LPAR);
if (lpar)
gettok();
if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE) {
ex = makeexpr_type(curtokmeaning->type);
gettok();
} else
ex = p_expr(NULL);
type = ex->val.type;
if (lpar)
skipcloseparen();
psize = 0;
packedsize(NULL, &type, &psize, 0);
if (psize > 0 && psize < 32 && next) {
if (psize > 16)
psize = 32;
else if (psize > 8)
psize = 16;
else if (psize > 4)
psize = 8;
else if (psize > 2)
psize = 4;
else if (psize > 1)
psize = 2;
else
psize = 1;
}
if (psize)
return makeexpr_long(psize);
else
return makeexpr_times(makeexpr_sizeof(ex, 0),
makeexpr_long(sizeof_char ? sizeof_char : 8));
}
Static Expr *func_bitsize()
{
return handle_bitsize(0);
}
Static Expr *func_bitnext()
{
return handle_bitsize(1);
}
Static Expr *func_blockread()
{
Expr *ex, *ex2, *vex, *sex, *fex;
Type *type;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
sex = p_expr(tp_integer);
sex = doseek(copyexpr(fex),
makeexpr_times(sex, makeexpr_long(512)))->exp1;
} else
sex = NULL;
skipcloseparen();
type = vex->val.type;
ex = makeexpr_bicall_4("fread", tp_integer,
makeexpr_addr(vex),
makeexpr_long(512),
convert_size(type, ex2, "BLOCKREAD"),
filebasename(copyexpr(fex)));
return makeexpr_comma(sex, ex);
}
Static Expr *func_blockwrite()
{
Expr *ex, *ex2, *vex, *sex, *fex;
Type *type;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
sex = p_expr(tp_integer);
sex = doseek(copyexpr(fex),
makeexpr_times(sex, makeexpr_long(512)))->exp1;
} else
sex = NULL;
skipcloseparen();
type = vex->val.type;
ex = makeexpr_bicall_4("fwrite", tp_integer,
makeexpr_addr(vex),
makeexpr_long(512),
convert_size(type, ex2, "BLOCKWRITE"),
filebasename(copyexpr(fex)));
return makeexpr_comma(sex, ex);
}
Static Stmt *proc_blockread()
{
Expr *ex, *ex2, *vex, *rex, *fex;
Type *type;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
rex = p_expr(tp_integer);
} else
rex = NULL;
skipcloseparen();
type = vex->val.type;
if (rex) {
ex = makeexpr_bicall_4("fread", tp_integer,
makeexpr_addr(vex),
makeexpr_long(1),
convert_size(type, ex2, "BLOCKREAD"),
filebasename(copyexpr(fex)));
ex = makeexpr_assign(rex, ex);
if (!iocheck_flag)
ex = makeexpr_comma(ex,
makeexpr_assign(makeexpr_var(mp_ioresult),
makeexpr_long(0)));
} else {
ex = makeexpr_bicall_4("fread", tp_integer,
makeexpr_addr(vex),
convert_size(type, ex2, "BLOCKREAD"),
makeexpr_long(1),
filebasename(copyexpr(fex)));
if (checkeof(fex)) {
ex = makeexpr_bicall_2(name_SETIO, tp_void,
makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
makeexpr_name(endoffilename, tp_int));
}
}
return wrapopencheck(makestmt_call(ex), fex);
}
Static Stmt *proc_blockwrite()
{
Expr *ex, *ex2, *vex, *rex, *fex;
Type *type;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
rex = p_expr(tp_integer);
} else
rex = NULL;
skipcloseparen();
type = vex->val.type;
if (rex) {
ex = makeexpr_bicall_4("fwrite", tp_integer,
makeexpr_addr(vex),
makeexpr_long(1),
convert_size(type, ex2, "BLOCKWRITE"),
filebasename(copyexpr(fex)));
ex = makeexpr_assign(rex, ex);
if (!iocheck_flag)
ex = makeexpr_comma(ex,
makeexpr_assign(makeexpr_var(mp_ioresult),
makeexpr_long(0)));
} else {
ex = makeexpr_bicall_4("fwrite", tp_integer,
makeexpr_addr(vex),
convert_size(type, ex2, "BLOCKWRITE"),
makeexpr_long(1),
filebasename(copyexpr(fex)));
if (FCheck(checkfilewrite)) {
ex = makeexpr_bicall_2(name_SETIO, tp_void,
makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
makeexpr_name(filewriteerrorname, tp_int));
}
}
return wrapopencheck(makestmt_call(ex), fex);
}
Static Stmt *proc_bclr()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
skipcloseparen();
return makestmt_assign(ex,
makeexpr_bin(EK_BAND, ex->val.type,
copyexpr(ex),
makeexpr_un(EK_BNOT, ex->val.type,
makeexpr_bin(EK_LSH, tp_integer,
makeexpr_arglong(
makeexpr_long(1), 1),
ex2))));
}
Static Stmt *proc_bset()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
skipcloseparen();
return makestmt_assign(ex,
makeexpr_bin(EK_BOR, ex->val.type,
copyexpr(ex),
makeexpr_bin(EK_LSH, tp_integer,
makeexpr_arglong(
makeexpr_long(1), 1),
ex2)));
}
Static Expr *func_bsl()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
skipcloseparen();
return makeexpr_bin(EK_LSH, tp_integer, ex, ex2);
}
Static Expr *func_bsr()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
skipcloseparen();
return makeexpr_bin(EK_RSH, tp_integer, force_unsigned(ex), ex2);
}
Static Expr *func_btst()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
skipcloseparen();
return makeexpr_rel(EK_NE,
makeexpr_bin(EK_BAND, tp_integer,
ex,
makeexpr_bin(EK_LSH, tp_integer,
makeexpr_arglong(
makeexpr_long(1), 1),
ex2)),
makeexpr_long(0));
}
Static Expr *func_byteread()
{
Expr *ex, *ex2, *vex, *sex, *fex;
Type *type;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
sex = p_expr(tp_integer);
sex = doseek(copyexpr(fex), sex)->exp1;
} else
sex = NULL;
skipcloseparen();
type = vex->val.type;
ex = makeexpr_bicall_4("fread", tp_integer,
makeexpr_addr(vex),
makeexpr_long(1),
convert_size(type, ex2, "BYTEREAD"),
filebasename(copyexpr(fex)));
return makeexpr_comma(sex, ex);
}
Static Expr *func_bytewrite()
{
Expr *ex, *ex2, *vex, *sex, *fex;
Type *type;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
sex = p_expr(tp_integer);
sex = doseek(copyexpr(fex), sex)->exp1;
} else
sex = NULL;
skipcloseparen();
type = vex->val.type;
ex = makeexpr_bicall_4("fwrite", tp_integer,
makeexpr_addr(vex),
makeexpr_long(1),
convert_size(type, ex2, "BYTEWRITE"),
filebasename(copyexpr(fex)));
return makeexpr_comma(sex, ex);
}
Static Expr *func_byte_offset()
{
Type *tp;
Meaning *mp;
Expr *ex;
if (!skipopenparen())
return NULL;
tp = p_type(NULL);
if (!skipcomma())
return NULL;
if (!wexpecttok(TOK_IDENT))
return NULL;
mp = curtoksym->fbase;
while (mp && mp->rectype != tp)
mp = mp->snext;
if (!mp)
ex = makeexpr_name(curtokcase, tp_integer);
else
ex = makeexpr_name(mp->name, tp_integer);
gettok();
skipcloseparen();
return makeexpr_bicall_2("OFFSETOF", (size_t_long) ? tp_integer : tp_int,
makeexpr_type(tp), ex);
}
Static Stmt *proc_call()
{
Expr *ex, *ex2, *ex3;
Type *type, *tp;
Meaning *mp;
if (!skipopenparen())
return NULL;
ex2 = p_expr(tp_proc);
type = ex2->val.type;
if (type->kind != TK_PROCPTR && type->kind != TK_CPROCPTR) {
warning("CALL requires a procedure variable [208]");
type = tp_proc;
}
ex = makeexpr(EK_SPCALL, 1);
ex->val.type = tp_void;
ex->args[0] = copyexpr(ex2);
if (type->escale != 0)
ex->args[0] = makeexpr_cast(makeexpr_dotq(ex2, "proc", tp_anyptr),
makepointertype(type->basetype));
mp = type->basetype->fbase;
if (mp) {
if (wneedtok(TOK_COMMA))
ex = p_funcarglist(ex, mp, 0, 0);
}
skipcloseparen();
if (type->escale != 1 || hasstaticlinks == 2) {
freeexpr(ex2);
return makestmt_call(ex);
}
ex2 = makeexpr_dotq(ex2, "link", tp_anyptr),
ex3 = copyexpr(ex);
insertarg(&ex3, ex3->nargs, copyexpr(ex2));
tp = maketype(TK_FUNCTION);
tp->basetype = type->basetype->basetype;
tp->fbase = type->basetype->fbase;
tp->issigned = 1;
ex3->args[0]->val.type = makepointertype(tp);
return makestmt_if(makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
makestmt_call(ex3),
makestmt_call(ex));
}
Static Expr *func_chr()
{
Expr *ex;
ex = p_expr(tp_integer);
if ((exprlongness(ex) < 0 || ex->kind == EK_CAST) && ex->kind != EK_ACTCAST)
ex->val.type = tp_char;
else
ex = makeexpr_cast(ex, tp_char);
return ex;
}
Static Stmt *proc_close()
{
Stmt *sp;
Expr *fex, *ex;
char *opt;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
sp = makestmt_if(makeexpr_rel(EK_NE, filebasename(copyexpr(fex)),
makeexpr_nil()),
makestmt_call(makeexpr_bicall_1("fclose", tp_void,
filebasename(copyexpr(fex)))),
(FCheck(checkfileisopen))
? makestmt_call(
makeexpr_bicall_1(name_ESCIO,
tp_integer,
makeexpr_name(filenotopenname,
tp_int)))
: NULL);
if (curtok == TOK_COMMA) {
gettok();
opt = "";
if (curtok == TOK_IDENT &&
(!strcicmp(curtokbuf, "LOCK") ||
!strcicmp(curtokbuf, "PURGE") ||
!strcicmp(curtokbuf, "NORMAL") ||
!strcicmp(curtokbuf, "CRUNCH"))) {
opt = stralloc(curtokbuf);
gettok();
} else {
ex = p_expr(tp_str255);
if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING)
opt = ex->val.s;
}
if (!strcicmp(opt, "PURGE")) {
note("File is being closed with PURGE option [186]");
}
}
sp = makestmt_seq(sp, makestmt_assign(filebasename(fex), makeexpr_nil()));
skipcloseparen();
return sp;
}
Static Expr *func_concat()
{
Expr *ex;
if (!skipopenparen())
return makeexpr_string("oops");
ex = p_expr(tp_str255);
while (curtok == TOK_COMMA) {
gettok();
ex = makeexpr_concat(ex, p_expr(tp_str255), 0);
}
skipcloseparen();
return ex;
}
Static Expr *func_copy(ex)
Expr *ex;
{
if (isliteralconst(ex->args[3], NULL) == 2 &&
ex->args[3]->val.i >= stringceiling) {
return makeexpr_bicall_3("sprintf", ex->val.type,
ex->args[0],
makeexpr_string("%s"),
bumpstring(ex->args[1],
makeexpr_unlongcast(ex->args[2]), 1));
}
if (checkconst(ex->args[2], 1)) {
return makeexpr_addr(makeexpr_substring(ex->args[0], ex->args[1],
ex->args[2], ex->args[3]));
}
return makeexpr_bicall_4(strsubname, ex->val.type,
ex->args[0],
ex->args[1],
makeexpr_arglong(ex->args[2], 0),
makeexpr_arglong(ex->args[3], 0));
}
Static Expr *func_cos(ex)
Expr *ex;
{
return makeexpr_bicall_1("cos", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_cosh(ex)
Expr *ex;
{
return makeexpr_bicall_1("cosh", tp_longreal, grabarg(ex, 0));
}
Static Stmt *proc_cycle()
{
return makestmt(SK_CONTINUE);
}
Static Stmt *proc_date()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_str255);
skipcloseparen();
return makestmt_call(makeexpr_bicall_1("VAXdate", tp_integer, ex));
}
Static Stmt *proc_dec()
{
Expr *vex, *ex;
if (!skipopenparen())
return NULL;
vex = p_expr(NULL);
if (curtok == TOK_COMMA) {
gettok();
ex = p_expr(tp_integer);
} else
ex = makeexpr_long(1);
skipcloseparen();
return makestmt_assign(vex, makeexpr_minus(copyexpr(vex), ex));
}
Static Expr *func_dec()
{
return handle_vax_hex(NULL, "d", 0);
}
Static Stmt *proc_delete(ex)
Expr *ex;
{
if (ex->nargs == 1) /* Kludge for Oregon Software Pascal's delete(f) */
return makestmt_call(makeexpr_bicall_1(strdeletename, tp_void, ex->args[0]));
return makestmt_call(makeexpr_bicall_3(strdeletename, tp_void,
ex->args[0],
makeexpr_arglong(ex->args[1], 0),
makeexpr_arglong(ex->args[2], 0)));
}
void parse_special_variant(tp, buf)
Type *tp;
char *buf;
{
char *cp;
Expr *ex;
if (!tp)
intwarning("parse_special_variant", "tp == NULL");
if (!tp || tp->meaning == NULL) {
*buf = 0;
if (curtok == TOK_COMMA) {
skiptotoken(TOK_RPAR);
}
return;
}
strcpy(buf, tp->meaning->name);
while (curtok == TOK_COMMA) {
gettok();
cp = buf + strlen(buf);
*cp++ = '.';
if (curtok == TOK_MINUS) {
*cp++ = '-';
gettok();
}
if (curtok == TOK_INTLIT ||
curtok == TOK_HEXLIT ||
curtok == TOK_OCTLIT) {
sprintf(cp, "%ld", curtokint);
gettok();
} else if (curtok == TOK_HAT || curtok == TOK_STRLIT) {
ex = makeexpr_charcast(accumulate_strlit());
if (ex->kind == EK_CONST) {
if (ex->val.i <= 32 || ex->val.i > 126 ||
ex->val.i == '\'' || ex->val.i == '\\' ||
ex->val.i == '=' || ex->val.i == '}')
sprintf(cp, "%ld", ex->val.i);
else
strcpy(cp, makeCchar(ex->val.i));
} else {
*buf = 0;
*cp = 0;
}
freeexpr(ex);
} else {
if (!wexpecttok(TOK_IDENT)) {
skiptotoken(TOK_RPAR);
return;
}
if (curtokmeaning)
strcpy(cp, curtokmeaning->name);
else
strcpy(cp, curtokbuf);
gettok();
}
}
}
char *find_special_variant(buf, spname, splist, need)
char *buf, *spname;
Strlist *splist;
int need;
{
Strlist *best = NULL;
int len, bestlen = -1;
char *cp, *cp2;
if (!*buf)
return NULL;
while (splist) {
cp = splist->s;
cp2 = buf;
while (*cp && toupper(*cp) == toupper(*cp2))
cp++, cp2++;
len = cp2 - buf;
if (!*cp && (!*cp2 || *cp2 == '.') && len > bestlen) {
best = splist;
bestlen = len;
}
splist = splist->next;
}
if (bestlen != strlen(buf) && my_strchr(buf, '.')) {
if ((need & 1) || bestlen >= 0) {
if (need & 2)
return NULL;
if (spname)
note(format_ss("No %s form known for %s [187]",
spname, strupper(buf)));
}
}
if (bestlen >= 0)
return (char *)best->value;
else
return NULL;
}
Static char *choose_free_func(ex)
Expr *ex;
{
if (!*freename) {
if (!*freervaluename)
return "free";
else
return freervaluename;
}
if (!*freervaluename)
return freervaluename;
if (expr_is_lvalue(ex))
return freename;
else
return freervaluename;
}
Static Stmt *proc_dispose()
{
Expr *ex;
Type *type;
char *name, vbuf[1000];
if (!skipopenparen())
return NULL;
ex = p_expr(tp_anyptr);
type = ex->val.type->basetype;
parse_special_variant(type, vbuf);
skipcloseparen();
name = find_special_variant(vbuf, "SpecialFree", specialfrees, 0);
if (!name)
name = choose_free_func(ex);
return makestmt_call(makeexpr_bicall_1(name, tp_void, ex));
}
Static Expr *func_exp(ex)
Expr *ex;
{
return makeexpr_bicall_1("exp", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_expo(ex)
Expr *ex;
{
Meaning *tvar;
tvar = makestmttempvar(tp_int, name_TEMP);
return makeexpr_comma(makeexpr_bicall_2("frexp", tp_longreal,
grabarg(ex, 0),
makeexpr_addr(makeexpr_var(tvar))),
makeexpr_var(tvar));
}
int is_std_file(ex)
Expr *ex;
{
return isvar(ex, mp_input) || isvar(ex, mp_output) ||
isvar(ex, mp_stderr);
}
Static Expr *iofunc(ex, code)
Expr *ex;
int code;
{
Expr *ex2 = NULL, *ex3 = NULL;
Meaning *tvar = NULL;
if (FCheck(checkfileisopen) && !is_std_file(ex)) {
if (isfiletype(ex->val.type, 1) ||
(exprspeed(ex) < 5 && nosideeffects(ex, 0))) {
ex2 = filebasename(copyexpr(ex));
} else {
ex3 = ex;
tvar = makestmttempvar(ex->val.type, name_TEMP);
ex2 = makeexpr_var(tvar);
ex = makeexpr_var(tvar);
}
}
ex = filebasename(ex);
switch (code) {
case 0: /* eof */
if (fileisbuffered(ex, 0) && *eofbufname)
ex = makeexpr_bicall_1(eofbufname, tp_boolean, ex);
else if (*eofname)
ex = makeexpr_bicall_1(eofname, tp_boolean, ex);
else
ex = makeexpr_rel(EK_NE, makeexpr_bicall_1("feof", tp_int, ex),
makeexpr_long(0));
break;
case 1: /* eoln */
ex = makeexpr_bicall_1(eolnname, tp_boolean, ex);
break;
case 2: /* position or filepos */
if (fileisbuffered(ex, 0) && *fileposbufname)
ex = makeexpr_bicall_1(fileposbufname, tp_integer, ex);
else
ex = makeexpr_bicall_1(fileposname, tp_integer, ex);
break;
case 3: /* maxpos or filesize */
ex = makeexpr_bicall_1(maxposname, tp_integer, ex);
break;
}
if (ex2) {
ex = makeexpr_bicall_4("~CHKIO",
(code == 0 || code == 1) ? tp_boolean : tp_integer,
makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
makeexpr_name("FileNotOpen", tp_int),
ex, makeexpr_long(0));
}
if (ex3)
ex = makeexpr_comma(makeexpr_assign(makeexpr_var(tvar), ex3), ex);
return ex;
}
Static Expr *func_eof()
{
Expr *ex;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_input);
return iofunc(ex, 0);
}
Static Expr *func_eoln()
{
Expr *ex;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_input);
return iofunc(ex, 1);
}
Static Stmt *proc_escape()
{
Expr *ex;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_integer);
else
ex = makeexpr_long(0);
return makestmt_call(makeexpr_bicall_1(name_ESCAPE, tp_int,
makeexpr_arglong(ex, 0)));
}
Static Stmt *proc_excl()
{
Expr *vex, *ex;
if (!skipopenparen())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex = p_expr(vex->val.type->indextype);
skipcloseparen();
if (vex->val.type->kind == TK_SMALLSET)
return makestmt_assign(vex, makeexpr_bin(EK_BAND, vex->val.type,
copyexpr(vex),
makeexpr_un(EK_BNOT, vex->val.type,
makeexpr_bin(EK_LSH, vex->val.type,
makeexpr_longcast(makeexpr_long(1), 1),
ex))));
else
return makestmt_call(makeexpr_bicall_2(setremname, tp_void, vex,
makeexpr_arglong(enum_to_int(ex), 0)));
}
Stmt *proc_exit()
{
Stmt *sp;
if (modula2) {
return makestmt(SK_BREAK);
}
if (curtok == TOK_LPAR) {
gettok();
if (curtok == TOK_PROGRAM ||
(curtok == TOK_IDENT && curtokmeaning->kind == MK_MODULE)) {
gettok();
skipcloseparen();
return makestmt_call(makeexpr_bicall_1("exit", tp_void,
makeexpr_name("EXIT_SUCCESS",
tp_integer)));
}
if (curtok != TOK_IDENT || !curtokmeaning || curtokmeaning != curctx)
note("Attempting to EXIT beyond this function [188]");
gettok();
skipcloseparen();
}
sp = makestmt(SK_RETURN);
if (curctx->kind == MK_FUNCTION && curctx->isfunction) {
sp->exp1 = makeexpr_var(curctx->cbase);
curctx->cbase->refcount++;
}
return sp;
}
Static Expr *file_iofunc(code, base)
int code;
long base;
{
Expr *ex;
Type *basetype;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_input);
if (!ex->val.type || !ex->val.type->basetype ||
!filebasetype(ex->val.type))
basetype = tp_char;
else
basetype = filebasetype(ex->val.type);
return makeexpr_plus(makeexpr_div(iofunc(ex, code),
makeexpr_sizeof(makeexpr_type(basetype), 0)),
makeexpr_long(base));
}
Static Expr *func_fcall()
{
Expr *ex, *ex2, *ex3;
Type *type, *tp;
Meaning *mp, *tvar = NULL;
int firstarg = 0;
if (!skipopenparen())
return NULL;
ex2 = p_expr(tp_proc);
type = ex2->val.type;
if (type->kind != TK_PROCPTR && type->kind != TK_CPROCPTR) {
warning("FCALL requires a function variable [209]");
type = tp_proc;
}
ex = makeexpr(EK_SPCALL, 1);
ex->val.type = type->basetype->basetype;
ex->args[0] = copyexpr(ex2);
if (type->escale != 0)
ex->args[0] = makeexpr_cast(makeexpr_dotq(ex2, "proc", tp_anyptr),
makepointertype(type->basetype));
mp = type->basetype->fbase;
if (mp && mp->isreturn) { /* pointer to buffer for return value */
tvar = makestmttempvar(ex->val.type->basetype,
(ex->val.type->basetype->kind == TK_STRING) ? name_STRING : name_TEMP);
insertarg(&ex, 1, makeexpr_addr(makeexpr_var(tvar)));
mp = mp->xnext;
firstarg++;
}
if (mp) {
if (wneedtok(TOK_COMMA))
ex = p_funcarglist(ex, mp, 0, 0);
}
if (tvar)
ex = makeexpr_hat(ex, 0); /* returns pointer to structured result */
skipcloseparen();
if (type->escale != 1 || hasstaticlinks == 2) {
freeexpr(ex2);
return ex;
}
ex2 = makeexpr_dotq(ex2, "link", tp_anyptr),
ex3 = copyexpr(ex);
insertarg(&ex3, ex3->nargs, copyexpr(ex2));
tp = maketype(TK_FUNCTION);
tp->basetype = type->basetype->basetype;
tp->fbase = type->basetype->fbase;
tp->issigned = 1;
ex3->args[0]->val.type = makepointertype(tp);
return makeexpr_cond(makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
ex3, ex);
}
Static Expr *func_filepos()
{
return file_iofunc(2, seek_base);
}
Static Expr *func_filesize()
{
return file_iofunc(3, 1L);
}
Static Stmt *proc_fillchar()
{
Expr *vex, *ex, *cex;
if (!skipopenparen())
return NULL;
vex = gentle_cast(makeexpr_addr(p_expr(NULL)), tp_anyptr);
if (!skipcomma())
return NULL;
ex = convert_size(argbasetype(vex), p_expr(tp_integer), "FILLCHAR");
if (!skipcomma())
return NULL;
cex = makeexpr_charcast(p_expr(tp_integer));
skipcloseparen();
return makestmt_call(makeexpr_bicall_3("memset", tp_void,
vex,
makeexpr_arglong(cex, 0),
makeexpr_arglong(ex, (size_t_long != 0))));
}
Static Expr *func_sngl()
{
Expr *ex;
ex = p_parexpr(tp_real);
return makeexpr_cast(ex, tp_real);
}
Static Expr *func_float()
{
Expr *ex;
ex = p_parexpr(tp_longreal);
return makeexpr_cast(ex, tp_longreal);
}
Static Stmt *proc_flush()
{
Expr *ex;
Stmt *sp;
ex = p_parexpr(tp_text);
sp = makestmt_call(makeexpr_bicall_1("fflush", tp_void, filebasename(ex)));
if (iocheck_flag)
sp = makestmt_seq(sp, makestmt_assign(makeexpr_var(mp_ioresult),
makeexpr_long(0)));
return sp;
}
Static Expr *func_frac(ex)
Expr *ex;
{
Meaning *tvar;
tvar = makestmttempvar(tp_longreal, name_DUMMY);
return makeexpr_bicall_2("modf", tp_longreal,
grabarg(ex, 0),
makeexpr_addr(makeexpr_var(tvar)));
}
Static Stmt *proc_freemem(ex)
Expr *ex;
{
Stmt *sp;
Expr *vex;
vex = makeexpr_hat(eatcasts(ex->args[0]), 0);
sp = makestmt_call(makeexpr_bicall_1(choose_free_func(vex),
tp_void, copyexpr(vex)));
if (alloczeronil) {
sp = makestmt_if(makeexpr_rel(EK_NE, vex, makeexpr_nil()),
sp, NULL);
} else
freeexpr(vex);
return sp;
}
Static Stmt *proc_get()
{
Expr *ex;
Type *type;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_input);
requirefilebuffer(ex);
type = ex->val.type;
if (isfiletype(type, -1) && *chargetname &&
filebasetype(type)->kind == TK_CHAR)
return makestmt_call(makeexpr_bicall_1(chargetname, tp_void,
filebasename(ex)));
else if (isfiletype(type, -1) && *arraygetname &&
filebasetype(type)->kind == TK_ARRAY)
return makestmt_call(makeexpr_bicall_2(arraygetname, tp_void,
filebasename(ex),
makeexpr_type(filebasetype(type))));
else
return makestmt_call(makeexpr_bicall_2(getname, tp_void,
filebasename(ex),
makeexpr_type(filebasetype(type))));
}
Static Stmt *proc_getmem(ex)
Expr *ex;
{
Expr *vex, *ex2, *sz = NULL;
Stmt *sp;
vex = makeexpr_hat(eatcasts(ex->args[0]), 0);
ex2 = ex->args[1];
if (vex->val.type->kind == TK_POINTER)
ex2 = convert_size(vex->val.type->basetype, ex2, "GETMEM");
if (alloczeronil)
sz = copyexpr(ex2);
ex2 = makeexpr_bicall_1(mallocname, tp_anyptr, ex2);
sp = makestmt_assign(copyexpr(vex), ex2);
if (malloccheck) {
sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ, copyexpr(vex), makeexpr_nil()),
makestmt_call(makeexpr_bicall_0(name_OUTMEM, tp_int)),
NULL));
}
if (sz && !isconstantexpr(sz)) {
if (alloczeronil == 2)
note("Called GETMEM with variable argument [189]");
sp = makestmt_if(makeexpr_rel(EK_NE, sz, makeexpr_long(0)),
sp,
makestmt_assign(vex, makeexpr_nil()));
} else
freeexpr(vex);
return sp;
}
Static Stmt *proc_gotoxy(ex)
Expr *ex;
{
return makestmt_call(makeexpr_bicall_2("gotoxy", tp_void,
makeexpr_arglong(ex->args[0], 0),
makeexpr_arglong(ex->args[1], 0)));
}
Static Expr *handle_vax_hex(ex, fmt, scale)
Expr *ex;
char *fmt;
int scale;
{
Expr *lex, *dex, *vex;
Meaning *tvar;
Type *tp;
long smin, smax;
int bits;
if (!ex) {
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
}
tp = true_type(ex);
if (ord_range(tp, &smin, &smax))
bits = typebits(smin, smax);
else
bits = 32;
if (curtok == TOK_COMMA) {
gettok();
if (curtok != TOK_COMMA)
lex = makeexpr_arglong(p_expr(tp_integer), 0);
else
lex = NULL;
} else
lex = NULL;
if (!lex) {
if (!scale)
lex = makeexpr_long(11);
else
lex = makeexpr_long((bits+scale-1) / scale + 1);
}
if (curtok == TOK_COMMA) {
gettok();
dex = makeexpr_arglong(p_expr(tp_integer), 0);
} else {
if (!scale)
dex = makeexpr_long(10);
else
dex = makeexpr_long((bits+scale-1) / scale);
}
if (lex->kind == EK_CONST && dex->kind == EK_CONST &&
lex->val.i < dex->val.i)
lex = NULL;
skipcloseparen();
tvar = makestmttempvar(tp_str255, name_STRING);
vex = makeexpr_var(tvar);
ex = makeexpr_forcelongness(ex);
if (exprlongness(ex) > 0)
fmt = format_s("l%s", fmt);
if (checkconst(lex, 0) || checkconst(lex, 1))
lex = NULL;
if (checkconst(dex, 0) || checkconst(dex, 1))
dex = NULL;
if (lex) {
if (dex)
ex = makeexpr_bicall_5("sprintf", tp_str255, vex,
makeexpr_string(format_s("%%*.*%s", fmt)),
lex, dex, ex);
else
ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
makeexpr_string(format_s("%%*%s", fmt)),
lex, ex);
} else {
if (dex)
ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
makeexpr_string(format_s("%%.*%s", fmt)),
dex, ex);
else
ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
makeexpr_string(format_s("%%%s", fmt)),
ex);
}
return ex;
}
Static Expr *func_hex()
{
Expr *ex;
char *cp;
if (!skipopenparen())
return NULL;
ex = makeexpr_stringcast(p_expr(tp_integer));
if ((ex->val.type->kind == TK_STRING ||
ex->val.type == tp_strptr) &&
curtok != TOK_COMMA) {
skipcloseparen();
if (ex->kind == EK_CONST) { /* HP Pascal */
cp = getstring(ex);
ex = makeexpr_long(my_strtol(cp, NULL, 16));
insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer));
return ex;
} else {
return makeexpr_bicall_3("strtol", tp_integer,
ex, makeexpr_nil(), makeexpr_long(16));
}
} else { /* VAX Pascal */
return handle_vax_hex(ex, "x", 4);
}
}
Static Expr *func_hi()
{
Expr *ex;
ex = force_unsigned(p_parexpr(tp_integer));
return makeexpr_bin(EK_RSH, tp_ubyte,
ex, makeexpr_long(8));
}
Static Expr *func_high()
{
Expr *ex;
Type *type;
ex = p_parexpr(tp_integer);
type = ex->val.type;
if (type->kind == TK_POINTER)
type = type->basetype;
if (type->kind == TK_ARRAY ||
type->kind == TK_SMALLARRAY) {
ex = makeexpr_minus(copyexpr(type->indextype->smax),
copyexpr(type->indextype->smin));
} else {
warning("HIGH requires an array name parameter [210]");
ex = makeexpr_bicall_1("HIGH", tp_int, ex);
}
return ex;
}
Static Expr *func_hiword()
{
Expr *ex;
ex = force_unsigned(p_parexpr(tp_unsigned));
return makeexpr_bin(EK_RSH, tp_unsigned,
ex, makeexpr_long(16));
}
Static Stmt *proc_inc()
{
Expr *vex, *ex;
if (!skipopenparen())
return NULL;
vex = p_expr(NULL);
if (curtok == TOK_COMMA) {
gettok();
ex = p_expr(tp_integer);
} else
ex = makeexpr_long(1);
skipcloseparen();
return makestmt_assign(vex, makeexpr_plus(copyexpr(vex), ex));
}
Static Stmt *proc_incl()
{
Expr *vex, *ex;
if (!skipopenparen())
return NULL;
vex = p_expr(NULL);
if (!skipcomma())
return NULL;
ex = p_expr(vex->val.type->indextype);
skipcloseparen();
if (vex->val.type->kind == TK_SMALLSET)
return makestmt_assign(vex, makeexpr_bin(EK_BOR, vex->val.type,
copyexpr(vex),
makeexpr_bin(EK_LSH, vex->val.type,
makeexpr_longcast(makeexpr_long(1), 1),
ex)));
else
return makestmt_call(makeexpr_bicall_2(setaddname, tp_void, vex,
makeexpr_arglong(enum_to_int(ex), 0)));
}
Static Stmt *proc_insert(ex)
Expr *ex;
{
return makestmt_call(makeexpr_bicall_3(strinsertname, tp_void,
ex->args[0],
ex->args[1],
makeexpr_arglong(ex->args[2], 0)));
}
Static Expr *func_int()
{
Expr *ex;
Meaning *tvar;
ex = p_parexpr(tp_integer);
if (ex->val.type->kind == TK_REAL) { /* Turbo Pascal INT */
tvar = makestmttempvar(tp_longreal, name_TEMP);
return makeexpr_comma(makeexpr_bicall_2("modf", tp_longreal,
grabarg(ex, 0),
makeexpr_addr(makeexpr_var(tvar))),
makeexpr_var(tvar));
} else { /* VAX Pascal INT */
return makeexpr_ord(ex);
}
}
Static Expr *func_uint()
{
Expr *ex;
ex = p_parexpr(tp_integer);
return makeexpr_cast(ex, tp_unsigned);
}
Static Stmt *proc_leave()
{
return makestmt(SK_BREAK);
}
Static Expr *func_lo()
{
Expr *ex;
ex = gentle_cast(p_parexpr(tp_integer), tp_ushort);
return makeexpr_bin(EK_BAND, tp_ubyte,
ex, makeexpr_long(255));
}
Static Expr *func_loophole()
{
Type *type;
Expr *ex;
if (!skipopenparen())
return NULL;
type = p_type(NULL);
if (!skipcomma())
return NULL;
ex = p_expr(tp_integer);
skipcloseparen();
return pascaltypecast(type, ex);
}
Static Expr *func_lower()
{
Expr *ex;
Value val;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
val = p_constant(tp_integer);
if (!val.type || val.i != 1)
note("LOWER(v,n) not supported for n>1 [190]");
}
skipcloseparen();
return copyexpr(ex->val.type->indextype->smin);
}
Static Expr *func_loword()
{
Expr *ex;
ex = p_parexpr(tp_integer);
return makeexpr_bin(EK_BAND, tp_ushort,
ex, makeexpr_long(65535));
}
Static Expr *func_ln(ex)
Expr *ex;
{
return makeexpr_bicall_1("log", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_log(ex)
Expr *ex;
{
return makeexpr_bicall_1("log10", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_max()
{
Type *tp;
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE) {
tp = curtokmeaning->type;
gettok();
skipcloseparen();
return copyexpr(tp->smax);
}
ex = p_expr(tp_integer);
while (curtok == TOK_COMMA) {
gettok();
ex2 = p_expr(ex->val.type);
if (ex->val.type->kind == TK_REAL) {
tp = ex->val.type;
if (ex2->val.type->kind != TK_REAL)
ex2 = makeexpr_cast(ex2, tp);
} else {
tp = ex2->val.type;
if (ex->val.type->kind != TK_REAL)
ex = makeexpr_cast(ex, tp);
}
ex = makeexpr_bicall_2((tp->kind == TK_REAL) ? "P_rmax" : "P_imax",
tp, ex, ex2);
}
skipcloseparen();
return ex;
}
Static Expr *func_maxavail(ex)
Expr *ex;
{
freeexpr(ex);
return makeexpr_bicall_0("maxavail", tp_integer);
}
Static Expr *func_maxpos()
{
return file_iofunc(3, seek_base);
}
Static Expr *func_memavail(ex)
Expr *ex;
{
freeexpr(ex);
return makeexpr_bicall_0("memavail", tp_integer);
}
Static Expr *var_mem()
{
Expr *ex, *ex2;
if (!wneedtok(TOK_LBR))
return makeexpr_name("MEM", tp_integer);
ex = p_expr(tp_integer);
if (curtok == TOK_COLON) {
gettok();
ex2 = p_expr(tp_integer);
ex = makeexpr_bicall_2("MEM", tp_ubyte, ex, ex2);
} else {
ex = makeexpr_bicall_1("MEM", tp_ubyte, ex);
}
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
note("Reference to MEM [191]");
return ex;
}
Static Expr *var_memw()
{
Expr *ex, *ex2;
if (!wneedtok(TOK_LBR))
return makeexpr_name("MEMW", tp_integer);
ex = p_expr(tp_integer);
if (curtok == TOK_COLON) {
gettok();
ex2 = p_expr(tp_integer);
ex = makeexpr_bicall_2("MEMW", tp_ushort, ex, ex2);
} else {
ex = makeexpr_bicall_1("MEMW", tp_ushort, ex);
}
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
note("Reference to MEMW [191]");
return ex;
}
Static Expr *var_meml()
{
Expr *ex, *ex2;
if (!wneedtok(TOK_LBR))
return makeexpr_name("MEML", tp_integer);
ex = p_expr(tp_integer);
if (curtok == TOK_COLON) {
gettok();
ex2 = p_expr(tp_integer);
ex = makeexpr_bicall_2("MEML", tp_integer, ex, ex2);
} else {
ex = makeexpr_bicall_1("MEML", tp_integer, ex);
}
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
note("Reference to MEML [191]");
return ex;
}
Static Expr *func_min()
{
Type *tp;
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE) {
tp = curtokmeaning->type;
gettok();
skipcloseparen();
return copyexpr(tp->smin);
}
ex = p_expr(tp_integer);
while (curtok == TOK_COMMA) {
gettok();
ex2 = p_expr(ex->val.type);
if (ex->val.type->kind == TK_REAL) {
tp = ex->val.type;
if (ex2->val.type->kind != TK_REAL)
ex2 = makeexpr_cast(ex2, tp);
} else {
tp = ex2->val.type;
if (ex->val.type->kind != TK_REAL)
ex = makeexpr_cast(ex, tp);
}
ex = makeexpr_bicall_2((tp->kind == TK_REAL) ? "P_rmin" : "P_imin",
tp, ex, ex2);
}
skipcloseparen();
return ex;
}
Static Stmt *proc_move(ex)
Expr *ex;
{
ex->args[0] = gentle_cast(ex->args[0], tp_anyptr); /* source */
ex->args[1] = gentle_cast(ex->args[1], tp_anyptr); /* dest */
ex->args[2] = convert_size(choosetype(argbasetype(ex->args[0]),
argbasetype(ex->args[1])), ex->args[2], "MOVE");
return makestmt_call(makeexpr_bicall_3("memmove", tp_void,
ex->args[1],
ex->args[0],
makeexpr_arglong(ex->args[2], (size_t_long != 0))));
}
Static Stmt *proc_move_fast()
{
Expr *ex, *ex2, *ex3, *ex4;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ord_range_expr(ex2->val.type->indextype, &ex4, NULL);
ex2 = makeexpr_index(ex2, p_expr(tp_integer), copyexpr(ex4));
if (!skipcomma())
return NULL;
ex3 = p_expr(tp_integer);
if (!skipcomma())
return NULL;
ord_range_expr(ex3->val.type->indextype, &ex4, NULL);
ex3 = makeexpr_index(ex3, p_expr(tp_integer), copyexpr(ex4));
skipcloseparen();
ex = convert_size(choosetype(argbasetype(ex2),
argbasetype(ex3)), ex, "MOVE_FAST");
return makestmt_call(makeexpr_bicall_3("memmove", tp_void,
makeexpr_addr(ex3),
makeexpr_addr(ex2),
makeexpr_arglong(ex, (size_t_long != 0))));
}
Static Stmt *proc_new()
{
Expr *ex, *ex2;
Stmt *sp, **spp;
Type *type;
char *name, *name2 = NULL, vbuf[1000];
if (!skipopenparen())
return NULL;
ex = p_expr(tp_anyptr);
type = ex->val.type;
if (type->kind == TK_POINTER)
type = type->basetype;
parse_special_variant(type, vbuf);
skipcloseparen();
name = find_special_variant(vbuf, NULL, specialmallocs, 3);
if (!name) {
name2 = find_special_variant(vbuf, NULL, specialsizeofs, 3);
if (!name2) {
name = find_special_variant(vbuf, NULL, specialmallocs, 1);
name2 = find_special_variant(vbuf, NULL, specialsizeofs, 1);
if (name || !name2)
name = find_special_variant(vbuf, "SpecialMalloc", specialmallocs, 1);
else
name2 = find_special_variant(vbuf, "SpecialSizeOf", specialsizeofs, 1);
}
}
if (name) {
ex2 = makeexpr_bicall_0(name, ex->val.type);
} else if (name2) {
ex2 = makeexpr_bicall_1(mallocname, tp_anyptr, pc_expr_str(name2));
} else {
ex2 = makeexpr_bicall_1(mallocname, tp_anyptr,
makeexpr_sizeof(makeexpr_type(type), 1));
}
sp = makestmt_assign(copyexpr(ex), ex2);
if (malloccheck) {
sp = makestmt_seq(sp, makestmt_if(makeexpr_rel(EK_EQ,
copyexpr(ex),
makeexpr_nil()),
makestmt_call(makeexpr_bicall_0(name_OUTMEM, tp_int)),
NULL));
}
spp = &sp->next;
while (*spp)
spp = &(*spp)->next;
if (type->kind == TK_RECORD)
initfilevars(type->fbase, &spp, makeexpr_hat(ex, 0));
else if (isfiletype(type, -1))
sp = makestmt_seq(sp, makestmt_call(initfilevar(makeexpr_hat(ex, 0))));
else
freeexpr(ex);
return sp;
}
Static Expr *func_oct()
{
return handle_vax_hex(NULL, "o", 3);
}
Static Expr *func_octal(ex)
Expr *ex;
{
char *cp;
ex = grabarg(ex, 0);
if (ex->kind == EK_CONST) {
cp = getstring(ex);
ex = makeexpr_long(my_strtol(cp, NULL, 8));
insertarg(&ex, 0, makeexpr_name("0%lo", tp_integer));
return ex;
} else {
return makeexpr_bicall_3("strtol", tp_integer,
ex, makeexpr_nil(), makeexpr_long(8));
}
}
Static Expr *func_odd(ex)
Expr *ex;
{
ex = makeexpr_unlongcast(grabarg(ex, 0));
if (*oddname)
return makeexpr_bicall_1(oddname, tp_boolean, ex);
else
return makeexpr_bin(EK_BAND, tp_boolean, ex, makeexpr_long(1));
}
Static Stmt *proc_open()
{
return handleopen(2);
}
Static Expr *func_ord()
{
Expr *ex;
if (wneedtok(TOK_LPAR)) {
ex = p_ord_expr();
skipcloseparen();
} else
ex = p_ord_expr();
return makeexpr_ord(ex);
}
Static Expr *func_ord4()
{
Expr *ex;
if (wneedtok(TOK_LPAR)) {
ex = p_ord_expr();
skipcloseparen();
} else
ex = p_ord_expr();
return makeexpr_longcast(makeexpr_ord(ex), 1);
}
Static Stmt *proc_pack()
{
Expr *exs, *exd, *exi, *mind;
Meaning *tvar;
Stmt *sp;
if (!skipopenparen())
return NULL;
exs = p_expr(NULL);
if (!skipcomma())
return NULL;
exi = p_ord_expr();
if (!skipcomma())
return NULL;
exd = p_expr(NULL);
skipcloseparen();
if (exs->val.type->kind != TK_ARRAY ||
(exd->val.type->kind != TK_ARRAY &&
exd->val.type->kind != TK_SMALLARRAY)) {
warning("Bad argument types for PACK/UNPACK [325]");
return makestmt_call(makeexpr_bicall_3("pack", tp_void,
exs, exi, exd));
}
if (exs->val.type->smax || exd->val.type->smax) {
tvar = makestmttempvar(exd->val.type->indextype, name_TEMP);
sp = makestmt(SK_FOR);
if (exd->val.type->smin)
mind = exd->val.type->smin;
else
mind = exd->val.type->indextype->smin;
sp->exp1 = makeexpr_assign(makeexpr_var(tvar),
copyexpr(mind));
sp->exp2 = makeexpr_rel(EK_LE, makeexpr_var(tvar),
copyexpr(exd->val.type->indextype->smax));
sp->exp3 = makeexpr_assign(makeexpr_var(tvar),
makeexpr_plus(makeexpr_var(tvar),
makeexpr_long(1)));
exi = makeexpr_minus(exi, copyexpr(mind));
sp->stm1 = makestmt_assign(p_index(exd, makeexpr_var(tvar)),
p_index(exs,
makeexpr_plus(makeexpr_var(tvar),
exi)));
return sp;
} else {
exi = gentle_cast(exi, exs->val.type->indextype);
return makestmt_call(makeexpr_bicall_3("memcpy", exd->val.type,
exd,
makeexpr_addr(p_index(exs, exi)),
makeexpr_sizeof(copyexpr(exd), 0)));
}
}
Static Expr *func_pad(ex)
Expr *ex;
{
if (checkconst(ex->args[1], 0) || /* "s" is null string */
checkconst(ex->args[2], ' ')) {
return makeexpr_bicall_4("sprintf", tp_strptr, ex->args[0],
makeexpr_string("%*s"),
makeexpr_longcast(ex->args[3], 0),
makeexpr_string(""));
}
return makeexpr_bicall_4(strpadname, tp_strptr,
ex->args[0], ex->args[1], ex->args[2],
makeexpr_arglong(ex->args[3], 0));
}
Static Stmt *proc_page()
{
Expr *fex, *ex;
if (curtok == TOK_LPAR) {
fex = p_parexpr(tp_text);
ex = makeexpr_bicall_2("fprintf", tp_int,
filebasename(copyexpr(fex)),
makeexpr_string("\f"));
} else {
fex = makeexpr_var(mp_output);
ex = makeexpr_bicall_1("printf", tp_int,
makeexpr_string("\f"));
}
if (FCheck(checkfilewrite)) {
ex = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_GE, ex, makeexpr_long(0)),
makeexpr_name(filewriteerrorname, tp_int));
}
return wrapopencheck(makestmt_call(ex), fex);
}
Static Expr *func_paramcount(ex)
Expr *ex;
{
freeexpr(ex);
return makeexpr_minus(makeexpr_name(name_ARGC, tp_int),
makeexpr_long(1));
}
Static Expr *func_paramstr(ex)
Expr *ex;
{
Expr *ex2;
ex2 = makeexpr_index(makeexpr_name(name_ARGV,
makepointertype(tp_strptr)),
makeexpr_unlongcast(ex->args[1]),
makeexpr_long(0));
ex2->val.type = tp_str255;
return makeexpr_bicall_3("sprintf", tp_strptr,
ex->args[0],
makeexpr_string("%s"),
ex2);
}
Static Expr *func_pi()
{
return makeexpr_name("M_PI", tp_longreal);
}
Static Expr *var_port()
{
Expr *ex;
if (!wneedtok(TOK_LBR))
return makeexpr_name("PORT", tp_integer);
ex = p_expr(tp_integer);
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
note("Reference to PORT [191]");
return makeexpr_bicall_1("PORT", tp_ubyte, ex);
}
Static Expr *var_portw()
{
Expr *ex;
if (!wneedtok(TOK_LBR))
return makeexpr_name("PORTW", tp_integer);
ex = p_expr(tp_integer);
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
note("Reference to PORTW [191]");
return makeexpr_bicall_1("PORTW", tp_ushort, ex);
}
Static Expr *func_pos(ex)
Expr *ex;
{
char *cp;
cp = strposname;
if (!*cp) {
note("POS function used [192]");
cp = "POS";
}
return makeexpr_bicall_3(cp, tp_int,
ex->args[1],
ex->args[0],
makeexpr_long(1));
}
Static Expr *func_ptr(ex)
Expr *ex;
{
note("PTR function was used [193]");
return ex;
}
Static Expr *func_position()
{
return file_iofunc(2, seek_base);
}
Static Expr *func_pred()
{
Expr *ex;
if (wneedtok(TOK_LPAR)) {
ex = p_ord_expr();
skipcloseparen();
} else
ex = p_ord_expr();
#if 1
ex = makeexpr_inc(ex, makeexpr_long(-1));
#else
ex = makeexpr_cast(makeexpr_plus(ex, makeexpr_long(-1)), ex->val.type);
#endif
return ex;
}
Static Stmt *proc_put()
{
Expr *ex;
Type *type;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_output);
requirefilebuffer(ex);
type = ex->val.type;
if (isfiletype(type, -1) && *charputname &&
filebasetype(type)->kind == TK_CHAR)
return makestmt_call(makeexpr_bicall_1(charputname, tp_void,
filebasename(ex)));
else if (isfiletype(type, -1) && *arrayputname &&
filebasetype(type)->kind == TK_ARRAY)
return makestmt_call(makeexpr_bicall_2(arrayputname, tp_void,
filebasename(ex),
makeexpr_type(filebasetype(type))));
else
return makestmt_call(makeexpr_bicall_2(putname, tp_void,
filebasename(ex),
makeexpr_type(filebasetype(type))));
}
Static Expr *func_pwroften(ex)
Expr *ex;
{
return makeexpr_bicall_2("pow", tp_longreal,
makeexpr_real("10.0"), grabarg(ex, 0));
}
Static Stmt *proc_reset()
{
return handleopen(0);
}
Static Stmt *proc_rewrite()
{
return handleopen(1);
}
Stmt *doseek(fex, ex)
Expr *fex, *ex;
{
Expr *ex2;
Type *basetype = filebasetype(fex->val.type);
if (ansiC == 1)
ex2 = makeexpr_name("SEEK_SET", tp_int);
else
ex2 = makeexpr_long(0);
ex = makeexpr_bicall_3("fseek", tp_int,
filebasename(copyexpr(fex)),
makeexpr_arglong(
makeexpr_times(makeexpr_minus(ex,
makeexpr_long(seek_base)),
makeexpr_sizeof(makeexpr_type(basetype), 0)),
1),
ex2);
if (FCheck(checkfileseek)) {
ex = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_EQ, ex, makeexpr_long(0)),
makeexpr_name(endoffilename, tp_int));
}
return makestmt_call(ex);
}
Static Expr *makegetchar(fex)
Expr *fex;
{
if (isvar(fex, mp_input))
return makeexpr_bicall_0("getchar", tp_char);
else
return makeexpr_bicall_1("getc", tp_char, filebasename(copyexpr(fex)));
}
Static Stmt *fixscanf(sp, fex)
Stmt *sp;
Expr *fex;
{
int nargs, i, isstrread;
char *cp;
Expr *ex;
Stmt *sp2;
isstrread = (fex->val.type->kind == TK_STRING);
if (sp->kind == SK_ASSIGN && sp->exp1->kind == EK_BICALL &&
!strcmp(sp->exp1->val.s, "scanf")) {
if (sp->exp1->args[0]->kind == EK_CONST &&
!(sp->exp1->args[0]->val.i&1) && !isstrread) {
cp = sp->exp1->args[0]->val.s; /* scanf("%c%c") -> getchar;getchar */
for (i = 0; cp[i] == '%' && cp[i+1] == 'c'; ) {
i += 2;
if (i == sp->exp1->args[0]->val.i) {
sp2 = NULL;
for (i = 1; i < sp->exp1->nargs; i++) {
ex = makeexpr_hat(sp->exp1->args[i], 0);
sp2 = makestmt_seq(sp2,
makestmt_assign(copyexpr(ex),
makegetchar(fex)));
if (checkeof(fex)) {
sp2 = makestmt_seq(sp2,
makestmt_call(makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_NE,
ex,
makeexpr_name("EOF", tp_char)),
makeexpr_name(endoffilename, tp_int))));
} else
freeexpr(ex);
}
return sp2;
}
}
}
nargs = sp->exp1->nargs - 1;
if (isstrread) {
strchange(&sp->exp1->val.s, "sscanf");
insertarg(&sp->exp1, 0, copyexpr(fex));
} else if (!isvar(fex, mp_input)) {
strchange(&sp->exp1->val.s, "fscanf");
insertarg(&sp->exp1, 0, filebasename(copyexpr(fex)));
}
if (FCheck(checkreadformat)) {
if (checkeof(fex) && !isstrread)
ex = makeexpr_cond(makeexpr_rel(EK_NE,
makeexpr_bicall_1("feof",
tp_int,
filebasename(copyexpr(fex))),
makeexpr_long(0)),
makeexpr_name(endoffilename, tp_int),
makeexpr_name(badinputformatname, tp_int));
else
ex = makeexpr_name(badinputformatname, tp_int);
sp->exp1 = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_EQ,
sp->exp1,
makeexpr_long(nargs)),
ex);
} else if (checkeof(fex) && !isstrread) {
sp->exp1 = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_NE,
sp->exp1,
makeexpr_name("EOF", tp_int)),
makeexpr_name(endoffilename, tp_int));
}
}
return sp;
}
Static Expr *makefgets(vex, lex, fex)
Expr *vex, *lex, *fex;
{
Expr *ex;
ex = makeexpr_bicall_3("fgets", tp_strptr,
vex,
lex,
filebasename(copyexpr(fex)));
if (checkeof(fex)) {
ex = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_NE, ex, makeexpr_nil()),
makeexpr_name(endoffilename, tp_int));
}
return ex;
}
Static Stmt *skipeoln(fex)
Expr *fex;
{
Meaning *tvar;
Expr *ex;
if (!strcmp(readlnname, "fgets")) {
tvar = makestmttempvar(tp_str255, name_STRING);
return makestmt_call(makefgets(makeexpr_var(tvar),
makeexpr_long(stringceiling+1),
filebasename(fex)));
} else if (!strcmp(readlnname, "scanf") || !*readlnname) {
if (checkeof(fex))
ex = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_NE,
makegetchar(fex),
makeexpr_name("EOF", tp_char)),
makeexpr_name(endoffilename, tp_int));
else
ex = makegetchar(fex);
return makestmt_seq(fixscanf(
makestmt_call(makeexpr_bicall_1("scanf", tp_int,
makeexpr_string("%*[^\n]"))), fex),
makestmt_call(ex));
} else {
return makestmt_call(makeexpr_bicall_1(readlnname, tp_void,
filebasename(copyexpr(fex))));
}
}
Static Stmt *handleread_text(fex, var, isreadln)
Expr *fex, *var;
int isreadln;
{
Stmt *spbase, *spafter, *sp;
Expr *ex = NULL, *exj = NULL;
Type *type;
Meaning *tvar, *tempcp, *mp;
int i, isstrread, scanfmode, readlnflag, varstring, maxstring;
int longstrsize = (longstringsize > 0) ? longstringsize : stringceiling;
long rmin, rmax;
char *fmt;
spbase = NULL;
spafter = NULL;
sp = NULL;
tempcp = NULL;
if (fex->val.type->kind == TK_ARRAY)
fex = makeexpr_sprintfify(fex);
isstrread = (fex->val.type->kind == TK_STRING);
if (isstrread) {
exj = var;
var = p_expr(NULL);
}
scanfmode = !strcmp(readlnname, "scanf") || !*readlnname || isstrread;
for (;;) {
readlnflag = isreadln && curtok == TOK_RPAR;
if (var->val.type->kind == TK_STRING && !isstrread) {
if (sp)
spbase = makestmt_seq(spbase, fixscanf(sp, fex));
spbase = makestmt_seq(spbase, spafter);
varstring = (varstrings && var->kind == EK_VAR &&
(mp = (Meaning *)var->val.i)->kind == MK_VARPARAM &&
mp->type == tp_strptr);
maxstring = (strmax(var) >= longstrsize && !varstring);
if (isvar(fex, mp_input) && maxstring && usegets && readlnflag) {
spbase = makestmt_seq(spbase,
makestmt_call(makeexpr_bicall_1("gets", tp_str255,
makeexpr_addr(var))));
isreadln = 0;
} else if (scanfmode && !varstring &&
(*readlnname || !isreadln)) {
spbase = makestmt_seq(spbase, makestmt_assign(makeexpr_hat(copyexpr(var), 0),
makeexpr_char(0)));
if (maxstring && usegets)
ex = makeexpr_string("%[^\n]");
else
ex = makeexpr_string(format_d("%%%d[^\n]", strmax(var)));
ex = makeexpr_bicall_2("scanf", tp_int, ex, makeexpr_addr(var));
spbase = makestmt_seq(spbase, fixscanf(makestmt_call(ex), fex));
if (readlnflag && maxstring && usegets) {
spbase = makestmt_seq(spbase, makestmt_call(makegetchar(fex)));
isreadln = 0;
}
} else {
ex = makeexpr_plus(strmax_func(var), makeexpr_long(1));
spbase = makestmt_seq(spbase,
makestmt_call(makefgets(makeexpr_addr(copyexpr(var)),
ex,
fex)));
if (!tempcp)
tempcp = makestmttempvar(tp_charptr, name_TEMP);
spbase = makestmt_seq(spbase,
makestmt_assign(makeexpr_var(tempcp),
makeexpr_bicall_2("strchr", tp_charptr,
makeexpr_addr(copyexpr(var)),
makeexpr_char('\n'))));
sp = makestmt_assign(makeexpr_hat(makeexpr_var(tempcp), 0),
makeexpr_long(0));
if (readlnflag)
isreadln = 0;
else
sp = makestmt_seq(sp,
makestmt_call(makeexpr_bicall_2("ungetc", tp_void,
makeexpr_char('\n'),
filebasename(copyexpr(fex)))));
spbase = makestmt_seq(spbase, makestmt_if(makeexpr_rel(EK_NE,
makeexpr_var(tempcp),
makeexpr_nil()),
sp,
NULL));
}
sp = NULL;
spafter = NULL;
} else if (var->val.type->kind == TK_ARRAY && !isstrread) {
if (sp)
spbase = makestmt_seq(spbase, fixscanf(sp, fex));
spbase = makestmt_seq(spbase, spafter);
ex = makeexpr_sizeof(copyexpr(var), 0);
if (readlnflag) {
spbase = makestmt_seq(spbase,
makestmt_call(
makeexpr_bicall_3("P_readlnpaoc", tp_void,
filebasename(copyexpr(fex)),
makeexpr_addr(var),
makeexpr_arglong(ex, 0))));
isreadln = 0;
} else {
spbase = makestmt_seq(spbase,
makestmt_call(
makeexpr_bicall_3("P_readpaoc", tp_void,
filebasename(copyexpr(fex)),
makeexpr_addr(var),
makeexpr_arglong(ex, 0))));
}
sp = NULL;
spafter = NULL;
} else {
switch (ord_type(var->val.type)->kind) {
case TK_INTEGER:
fmt = "d";
if (curtok == TOK_COLON) {
gettok();
if (curtok == TOK_IDENT &&
!strcicmp(curtokbuf, "HEX")) {
fmt = "x";
} else if (curtok == TOK_IDENT &&
!strcicmp(curtokbuf, "OCT")) {
fmt = "o";
} else if (curtok == TOK_IDENT &&
!strcicmp(curtokbuf, "BIN")) {
fmt = "b";
note("Using %b for binary format in scanf [194]");
} else
warning("Unrecognized format specified in READ [212]");
gettok();
}
type = findbasetype(var->val.type, ODECL_NOPRES);
if (exprlongness(var) > 0)
ex = makeexpr_string(format_s("%%l%s", fmt));
else if (type == tp_integer || type == tp_int ||
type == tp_uint || type == tp_sint)
ex = makeexpr_string(format_s("%%%s", fmt));
else if (type == tp_sshort || type == tp_ushort)
ex = makeexpr_string(format_s("%%h%s", fmt));
else {
tvar = makestmttempvar(tp_int, name_TEMP);
spafter = makestmt_seq(spafter,
makestmt_assign(var,
makeexpr_var(tvar)));
var = makeexpr_var(tvar);
ex = makeexpr_string(format_s("%%%s", fmt));
}
break;
case TK_CHAR:
ex = makeexpr_string("%c");
if (newlinespace && !isstrread) {
spafter = makestmt_seq(spafter,
makestmt_if(makeexpr_rel(EK_EQ,
copyexpr(var),
makeexpr_char('\n')),
makestmt_assign(copyexpr(var),
makeexpr_char(' ')),
NULL));
}
break;
case TK_BOOLEAN:
tvar = makestmttempvar(tp_str255, name_STRING);
spafter = makestmt_seq(spafter,
makestmt_assign(var,
makeexpr_or(makeexpr_rel(EK_EQ,
makeexpr_hat(makeexpr_var(tvar), 0),
makeexpr_char('T')),
makeexpr_rel(EK_EQ,
makeexpr_hat(makeexpr_var(tvar), 0),
makeexpr_char('t')))));
var = makeexpr_var(tvar);
ex = makeexpr_string(" %[a-zA-Z]");
break;
case TK_ENUM:
warning("READ on enumerated types not yet supported [213]");
if (useenum)
ex = makeexpr_string("%d");
else
ex = makeexpr_string("%hd");
break;
case TK_REAL:
if (var->val.type == tp_longreal)
ex = makeexpr_string("%lg");
else
ex = makeexpr_string("%g");
break;
case TK_STRING: /* strread only */
ex = makeexpr_string(format_d("%%%lds", strmax(fex)));
break;
case TK_ARRAY: /* strread only */
if (!ord_range(ex->val.type->indextype, &rmin, &rmax)) {
rmin = 1;
rmax = 1;
note("Can't determine length of packed array of chars [195]");
}
ex = makeexpr_string(format_d("%%%ldc", rmax-rmin+1));
break;
default:
note("Element has wrong type for WRITE statement [196]");
ex = NULL;
break;
}
if (ex) {
var = makeexpr_addr(var);
if (sp) {
sp->exp1->args[0] = makeexpr_concat(sp->exp1->args[0], ex, 0);
insertarg(&sp->exp1, sp->exp1->nargs, var);
} else {
sp = makestmt_call(makeexpr_bicall_2("scanf", tp_int, ex, var));
}
}
}
if (curtok == TOK_COMMA) {
gettok();
var = p_expr(NULL);
} else
break;
}
if (sp) {
if (isstrread && !FCheck(checkreadformat) &&
((i=0, checkstring(sp->exp1->args[0], "%d")) ||
(i++, checkstring(sp->exp1->args[0], "%ld")) ||
(i++, checkstring(sp->exp1->args[0], "%hd")) ||
(i++, checkstring(sp->exp1->args[0], "%lg")))) {
if (fullstrread != 0 && exj) {
tvar = makestmttempvar(tp_strptr, name_STRING);
sp->exp1 = makeexpr_assign(makeexpr_hat(sp->exp1->args[1], 0),
(i == 3) ? makeexpr_bicall_2("strtod", tp_longreal,
copyexpr(fex),
makeexpr_addr(makeexpr_var(tvar)))
: makeexpr_bicall_3("strtol", tp_integer,
copyexpr(fex),
makeexpr_addr(makeexpr_var(tvar)),
makeexpr_long(10)));
spafter = makestmt_seq(spafter,
makestmt_assign(copyexpr(exj),
makeexpr_minus(makeexpr_var(tvar),
makeexpr_addr(copyexpr(fex)))));
} else {
sp->exp1 = makeexpr_assign(makeexpr_hat(sp->exp1->args[1], 0),
makeexpr_bicall_1((i == 1) ? "atol" : (i == 3) ? "atof" : "atoi",
(i == 1) ? tp_integer : (i == 3) ? tp_longreal : tp_int,
copyexpr(fex)));
}
} else if (isstrread && fullstrread != 0 && exj) {
sp->exp1->args[0] = makeexpr_concat(sp->exp1->args[0],
makeexpr_string(sizeof_int >= 32 ? "%n" : "%ln"), 0);
insertarg(&sp->exp1, sp->exp1->nargs, makeexpr_addr(copyexpr(exj)));
} else if (isreadln && scanfmode && !FCheck(checkreadformat)) {
isreadln = 0;
sp->exp1->args[0] = makeexpr_concat(sp->exp1->args[0],
makeexpr_string("%*[^\n]"), 0);
spafter = makestmt_seq(makestmt_call(makegetchar(fex)), spafter);
}
spbase = makestmt_seq(spbase, fixscanf(sp, fex));
}
spbase = makestmt_seq(spbase, spafter);
if (isreadln)
spbase = makestmt_seq(spbase, skipeoln(fex));
return spbase;
}
Static Stmt *handleread_bin(fex, var)
Expr *fex, *var;
{
Type *basetype;
Stmt *sp;
Expr *ex, *tvardef = NULL;
sp = NULL;
basetype = filebasetype(fex->val.type);
for (;;) {
ex = makeexpr_bicall_4("fread", tp_integer, makeexpr_addr(var),
makeexpr_sizeof(makeexpr_type(basetype), 0),
makeexpr_long(1),
filebasename(copyexpr(fex)));
if (checkeof(fex)) {
ex = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
makeexpr_name(endoffilename, tp_int));
}
sp = makestmt_seq(sp, makestmt_call(ex));
if (curtok == TOK_COMMA) {
gettok();
var = p_expr(NULL);
} else
break;
}
freeexpr(tvardef);
return sp;
}
Static Stmt *proc_read()
{
Expr *fex, *ex;
Stmt *sp;
if (!skipopenparen())
return NULL;
ex = p_expr(NULL);
if (isfiletype(ex->val.type, -1) && wneedtok(TOK_COMMA)) {
fex = ex;
ex = p_expr(NULL);
} else {
fex = makeexpr_var(mp_input);
}
if (fex->val.type == tp_text || fex->val.type == tp_bigtext)
sp = handleread_text(fex, ex, 0);
else
sp = handleread_bin(fex, ex);
skipcloseparen();
return wrapopencheck(sp, fex);
}
Static Stmt *proc_readdir()
{
Expr *fex, *ex;
Stmt *sp;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
ex = p_expr(tp_integer);
sp = doseek(fex, ex);
if (!skipopenparen())
return sp;
sp = makestmt_seq(sp, handleread_bin(fex, p_expr(NULL)));
skipcloseparen();
return wrapopencheck(sp, fex);
}
Static Stmt *proc_readln()
{
Expr *fex, *ex;
Stmt *sp;
if (curtok != TOK_LPAR) {
fex = makeexpr_var(mp_input);
return wrapopencheck(skipeoln(copyexpr(fex)), fex);
} else {
gettok();
ex = p_expr(NULL);
if (isfiletype(ex->val.type, -1)) {
fex = ex;
if (curtok == TOK_RPAR || !wneedtok(TOK_COMMA)) {
skippasttotoken(TOK_RPAR, TOK_SEMI);
return wrapopencheck(skipeoln(copyexpr(fex)), fex);
} else {
ex = p_expr(NULL);
}
} else {
fex = makeexpr_var(mp_input);
}
sp = handleread_text(fex, ex, 1);
skipcloseparen();
}
return wrapopencheck(sp, fex);
}
Static Stmt *proc_readv()
{
Expr *vex;
Stmt *sp;
if (!skipopenparen())
return NULL;
vex = p_expr(tp_str255);
if (!skipcomma())
return NULL;
sp = handleread_text(vex, NULL, 0);
skipcloseparen();
return sp;
}
Static Stmt *proc_strread()
{
Expr *vex, *exi, *exj, *exjj, *ex;
Stmt *sp, *sp2;
Meaning *tvar, *jvar;
if (!skipopenparen())
return NULL;
vex = p_expr(tp_str255);
if (vex->kind != EK_VAR) {
tvar = makestmttempvar(tp_str255, name_STRING);
sp = makestmt_assign(makeexpr_var(tvar), vex);
vex = makeexpr_var(tvar);
} else
sp = NULL;
if (!skipcomma())
return NULL;
exi = p_expr(tp_integer);
if (!skipcomma())
return NULL;
exj = p_expr(tp_integer);
if (!skipcomma())
return NULL;
if (exprspeed(exi) >= 5 || !nosideeffects(exi, 0)) {
sp = makestmt_seq(sp, makestmt_assign(copyexpr(exj), exi));
exi = copyexpr(exj);
}
if (fullstrread != 0 &&
((ex = singlevar(exj)) == NULL || exproccurs(exi, ex))) {
jvar = makestmttempvar(exj->val.type, name_TEMP);
exjj = makeexpr_var(jvar);
} else {
exjj = copyexpr(exj);
jvar = (exj->kind == EK_VAR) ? (Meaning *)exj->val.i : NULL;
}
sp2 = handleread_text(bumpstring(copyexpr(vex),
copyexpr(exi), 1),
exjj, 0);
sp = makestmt_seq(sp, sp2);
skipcloseparen();
if (fullstrread == 0) {
sp = makestmt_seq(sp, makestmt_assign(exj,
makeexpr_plus(makeexpr_bicall_1("strlen", tp_int,
vex),
makeexpr_long(1))));
freeexpr(exjj);
freeexpr(exi);
} else {
sp = makestmt_seq(sp, makestmt_assign(exj,
makeexpr_plus(exjj, exi)));
if (fullstrread == 2)
note("STRREAD was used [197]");
freeexpr(vex);
}
return mixassignments(sp, jvar);
}
Static Expr *func_random()
{
Expr *ex;
if (curtok == TOK_LPAR) {
gettok();
ex = p_expr(tp_integer);
skipcloseparen();
return makeexpr_bicall_1(randintname, tp_integer, makeexpr_arglong(ex, 1));
} else {
return makeexpr_bicall_0(randrealname, tp_longreal);
}
}
Static Stmt *proc_randomize()
{
if (*randomizename)
return makestmt_call(makeexpr_bicall_0(randomizename, tp_void));
else
return NULL;
}
Static Expr *func_round(ex)
Expr *ex;
{
Meaning *tvar;
ex = grabarg(ex, 0);
if (ex->val.type->kind != TK_REAL)
return ex;
if (*roundname) {
if (*roundname != '*' || (exprspeed(ex) < 5 && nosideeffects(ex, 0))) {
return makeexpr_bicall_1(roundname, tp_integer, ex);
} else {
tvar = makestmttempvar(tp_longreal, name_TEMP);
return makeexpr_comma(makeexpr_assign(makeexpr_var(tvar), ex),
makeexpr_bicall_1(roundname, tp_integer, makeexpr_var(tvar)));
}
} else {
return makeexpr_actcast(makeexpr_bicall_1("floor", tp_longreal,
makeexpr_plus(ex, makeexpr_real("0.5"))),
tp_integer);
}
}
Static Stmt *proc_unpack()
{
Expr *exs, *exd, *exi, *mins;
Meaning *tvar;
Stmt *sp;
if (!skipopenparen())
return NULL;
exs = p_expr(NULL);
if (!skipcomma())
return NULL;
exd = p_expr(NULL);
if (!skipcomma())
return NULL;
exi = p_ord_expr();
skipcloseparen();
if (exd->val.type->kind != TK_ARRAY ||
(exs->val.type->kind != TK_ARRAY &&
exs->val.type->kind != TK_SMALLARRAY)) {
warning("Bad argument types for PACK/UNPACK [325]");
return makestmt_call(makeexpr_bicall_3("unpack", tp_void,
exs, exd, exi));
}
if (exs->val.type->smax || exd->val.type->smax) {
tvar = makestmttempvar(exs->val.type->indextype, name_TEMP);
sp = makestmt(SK_FOR);
if (exs->val.type->smin)
mins = exs->val.type->smin;
else
mins = exs->val.type->indextype->smin;
sp->exp1 = makeexpr_assign(makeexpr_var(tvar),
copyexpr(mins));
sp->exp2 = makeexpr_rel(EK_LE, makeexpr_var(tvar),
copyexpr(exs->val.type->indextype->smax));
sp->exp3 = makeexpr_assign(makeexpr_var(tvar),
makeexpr_plus(makeexpr_var(tvar),
makeexpr_long(1)));
exi = makeexpr_minus(exi, copyexpr(mins));
sp->stm1 = makestmt_assign(p_index(exd,
makeexpr_plus(makeexpr_var(tvar),
exi)),
p_index(exs, makeexpr_var(tvar)));
return sp;
} else {
exi = gentle_cast(exi, exs->val.type->indextype);
return makestmt_call(makeexpr_bicall_3("memcpy", exd->val.type,
exd,
makeexpr_addr(p_index(exs, exi)),
makeexpr_sizeof(copyexpr(exd), 0)));
}
}
Static Expr *func_uround(ex)
Expr *ex;
{
ex = grabarg(ex, 0);
if (ex->val.type->kind != TK_REAL)
return ex;
return makeexpr_actcast(makeexpr_bicall_1("floor", tp_longreal,
makeexpr_plus(ex, makeexpr_real("0.5"))),
tp_unsigned);
}
Static Expr *func_scan()
{
Expr *ex, *ex2, *ex3;
char *name;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (!skipcomma())
return NULL;
if (curtok == TOK_EQ)
name = "P_scaneq";
else
name = "P_scanne";
gettok();
ex2 = p_expr(tp_char);
if (!skipcomma())
return NULL;
ex3 = p_expr(tp_str255);
skipcloseparen();
return makeexpr_bicall_3(name, tp_int,
makeexpr_arglong(ex, 0),
makeexpr_charcast(ex2), ex3);
}
Static Expr *func_scaneq(ex)
Expr *ex;
{
return makeexpr_bicall_3("P_scaneq", tp_int,
makeexpr_arglong(ex->args[0], 0),
makeexpr_charcast(ex->args[1]),
ex->args[2]);
}
Static Expr *func_scanne(ex)
Expr *ex;
{
return makeexpr_bicall_3("P_scanne", tp_int,
makeexpr_arglong(ex->args[0], 0),
makeexpr_charcast(ex->args[1]),
ex->args[2]);
}
Static Stmt *proc_seek()
{
Expr *fex, *ex;
Stmt *sp;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
ex = p_expr(tp_integer);
skipcloseparen();
sp = wrapopencheck(doseek(fex, ex), copyexpr(fex));
if (*setupbufname && fileisbuffered(fex, 1))
sp = makestmt_seq(sp,
makestmt_call(
makeexpr_bicall_2(setupbufname, tp_void,
filebasename(fex),
makeexpr_type(filebasetype(fex->val.type)))));
else
freeexpr(fex);
return sp;
}
Static Expr *func_seekeof()
{
Expr *ex;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_input);
if (*skipspacename)
ex = makeexpr_bicall_1(skipspacename, tp_text, filebasename(ex));
else
note("SEEKEOF was used [198]");
return iofunc(ex, 0);
}
Static Expr *func_seekeoln()
{
Expr *ex;
if (curtok == TOK_LPAR)
ex = p_parexpr(tp_text);
else
ex = makeexpr_var(mp_input);
if (*skipspacename)
ex = makeexpr_bicall_1(skipspacename, tp_text, filebasename(ex));
else
note("SEEKEOLN was used [199]");
return iofunc(ex, 1);
}
Static Stmt *proc_setstrlen()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_str255);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_integer);
skipcloseparen();
return makestmt_assign(makeexpr_bicall_1("strlen", tp_int, ex),
ex2);
}
Static Stmt *proc_settextbuf()
{
Expr *fex, *bex, *sex;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
bex = p_expr(NULL);
if (curtok == TOK_COMMA) {
gettok();
sex = p_expr(tp_integer);
} else
sex = makeexpr_sizeof(copyexpr(bex), 0);
skipcloseparen();
note("Make sure setvbuf() call occurs when file is open [200]");
return makestmt_call(makeexpr_bicall_4("setvbuf", tp_void,
filebasename(fex),
makeexpr_addr(bex),
makeexpr_name("_IOFBF", tp_integer),
sex));
}
Static Expr *func_sin(ex)
Expr *ex;
{
return makeexpr_bicall_1("sin", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_sinh(ex)
Expr *ex;
{
return makeexpr_bicall_1("sinh", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_sizeof()
{
Expr *ex;
Type *type;
char *name, vbuf[1000];
int lpar;
lpar = (curtok == TOK_LPAR);
if (lpar)
gettok();
if (curtok == TOK_IDENT && curtokmeaning && curtokmeaning->kind == MK_TYPE) {
ex = makeexpr_type(curtokmeaning->type);
gettok();
} else
ex = p_expr(NULL);
type = ex->val.type;
parse_special_variant(type, vbuf);
if (lpar)
skipcloseparen();
name = find_special_variant(vbuf, "SpecialSizeOf", specialsizeofs, 1);
if (name) {
freeexpr(ex);
return pc_expr_str(name);
} else
return makeexpr_sizeof(ex, 0);
}
Static Expr *func_statusv()
{
return makeexpr_name(name_IORESULT, tp_integer);
}
Static Expr *func_str_hp(ex)
Expr *ex;
{
return makeexpr_addr(makeexpr_substring(ex->args[0], ex->args[1],
ex->args[2], ex->args[3]));
}
Static Stmt *proc_strappend()
{
Expr *ex, *ex2;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_str255);
if (!skipcomma())
return NULL;
ex2 = p_expr(tp_str255);
skipcloseparen();
return makestmt_assign(ex, makeexpr_concat(copyexpr(ex), ex2, 0));
}
Static Stmt *proc_strdelete()
{
Meaning *tvar = NULL, *tvari;
Expr *ex, *ex2, *ex3, *ex4, *exi, *exn;
Stmt *sp;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_str255);
if (!skipcomma())
return NULL;
exi = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
exn = p_expr(tp_integer);
} else
exn = makeexpr_long(1);
skipcloseparen();
if (exprspeed(exi) < 5 && nosideeffects(exi, 0))
sp = NULL;
else {
tvari = makestmttempvar(tp_int, name_TEMP);
sp = makestmt_assign(makeexpr_var(tvari), exi);
exi = makeexpr_var(tvari);
}
ex3 = bumpstring(copyexpr(ex), copyexpr(exi), 1);
ex4 = bumpstring(copyexpr(ex), makeexpr_plus(exi, exn), 1);
if (strcpyleft) {
ex2 = ex3;
} else {
tvar = makestmttempvar(tp_str255, name_STRING);
ex2 = makeexpr_var(tvar);
}
sp = makestmt_seq(sp, makestmt_assign(ex2, ex4));
if (!strcpyleft)
sp = makestmt_seq(sp, makestmt_assign(ex3, makeexpr_var(tvar)));
return sp;
}
Static Stmt *proc_strinsert()
{
Meaning *tvari;
Expr *exs, *exd, *exi;
Stmt *sp;
if (!skipopenparen())
return NULL;
exs = p_expr(tp_str255);
if (!skipcomma())
return NULL;
exd = p_expr(tp_str255);
if (!skipcomma())
return NULL;
exi = p_expr(tp_integer);
skipcloseparen();
#if 0
if (checkconst(exi, 1)) {
freeexpr(exi);
return makestmt_assign(exd,
makeexpr_concat(exs, copyexpr(exd)));
}
#endif
if (exprspeed(exi) < 5 && nosideeffects(exi, 0))
sp = NULL;
else {
tvari = makestmttempvar(tp_int, name_TEMP);
sp = makestmt_assign(makeexpr_var(tvari), exi);
exi = makeexpr_var(tvari);
}
exd = bumpstring(exd, exi, 1);
sp = makestmt_seq(sp, makestmt_assign(exd,
makeexpr_concat(exs, copyexpr(exd), 0)));
return sp;
}
Static Stmt *proc_strmove()
{
Expr *exlen, *exs, *exsi, *exd, *exdi;
if (!skipopenparen())
return NULL;
exlen = p_expr(tp_integer);
if (!skipcomma())
return NULL;
exs = p_expr(tp_str255);
if (!skipcomma())
return NULL;
exsi = p_expr(tp_integer);
if (!skipcomma())
return NULL;
exd = p_expr(tp_str255);
if (!skipcomma())
return NULL;
exdi = p_expr(tp_integer);
skipcloseparen();
exsi = makeexpr_arglong(exsi, 0);
exdi = makeexpr_arglong(exdi, 0);
return makestmt_call(makeexpr_bicall_5(strmovename, tp_str255,
exlen, exs, exsi, exd, exdi));
}
Static Expr *func_strlen(ex)
Expr *ex;
{
return makeexpr_bicall_1("strlen", tp_int, grabarg(ex, 0));
}
Static Expr *func_strltrim(ex)
Expr *ex;
{
return makeexpr_assign(makeexpr_hat(ex->args[0], 0),
makeexpr_bicall_1(strltrimname, tp_str255, ex->args[1]));
}
Static Expr *func_strmax(ex)
Expr *ex;
{
return strmax_func(grabarg(ex, 0));
}
Static Expr *func_strpos(ex)
Expr *ex;
{
char *cp;
if (!switch_strpos)
swapexprs(ex->args[0], ex->args[1]);
cp = strposname;
if (!*cp) {
note("STRPOS function used [201]");
cp = "STRPOS";
}
return makeexpr_bicall_3(cp, tp_int,
ex->args[0],
ex->args[1],
makeexpr_long(1));
}
Static Expr *func_strrpt(ex)
Expr *ex;
{
if (ex->args[1]->kind == EK_CONST &&
ex->args[1]->val.i == 1 && ex->args[1]->val.s[0] == ' ') {
return makeexpr_bicall_4("sprintf", tp_strptr, ex->args[0],
makeexpr_string("%*s"),
makeexpr_longcast(ex->args[2], 0),
makeexpr_string(""));
} else
return makeexpr_bicall_3(strrptname, tp_strptr, ex->args[0], ex->args[1],
makeexpr_arglong(ex->args[2], 0));
}
Static Expr *func_strrtrim(ex)
Expr *ex;
{
return makeexpr_bicall_1(strrtrimname, tp_strptr,
makeexpr_assign(makeexpr_hat(ex->args[0], 0),
ex->args[1]));
}
Static Expr *func_succ()
{
Expr *ex;
if (wneedtok(TOK_LPAR)) {
ex = p_ord_expr();
skipcloseparen();
} else
ex = p_ord_expr();
#if 1
ex = makeexpr_inc(ex, makeexpr_long(1));
#else
ex = makeexpr_cast(makeexpr_plus(ex, makeexpr_long(1)), ex->val.type);
#endif
return ex;
}
Static Expr *func_sqr()
{
return makeexpr_sqr(p_parexpr(tp_integer), 0);
}
Static Expr *func_sqrt(ex)
Expr *ex;
{
return makeexpr_bicall_1("sqrt", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_swap(ex)
Expr *ex;
{
char *cp;
ex = grabarg(ex, 0);
cp = swapname;
if (!*cp) {
note("SWAP function was used [202]");
cp = "SWAP";
}
return makeexpr_bicall_1(swapname, tp_int, ex);
}
Static Expr *func_tan(ex)
Expr *ex;
{
return makeexpr_bicall_1("tan", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_tanh(ex)
Expr *ex;
{
return makeexpr_bicall_1("tanh", tp_longreal, grabarg(ex, 0));
}
Static Expr *func_trunc(ex)
Expr *ex;
{
return makeexpr_actcast(grabarg(ex, 0), tp_integer);
}
Static Expr *func_utrunc(ex)
Expr *ex;
{
return makeexpr_actcast(grabarg(ex, 0), tp_unsigned);
}
Static Expr *func_uand()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_unsigned);
if (skipcomma()) {
ex = makeexpr_bin(EK_BAND, ex->val.type, ex, p_expr(tp_unsigned));
skipcloseparen();
}
return ex;
}
Static Expr *func_udec()
{
return handle_vax_hex(NULL, "u", 0);
}
Static Expr *func_unot()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_unsigned);
ex = makeexpr_un(EK_BNOT, ex->val.type, ex);
skipcloseparen();
return ex;
}
Static Expr *func_uor()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_unsigned);
if (skipcomma()) {
ex = makeexpr_bin(EK_BOR, ex->val.type, ex, p_expr(tp_unsigned));
skipcloseparen();
}
return ex;
}
Static Expr *func_upcase(ex)
Expr *ex;
{
return makeexpr_bicall_1("toupper", tp_char, grabarg(ex, 0));
}
Static Expr *func_upper()
{
Expr *ex;
Value val;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_integer);
if (curtok == TOK_COMMA) {
gettok();
val = p_constant(tp_integer);
if (!val.type || val.i != 1)
note("UPPER(v,n) not supported for n>1 [190]");
}
skipcloseparen();
return copyexpr(ex->val.type->indextype->smax);
}
Static Expr *func_uxor()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_unsigned);
if (skipcomma()) {
ex = makeexpr_bin(EK_BXOR, ex->val.type, ex, p_expr(tp_unsigned));
skipcloseparen();
}
return ex;
}
Static Expr *func_val_modula()
{
Expr *ex;
Type *tp;
if (!skipopenparen())
return NULL;
tp = p_type(NULL);
if (!skipcomma())
return NULL;
ex = p_expr(tp);
skipcloseparen();
return pascaltypecast(tp, ex);
}
Static Stmt *proc_val_turbo()
{
Expr *ex, *vex, *code, *fmt;
if (!skipopenparen())
return NULL;
ex = gentle_cast(p_expr(tp_str255), tp_str255);
if (!skipcomma())
return NULL;
vex = p_expr(NULL);
if (curtok == TOK_COMMA) {
gettok();
code = gentle_cast(p_expr(tp_integer), tp_integer);
} else
code = NULL;
skipcloseparen();
if (vex->val.type->kind == TK_REAL)
fmt = makeexpr_string("%lg");
else if (exprlongness(vex) > 0)
fmt = makeexpr_string("%ld");
else
fmt = makeexpr_string("%d");
ex = makeexpr_bicall_3("sscanf", tp_int,
ex, fmt, makeexpr_addr(vex));
if (code) {
ex = makeexpr_rel(EK_EQ, ex, makeexpr_long(0));
return makestmt_assign(code, makeexpr_ord(ex));
} else
return makestmt_call(ex);
}
Static Expr *writestrelement(ex, wid, vex, code, needboth)
Expr *ex, *wid, *vex;
int code, needboth;
{
if (formatstrings && needboth) {
return makeexpr_bicall_5("sprintf", tp_str255, vex,
makeexpr_string(format_d("%%*.*%c", code)),
copyexpr(wid),
wid,
ex);
} else {
return makeexpr_bicall_4("sprintf", tp_str255, vex,
makeexpr_string(format_d("%%*%c", code)),
wid,
ex);
}
}
Static char *makeenumnames(tp)
Type *tp;
{
Strlist *sp;
char *name;
Meaning *mp;
int saveindent;
for (sp = enumnames; sp && sp->value != (long)tp; sp = sp->next) ;
if (!sp) {
if (tp->meaning)
name = format_s(name_ENUM, tp->meaning->name);
else
name = format_s(name_ENUM, format_d("_%d", ++enumnamecount));
sp = strlist_insert(&enumnames, name);
sp->value = (long)tp;
outsection(2);
output(format_s("static %s *", charname));
output(sp->s);
output("[] = {\n");
saveindent = outindent;
moreindent(tabsize);
moreindent(structinitindent);
for (mp = tp->fbase; mp; mp = mp->xnext) {
output(makeCstring(mp->sym->name, strlen(mp->sym->name)));
if (mp->xnext)
output(",\002 ");
}
outindent = saveindent;
output("\n} ;\n");
outsection(2);
}
return sp->s;
}
/* This function must return a "tempsprintf" */
Expr *writeelement(ex, wid, prec, base)
Expr *ex, *wid, *prec;
int base;
{
Expr *vex, *ex1, *ex2;
Meaning *tvar;
char *fmtcode;
Type *type;
ex = makeexpr_charcast(ex);
if (ex->val.type->kind == TK_POINTER) {
ex = makeexpr_hat(ex, 0); /* convert char *'s to strings */
intwarning("writeelement", "got a char * instead of a string [214]");
}
if ((ex->val.type->kind == TK_STRING && !wid) ||
(ord_type(ex->val.type)->kind == TK_CHAR && (!wid || checkconst(wid, 1)))) {
return makeexpr_sprintfify(ex);
}
tvar = makestmttempvar(tp_str255, name_STRING);
vex = makeexpr_var(tvar);
if (wid)
wid = makeexpr_longcast(wid, 0);
if (prec)
prec = makeexpr_longcast(prec, 0);
#if 0
if (wid && (wid->kind == EK_CONST && wid->val.i < 0 ||
checkconst(wid, -1))) {
freeexpr(wid); /* P-system uses write(x:-1) to mean write(x) */
wid = NULL;
}
if (prec && (prec->kind == EK_CONST && prec->val.i < 0 ||
checkconst(prec, -1))) {
freeexpr(prec);
prec = NULL;
}
#endif
switch (ord_type(ex->val.type)->kind) {
case TK_INTEGER:
if (!wid) {
if (integerwidth < 0)
integerwidth = (which_lang == LANG_TURBO) ? 1 : 12;
wid = makeexpr_long(integerwidth);
}
type = findbasetype(ex->val.type, ODECL_NOPRES);
if (base == 16)
fmtcode = "x";
else if (base == 8)
fmtcode = "o";
else if ((possiblesigns(wid) & (1|4)) == 1) {
wid = makeexpr_neg(wid);
fmtcode = "x";
} else if (type == tp_unsigned ||
type == tp_uint ||
(type == tp_ushort && sizeof_int < 32))
fmtcode = "u";
else
fmtcode = "d";
ex = makeexpr_forcelongness(ex);
if (checkconst(wid, 0) || checkconst(wid, 1)) {
ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
makeexpr_string(format_ss("%%%s%s",
(exprlongness(ex) > 0) ? "l" : "",
fmtcode)),
ex);
} else {
ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
makeexpr_string(format_ss("%%*%s%s",
(exprlongness(ex) > 0) ? "l" : "",
fmtcode)),
wid,
ex);
}
break;
case TK_CHAR:
ex = writestrelement(ex, wid, vex, 'c',
(wid->kind != EK_CONST || wid->val.i < 1));
break;
case TK_BOOLEAN:
if (!wid) {
ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
makeexpr_string("%s"),
makeexpr_cond(ex,
makeexpr_string(" TRUE"),
makeexpr_string("FALSE")));
} else if (checkconst(wid, 1)) {
ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
makeexpr_string("%c"),
makeexpr_cond(ex,
makeexpr_char('T'),
makeexpr_char('F')));
} else {
ex = writestrelement(makeexpr_cond(ex,
makeexpr_string("TRUE"),
makeexpr_string("FALSE")),
wid, vex, 's',
(wid->kind != EK_CONST || wid->val.i < 5));
}
break;
case TK_ENUM:
ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
makeexpr_string("%s"),
makeexpr_index(makeexpr_name(makeenumnames(ex->val.type),
tp_strptr),
ex, NULL));
break;
case TK_REAL:
if (!wid)
wid = makeexpr_long(realwidth);
if (prec && (possiblesigns(prec) & (1|4)) != 1) {
ex = makeexpr_bicall_5("sprintf", tp_str255, vex,
makeexpr_string("%*.*f"),
wid,
prec,
ex);
} else {
if (prec)
prec = makeexpr_neg(prec);
else
prec = makeexpr_minus(copyexpr(wid),
makeexpr_long(7));
if (prec->kind == EK_CONST) {
if (prec->val.i <= 0)
prec = makeexpr_long(1);
} else {
prec = makeexpr_bicall_2("P_max", tp_integer, prec,
makeexpr_long(1));
}
if (wid->kind == EK_CONST && wid->val.i > 21) {
ex = makeexpr_bicall_5("sprintf", tp_str255, vex,
makeexpr_string("%*.*E"),
wid,
prec,
ex);
#if 0
} else if (checkconst(wid, 7)) {
ex = makeexpr_bicall_3("sprintf", tp_str255, vex,
makeexpr_string("%E"),
ex);
#endif
} else {
ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
makeexpr_string("% .*E"),
prec,
ex);
}
}
break;
case TK_STRING:
ex = writestrelement(ex, wid, vex, 's', 1);
break;
case TK_ARRAY: /* assume packed array of char */
ord_range_expr(ex->val.type->indextype, &ex1, &ex2);
ex1 = makeexpr_plus(makeexpr_minus(copyexpr(ex2),
copyexpr(ex1)),
makeexpr_long(1));
ex1 = makeexpr_longcast(ex1, 0);
fmtcode = "%.*s";
if (!wid) {
wid = ex1;
} else {
if (isliteralconst(wid, NULL) == 2 &&
isliteralconst(ex1, NULL) == 2) {
if (wid->val.i > ex1->val.i) {
fmtcode = format_ds("%*s%%.*s",
wid->val.i - ex1->val.i, "");
wid = ex1;
}
} else
note("Format for packed-array-of-char will work only if width < length [321]");
}
ex = makeexpr_bicall_4("sprintf", tp_str255, vex,
makeexpr_string(fmtcode),
wid,
makeexpr_addr(ex));
break;
default:
note("Element has wrong type for WRITE statement [196]");
ex = makeexpr_bicall_2("sprintf", tp_str255, vex, makeexpr_string("<meef>"));
break;
}
return ex;
}
Static Stmt *handlewrite_text(fex, ex, iswriteln)
Expr *fex, *ex;
int iswriteln;
{
Expr *print, *wid, *prec;
unsigned char *ucp;
int i, done, base;
print = NULL;
for (;;) {
wid = NULL;
prec = NULL;
base = 10;
if (curtok == TOK_COLON && iswriteln >= 0) {
gettok();
wid = p_expr(tp_integer);
if (curtok == TOK_COLON) {
gettok();
prec = p_expr(tp_integer);
}
}
if (curtok == TOK_IDENT &&
!strcicmp(curtokbuf, "OCT")) {
base = 8;
gettok();
} else if (curtok == TOK_IDENT &&
!strcicmp(curtokbuf, "HEX")) {
base = 16;
gettok();
}
ex = writeelement(ex, wid, prec, base);
print = makeexpr_concat(print, cleansprintf(ex), 1);
if (curtok == TOK_COMMA && iswriteln >= 0) {
gettok();
ex = p_expr(NULL);
} else
break;
}
if (fex->val.type->kind != TK_STRING) { /* not strwrite */
switch (iswriteln) {
case 1:
case -1:
print = makeexpr_concat(print, makeexpr_string("\n"), 1);
break;
case 2:
case -2:
print = makeexpr_concat(print, makeexpr_string("\r"), 1);
break;
}
if (isvar(fex, mp_output)) {
ucp = (unsigned char *)print->args[1]->val.s;
for (i = 0; i < print->args[1]->val.i; i++) {
if (ucp[i] >= 128 && ucp[i] < 144) {
note("WRITE statement contains color/attribute characters [203]");
break;
}
}
}
if ((i = sprintflength(print, 0)) > 0 && print->nargs == 2 && printfonly != 1) {
print = makeexpr_unsprintfify(print);
done = 1;
if (isvar(fex, mp_output)) {
if (i == 1) {
print = makeexpr_bicall_1("putchar", tp_int,
makeexpr_charcast(print));
} else {
if (printfonly == 0) {
if (print->val.s[print->val.i-1] == '\n') {
print->val.s[--(print->val.i)] = 0;
print = makeexpr_bicall_1("puts", tp_int, print);
} else {
print = makeexpr_bicall_2("fputs", tp_int,
print,
copyexpr(fex));
}
} else {
print = makeexpr_sprintfify(print);
done = 0;
}
}
} else {
if (i == 1) {
print = makeexpr_bicall_2("putc", tp_int,
makeexpr_charcast(print),
filebasename(copyexpr(fex)));
} else if (printfonly == 0) {
print = makeexpr_bicall_2("fputs", tp_int,
print,
filebasename(copyexpr(fex)));
} else {
print = makeexpr_sprintfify(print);
done = 0;
}
}
} else
done = 0;
if (!done) {
canceltempvar(istempvar(print->args[0]));
if (checkstring(print->args[1], "%s") && printfonly != 1) {
print = makeexpr_bicall_2("fputs", tp_int,
grabarg(print, 2),
filebasename(copyexpr(fex)));
} else if (checkstring(print->args[1], "%c") && printfonly != 1 &&
!nosideeffects(print->args[2], 0)) {
print = makeexpr_bicall_2("fputc", tp_int,
grabarg(print, 2),
filebasename(copyexpr(fex)));
} else if (isvar(fex, mp_output)) {
if (checkstring(print->args[1], "%s\n") && printfonly != 1) {
print = makeexpr_bicall_1("puts", tp_int, grabarg(print, 2));
} else if (checkstring(print->args[1], "%c") && printfonly != 1) {
print = makeexpr_bicall_1("putchar", tp_int, grabarg(print, 2));
} else {
strchange(&print->val.s, "printf");
delfreearg(&print, 0);
print->val.type = tp_int;
}
} else {
if (checkstring(print->args[1], "%c") && printfonly != 1) {
print = makeexpr_bicall_2("putc", tp_int,
grabarg(print, 2),
filebasename(copyexpr(fex)));
} else {
strchange(&print->val.s, "fprintf");
freeexpr(print->args[0]);
print->args[0] = filebasename(copyexpr(fex));
print->val.type = tp_int;
}
}
}
if (FCheck(checkfilewrite)) {
print = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_GE, print, makeexpr_long(0)),
makeexpr_name(filewriteerrorname, tp_int));
}
}
return makestmt_call(print);
}
Static Stmt *handlewrite_bin(fex, ex)
Expr *fex, *ex;
{
Type *basetype;
Stmt *sp;
Expr *tvardef = NULL;
Meaning *tvar = NULL;
sp = NULL;
basetype = filebasetype(fex->val.type);
for (;;) {
if (!expr_has_address(ex) || ex->val.type != basetype) {
if (!tvar)
tvar = makestmttempvar(basetype, name_TEMP);
if (!tvardef || !exprsame(tvardef, ex, 1)) {
freeexpr(tvardef);
tvardef = copyexpr(ex);
sp = makestmt_seq(sp, makestmt_assign(makeexpr_var(tvar),
ex));
} else
freeexpr(ex);
ex = makeexpr_var(tvar);
}
ex = makeexpr_bicall_4("fwrite", tp_integer, makeexpr_addr(ex),
makeexpr_sizeof(makeexpr_type(basetype), 0),
makeexpr_long(1),
filebasename(copyexpr(fex)));
if (FCheck(checkfilewrite)) {
ex = makeexpr_bicall_2("~SETIO", tp_void,
makeexpr_rel(EK_EQ, ex, makeexpr_long(1)),
makeexpr_name(filewriteerrorname, tp_int));
}
sp = makestmt_seq(sp, makestmt_call(ex));
if (curtok == TOK_COMMA) {
gettok();
ex = p_expr(NULL);
} else
break;
}
freeexpr(tvardef);
return sp;
}
Static Stmt *proc_write()
{
Expr *fex, *ex;
Stmt *sp;
if (!skipopenparen())
return NULL;
ex = p_expr(NULL);
if (isfiletype(ex->val.type, -1) && wneedtok(TOK_COMMA)) {
fex = ex;
ex = p_expr(NULL);
} else {
fex = makeexpr_var(mp_output);
}
if (fex->val.type == tp_text || fex->val.type == tp_bigtext)
sp = handlewrite_text(fex, ex, 0);
else
sp = handlewrite_bin(fex, ex);
skipcloseparen();
return wrapopencheck(sp, fex);
}
Static Stmt *handle_modula_write(fmt)
char *fmt;
{
Expr *ex, *wid;
if (!skipopenparen())
return NULL;
ex = makeexpr_forcelongness(p_expr(NULL));
if (skipcomma())
wid = p_expr(tp_integer);
else
wid = makeexpr_long(1);
if (checkconst(wid, 0) || checkconst(wid, 1))
ex = makeexpr_bicall_2("printf", tp_str255,
makeexpr_string(format_ss("%%%s%s",
(exprlongness(ex) > 0) ? "l" : "",
fmt)),
ex);
else
ex = makeexpr_bicall_3("printf", tp_str255,
makeexpr_string(format_ss("%%*%s%s",
(exprlongness(ex) > 0) ? "l" : "",
fmt)),
makeexpr_arglong(wid, 0),
ex);
skipcloseparen();
return makestmt_call(ex);
}
Static Stmt *proc_writecard()
{
return handle_modula_write("u");
}
Static Stmt *proc_writeint()
{
return handle_modula_write("d");
}
Static Stmt *proc_writehex()
{
return handle_modula_write("x");
}
Static Stmt *proc_writeoct()
{
return handle_modula_write("o");
}
Static Stmt *proc_writereal()
{
return handle_modula_write("f");
}
Static Stmt *proc_writedir()
{
Expr *fex, *ex;
Stmt *sp;
if (!skipopenparen())
return NULL;
fex = p_expr(tp_text);
if (!skipcomma())
return NULL;
ex = p_expr(tp_integer);
sp = doseek(fex, ex);
if (!skipcomma())
return sp;
sp = makestmt_seq(sp, handlewrite_bin(fex, p_expr(NULL)));
skipcloseparen();
return wrapopencheck(sp, fex);
}
Static Stmt *handlewriteln(iswriteln)
int iswriteln;
{
Expr *fex, *ex;
Stmt *sp;
Meaning *deffile = mp_output;
sp = NULL;
if (iswriteln == 3) {
iswriteln = 1;
if (messagestderr)
deffile = mp_stderr;
}
if (curtok != TOK_LPAR) {
fex = makeexpr_var(deffile);
if (iswriteln)
sp = handlewrite_text(fex, makeexpr_string(""), -iswriteln);
} else {
gettok();
ex = p_expr(NULL);
if (isfiletype(ex->val.type, -1)) {
fex = ex;
if (curtok == TOK_RPAR || !wneedtok(TOK_COMMA)) {
if (iswriteln)
ex = makeexpr_string("");
else
ex = NULL;
} else {
ex = p_expr(NULL);
}
} else {
fex = makeexpr_var(deffile);
}
if (ex)
sp = handlewrite_text(fex, ex, iswriteln);
skipcloseparen();
}
if (iswriteln == 0) {
sp = makestmt_seq(sp, makestmt_call(makeexpr_bicall_1("fflush", tp_void,
filebasename(copyexpr(fex)))));
}
return wrapopencheck(sp, fex);
}
Static Stmt *proc_overprint()
{
return handlewriteln(2);
}
Static Stmt *proc_prompt()
{
return handlewriteln(0);
}
Static Stmt *proc_writeln()
{
return handlewriteln(1);
}
Static Stmt *proc_message()
{
return handlewriteln(3);
}
Static Stmt *proc_writev()
{
Expr *vex, *ex;
Stmt *sp;
Meaning *mp;
if (!skipopenparen())
return NULL;
vex = p_expr(tp_str255);
if (curtok == TOK_RPAR) {
gettok();
return makestmt_assign(vex, makeexpr_string(""));
}
if (!skipcomma())
return NULL;
sp = handlewrite_text(vex, p_expr(NULL), 0);
skipcloseparen();
ex = sp->exp1;
if (ex->kind == EK_BICALL && !strcmp(ex->val.s, "sprintf") &&
(mp = istempvar(ex->args[0])) != NULL) {
canceltempvar(mp);
ex->args[0] = vex;
} else
sp->exp1 = makeexpr_assign(vex, ex);
return sp;
}
Static Stmt *proc_strwrite(mp_x, spbase)
Meaning *mp_x;
Stmt *spbase;
{
Expr *vex, *exi, *exj, *ex;
Stmt *sp;
Meaning *mp;
if (!skipopenparen())
return NULL;
vex = p_expr(tp_str255);
if (!skipcomma())
return NULL;
exi = p_expr(tp_integer);
if (!skipcomma())
return NULL;
exj = p_expr(tp_integer);
if (!skipcomma())
return NULL;
sp = handlewrite_text(vex, p_expr(NULL), 0);
skipcloseparen();
ex = sp->exp1;
FREE(sp);
if (checkconst(exi, 1)) {
sp = spbase;
while (sp && sp->next)
sp = sp->next;
if (sp && sp->kind == SK_ASSIGN && sp->exp1->kind == EK_ASSIGN &&
(sp->exp1->args[0]->kind == EK_HAT ||
sp->exp1->args[0]->kind == EK_INDEX) &&
exprsame(sp->exp1->args[0]->args[0], vex, 1) &&
checkconst(sp->exp1->args[1], 0)) {
nukestmt(sp); /* remove preceding bogus setstrlen */
}
}
if (ex->kind == EK_BICALL && !strcmp(ex->val.s, "sprintf") &&
(mp = istempvar(ex->args[0])) != NULL) {
canceltempvar(mp);
ex->args[0] = bumpstring(copyexpr(vex), exi, 1);
sp = makestmt_call(ex);
} else
sp = makestmt_assign(bumpstring(copyexpr(vex), exi, 1), ex);
if (fullstrwrite != 0) {
sp = makestmt_seq(sp, makestmt_assign(exj,
makeexpr_plus(makeexpr_bicall_1("strlen", tp_int, vex),
makeexpr_long(1))));
if (fullstrwrite == 1)
note("FullStrWrite=1 not yet supported [204]");
if (fullstrwrite == 2)
note("STRWRITE was used [205]");
} else {
freeexpr(vex);
}
return mixassignments(sp, NULL);
}
Static Stmt *proc_str_turbo()
{
Expr *ex, *wid, *prec;
if (!skipopenparen())
return NULL;
ex = p_expr(NULL);
wid = NULL;
prec = NULL;
if (curtok == TOK_COLON) {
gettok();
wid = p_expr(tp_integer);
if (curtok == TOK_COLON) {
gettok();
prec = p_expr(tp_integer);
}
}
ex = writeelement(ex, wid, prec, 10);
if (!skipcomma())
return NULL;
wid = p_expr(tp_str255);
skipcloseparen();
return makestmt_assign(wid, ex);
}
Static Stmt *proc_time()
{
Expr *ex;
if (!skipopenparen())
return NULL;
ex = p_expr(tp_str255);
skipcloseparen();
return makestmt_call(makeexpr_bicall_1("VAXtime", tp_integer, ex));
}
Static Expr *func_xor()
{
Expr *ex, *ex2;
Type *type;
Meaning *tvar;
if (!skipopenparen())
return NULL;
ex = p_expr(NULL);
if (!skipcomma())
return ex;
ex2 = p_expr(ex->val.type);
skipcloseparen();
if (ex->val.type->kind != TK_SET &&
ex->val.type->kind != TK_SMALLSET) {
ex = makeexpr_bin(EK_BXOR, ex->val.type, ex, ex2);
} else {
type = mixsets(&ex, &ex2);
tvar = makestmttempvar(type, name_SET);
ex = makeexpr_bicall_3(setxorname, type,
makeexpr_var(tvar),
ex, ex2);
}
return ex;
}
void decl_builtins()
{
makespecialfunc( "ABS", func_abs);
makespecialfunc( "ADDR", func_addr);
if (!modula2)
makespecialfunc( "ADDRESS", func_addr);
makespecialfunc( "ADDTOPOINTER", func_addtopointer);
makespecialfunc( "ADR", func_addr);
makespecialfunc( "ASL", func_lsl);
makespecialfunc( "ASR", func_asr);
makespecialfunc( "BADDRESS", func_iaddress);
makespecialfunc( "BAND", func_uand);
makespecialfunc( "BIN", func_bin);
makespecialfunc( "BITNEXT", func_bitnext);
makespecialfunc( "BITSIZE", func_bitsize);
makespecialfunc( "BITSIZEOF", func_bitsize);
mp_blockread_ucsd =
makespecialfunc( "BLOCKREAD", func_blockread);
mp_blockwrite_ucsd =
makespecialfunc( "BLOCKWRITE", func_blockwrite);
makespecialfunc( "BNOT", func_unot);
makespecialfunc( "BOR", func_uor);
makespecialfunc( "BSL", func_bsl);
makespecialfunc( "BSR", func_bsr);
makespecialfunc( "BTST", func_btst);
makespecialfunc( "BXOR", func_uxor);
makespecialfunc( "BYTEREAD", func_byteread);
makespecialfunc( "BYTEWRITE", func_bytewrite);
makespecialfunc( "BYTE_OFFSET", func_byte_offset);
makespecialfunc( "CHR", func_chr);
makespecialfunc( "CONCAT", func_concat);
makespecialfunc( "DBLE", func_float);
mp_dec_dec =
makespecialfunc( "DEC", func_dec);
makespecialfunc( "EOF", func_eof);
makespecialfunc( "EOLN", func_eoln);
makespecialfunc( "FCALL", func_fcall);
makespecialfunc( "FILEPOS", func_filepos);
makespecialfunc( "FILESIZE", func_filesize);
makespecialfunc( "FLOAT", func_float);
makespecialfunc( "HEX", func_hex);
makespecialfunc( "HI", func_hi);
makespecialfunc( "HIWORD", func_hiword);
makespecialfunc( "HIWRD", func_hiword);
makespecialfunc( "HIGH", func_high);
makespecialfunc( "IADDRESS", func_iaddress);
makespecialfunc( "INT", func_int);
makespecialfunc( "LAND", func_uand);
makespecialfunc( "LNOT", func_unot);
makespecialfunc( "LO", func_lo);
makespecialfunc( "LOOPHOLE", func_loophole);
makespecialfunc( "LOR", func_uor);
makespecialfunc( "LOWER", func_lower);
makespecialfunc( "LOWORD", func_loword);
makespecialfunc( "LOWRD", func_loword);
makespecialfunc( "LSL", func_lsl);
makespecialfunc( "LSR", func_lsr);
makespecialfunc( "MAX", func_max);
makespecialfunc( "MAXPOS", func_maxpos);
makespecialfunc( "MIN", func_min);
makespecialfunc( "NEXT", func_sizeof);
makespecialfunc( "OCT", func_oct);
makespecialfunc( "ORD", func_ord);
makespecialfunc( "ORD4", func_ord4);
makespecialfunc( "PI", func_pi);
makespecialfunc( "POSITION", func_position);
makespecialfunc( "PRED", func_pred);
makespecialfunc( "QUAD", func_float);
makespecialfunc( "RANDOM", func_random);
makespecialfunc( "REF", func_addr);
makespecialfunc( "SCAN", func_scan);
makespecialfunc( "SEEKEOF", func_seekeof);
makespecialfunc( "SEEKEOLN", func_seekeoln);
makespecialfunc( "SIZE", func_sizeof);
makespecialfunc( "SIZEOF", func_sizeof);
makespecialfunc( "SNGL", func_sngl);
makespecialfunc( "SQR", func_sqr);
makespecialfunc( "STATUSV", func_statusv);
makespecialfunc( "SUCC", func_succ);
makespecialfunc( "TSIZE", func_sizeof);
makespecialfunc( "UAND", func_uand);
makespecialfunc( "UDEC", func_udec);
makespecialfunc( "UINT", func_uint);
makespecialfunc( "UNOT", func_unot);
makespecialfunc( "UOR", func_uor);
makespecialfunc( "UPPER", func_upper);
makespecialfunc( "UXOR", func_uxor);
mp_val_modula =
makespecialfunc( "VAL", func_val_modula);
makespecialfunc( "WADDRESS", func_iaddress);
makespecialfunc( "XOR", func_xor);
makestandardfunc("ARCTAN", func_arctan);
makestandardfunc("ARCTANH", func_arctanh);
makestandardfunc("BINARY", func_binary);
makestandardfunc("CAP", func_upcase);
makestandardfunc("COPY", func_copy);
makestandardfunc("COS", func_cos);
makestandardfunc("COSH", func_cosh);
makestandardfunc("EXP", func_exp);
makestandardfunc("EXP10", func_pwroften);
makestandardfunc("EXPO", func_expo);
makestandardfunc("FRAC", func_frac);
makestandardfunc("INDEX", func_strpos);
makestandardfunc("LASTPOS", NULL);
makestandardfunc("LINEPOS", NULL);
makestandardfunc("LENGTH", func_strlen);
makestandardfunc("LN", func_ln);
makestandardfunc("LOG", func_log);
makestandardfunc("LOG10", func_log);
makestandardfunc("MAXAVAIL", func_maxavail);
makestandardfunc("MEMAVAIL", func_memavail);
makestandardfunc("OCTAL", func_octal);
makestandardfunc("ODD", func_odd);
makestandardfunc("PAD", func_pad);
makestandardfunc("PARAMCOUNT", func_paramcount);
makestandardfunc("PARAMSTR", func_paramstr);
makestandardfunc("POS", func_pos);
makestandardfunc("PTR", func_ptr);
makestandardfunc("PWROFTEN", func_pwroften);
makestandardfunc("ROUND", func_round);
makestandardfunc("SCANEQ", func_scaneq);
makestandardfunc("SCANNE", func_scanne);
makestandardfunc("SIN", func_sin);
makestandardfunc("SINH", func_sinh);
makestandardfunc("SQRT", func_sqrt);
mp_str_hp =
makestandardfunc("STR", func_str_hp);
makestandardfunc("STRLEN", func_strlen);
makestandardfunc("STRLTRIM", func_strltrim);
makestandardfunc("STRMAX", func_strmax);
makestandardfunc("STRPOS", func_strpos);
makestandardfunc("STRRPT", func_strrpt);
makestandardfunc("STRRTRIM", func_strrtrim);
makestandardfunc("SUBSTR", func_str_hp);
makestandardfunc("SWAP", func_swap);
makestandardfunc("TAN", func_tan);
makestandardfunc("TANH", func_tanh);
makestandardfunc("TRUNC", func_trunc);
makestandardfunc("UPCASE", func_upcase);
makestandardfunc("UROUND", func_uround);
makestandardfunc("UTRUNC", func_utrunc);
makespecialproc( "APPEND", proc_append);
makespecialproc( "ARGV", proc_argv);
makespecialproc( "ASSERT", proc_assert);
makespecialproc( "ASSIGN", proc_assign);
makespecialproc( "BCLR", proc_bclr);
mp_blockread_turbo =
makespecialproc( "BLOCKREAD_TURBO", proc_blockread);
mp_blockwrite_turbo =
makespecialproc( "BLOCKWRITE_TURBO", proc_blockwrite);
makespecialproc( "BREAK", proc_flush);
makespecialproc( "BSET", proc_bset);
makespecialproc( "CALL", proc_call);
makespecialproc( "CLOSE", proc_close);
makespecialproc( "CONNECT", proc_assign);
makespecialproc( "CYCLE", proc_cycle);
makespecialproc( "DATE", proc_date);
mp_dec_turbo =
makespecialproc( "DEC_TURBO", proc_dec);
makespecialproc( "DISPOSE", proc_dispose);
makespecialproc( "ESCAPE", proc_escape);
makespecialproc( "EXCL", proc_excl);
makespecialproc( "EXIT", proc_exit);
makespecialproc( "FILLCHAR", proc_fillchar);
makespecialproc( "FLUSH", proc_flush);
makespecialproc( "GET", proc_get);
makespecialproc( "HALT", proc_escape);
makespecialproc( "INC", proc_inc);
makespecialproc( "INCL", proc_incl);
makespecialproc( "LEAVE", proc_leave);
makespecialproc( "LOCATE", proc_seek);
makespecialproc( "MESSAGE", proc_message);
makespecialproc( "MOVE_FAST", proc_move_fast);
makespecialproc( "MOVE_L_TO_R", proc_move_fast);
makespecialproc( "MOVE_R_TO_L", proc_move_fast);
makespecialproc( "NEW", proc_new);
if (which_lang != LANG_VAX)
makespecialproc( "OPEN", proc_open);
makespecialproc( "OVERPRINT", proc_overprint);
makespecialproc( "PACK", proc_pack);
makespecialproc( "PAGE", proc_page);
makespecialproc( "PUT", proc_put);
makespecialproc( "PROMPT", proc_prompt);
makespecialproc( "RANDOMIZE", proc_randomize);
makespecialproc( "READ", proc_read);
makespecialproc( "READDIR", proc_readdir);
makespecialproc( "READLN", proc_readln);
makespecialproc( "READV", proc_readv);
makespecialproc( "RESET", proc_reset);
makespecialproc( "REWRITE", proc_rewrite);
makespecialproc( "SEEK", proc_seek);
makespecialproc( "SETSTRLEN", proc_setstrlen);
makespecialproc( "SETTEXTBUF", proc_settextbuf);
mp_str_turbo =
makespecialproc( "STR_TURBO", proc_str_turbo);
makespecialproc( "STRAPPEND", proc_strappend);
makespecialproc( "STRDELETE", proc_strdelete);
makespecialproc( "STRINSERT", proc_strinsert);
makespecialproc( "STRMOVE", proc_strmove);
makespecialproc( "STRREAD", proc_strread);
makespecialproc( "STRWRITE", proc_strwrite);
makespecialproc( "TIME", proc_time);
makespecialproc( "UNPACK", proc_unpack);
makespecialproc( "WRITE", proc_write);
makespecialproc( "WRITEDIR", proc_writedir);
makespecialproc( "WRITELN", proc_writeln);
makespecialproc( "WRITEV", proc_writev);
mp_val_turbo =
makespecialproc( "VAL_TURBO", proc_val_turbo);
makestandardproc("DELETE", proc_delete);
makestandardproc("FREEMEM", proc_freemem);
makestandardproc("GETMEM", proc_getmem);
makestandardproc("GOTOXY", proc_gotoxy);
makestandardproc("INSERT", proc_insert);
makestandardproc("MARK", NULL);
makestandardproc("MOVE", proc_move);
makestandardproc("MOVELEFT", proc_move);
makestandardproc("MOVERIGHT", proc_move);
makestandardproc("RELEASE", NULL);
makespecialvar( "MEM", var_mem);
makespecialvar( "MEMW", var_memw);
makespecialvar( "MEML", var_meml);
makespecialvar( "PORT", var_port);
makespecialvar( "PORTW", var_portw);
/* Modula-2 standard I/O procedures (case-sensitive!) */
makespecialproc( "Read", proc_read);
makespecialproc( "ReadCard", proc_read);
makespecialproc( "ReadInt", proc_read);
makespecialproc( "ReadReal", proc_read);
makespecialproc( "ReadString", proc_read);
makespecialproc( "Write", proc_write);
makespecialproc( "WriteCard", proc_writecard);
makespecialproc( "WriteHex", proc_writehex);
makespecialproc( "WriteInt", proc_writeint);
makespecialproc( "WriteOct", proc_writeoct);
makespecialproc( "WriteLn", proc_writeln);
makespecialproc( "WriteReal", proc_writereal);
makespecialproc( "WriteString", proc_write);
}
/* End. */