home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
379a.lha
/
p2c1_13a
/
src
/
src.zoo
/
pexpr3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-14
|
19KB
|
547 lines
/* "p2c", a Pascal to C translator.
Copyright (C) 1989 David Gillespie.
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_PEXPR3_C
#include "trans.h"
Expr *pc_expr()
{
return pc_expr2(0);
}
Expr *pc_expr_str(buf)
char *buf;
{
Strlist *defsl, *sl;
Expr *ex;
defsl = NULL;
sl = strlist_append(&defsl, buf);
C_lex++;
push_input_strlist(defsl, buf);
ex = pc_expr();
if (curtok != TOK_EOF)
warning(format_s("Junk (%s) at end of C expression [306]",
tok_name(curtok)));
pop_input();
C_lex--;
strlist_empty(&defsl);
return ex;
}
/* Simplify an expression */
Expr *fixexpr(ex, env)
Expr *ex;
int env;
{
Expr *ex2, *ex3, **ep;
Type *type, *type2;
Meaning *mp;
char *cp;
char sbuf[5];
int i;
Value val;
if (!ex)
return NULL;
switch (ex->kind) {
case EK_BICALL:
ex2 = fix_bicall(ex, env);
if (ex2) {
ex = ex2;
break;
}
cp = ex->val.s;
if (!strcmp(cp, "strlen")) {
if (ex->args[0]->kind == EK_BICALL &&
!strcmp(ex->args[0]->val.s, "sprintf") &&
sprintf_value == 0) { /* does sprintf return char count? */
ex = grabarg(ex, 0);
strchange(&ex->val.s, "*sprintf");
ex = fixexpr(ex, env);
} else {
ex->args[0] = fixexpr(ex->args[0], ENV_EXPR);
}
} else if (!strcmp(cp, name_SETIO)) {
ex->args[0] = fixexpr(ex->args[0], ENV_BOOL);
} else if (!strcmp(cp, "~~SETIO")) {
ex->args[0] = fixexpr(ex->args[0], ENV_BOOL);
ex = makeexpr_cond(ex->args[0],
makeexpr_long(0),
makeexpr_bicall_1(name_ESCIO, tp_int, ex->args[1]));
} else if (!strcmp(cp, name_CHKIO)) {
ex->args[0] = fixexpr(ex->args[0], ENV_BOOL);
ex->args[2] = fixexpr(ex->args[2], env);
ex->args[3] = fixexpr(ex->args[3], env);
} else if (!strcmp(cp, "~~CHKIO")) {
ex->args[0] = fixexpr(ex->args[0], ENV_BOOL);
ex->args[2] = fixexpr(ex->args[2], env);
ex->args[3] = fixexpr(ex->args[3], env);
ex2 = makeexpr_bicall_1(name_ESCIO, tp_int, ex->args[1]);
if (ord_type(ex->args[3]->val.type)->kind != TK_INTEGER)
ex2 = makeexpr_cast(ex2, ex->args[3]->val.type);
ex = makeexpr_cond(ex->args[0], ex->args[2], ex2);
} else if (!strcmp(cp, "assert")) {
ex->args[0] = fixexpr(ex->args[0], ENV_BOOL);
} else {
for (i = 0; i < ex->nargs; i++)
ex->args[i] = fixexpr(ex->args[i], ENV_EXPR);
ex = cleansprintf(ex);
if (!strcmp(cp, "sprintf")) {
if (checkstring(ex->args[1], "%s")) {
delfreearg(&ex, 1);
strchange(&ex->val.s, "strcpy");
ex = fixexpr(ex, env);
} else if (sprintf_value != 1 && env != ENV_STMT) {
if (*sprintfname) {
strchange(&ex->val.s, format_s("*%s", sprintfname));
} else {
strchange(&ex->val.s, "*sprintf");
ex = makeexpr_comma(ex, copyexpr(ex->args[0]));
}
}
} else if (!strcmp(cp, "strcpy")) {
if (env == ENV_STMT &&
ex->args[1]->kind == EK_BICALL &&
!strcmp(ex->args[1]->val.s, "strcpy") &&
nosideeffects(ex->args[1]->args[0], 1)) {
ex2 = ex->args[1];
ex->args[1] = copyexpr(ex2->args[0]);
ex = makeexpr_comma(ex2, ex);
}
} else if (!strcmp(cp, "memcpy")) {
strchange(&ex->val.s, format_s("*%s", memcpyname));
if (!strcmp(memcpyname, "*bcopy")) {
swapexprs(ex->args[0], ex->args[1]);
if (env != ENV_STMT)
ex = makeexpr_comma(ex, copyexpr(ex->args[1]));
}
} else if (!strcmp(cp, setunionname) &&
(ex3 = singlevar(ex->args[0])) != NULL &&
((i=1, exprsame(ex->args[0], ex->args[i], 0)) ||
(i=2, exprsame(ex->args[0], ex->args[i], 0))) &&
!exproccurs(ex3, ex->args[3-i])) {
ep = &ex->args[3-i];
while ((ex2 = *ep)->kind == EK_BICALL &&
(!strcmp(ex2->val.s, setaddname) ||
!strcmp(ex2->val.s, setaddrangename)))
ep = &ex2->args[0];
if (ex2->kind == EK_BICALL &&
!strcmp(ex2->val.s, setexpandname) &&
checkconst(ex2->args[1], 0) &&
(mp = istempvar(ex2->args[0])) != NULL) {
if (ex2 == ex->args[3-i]) {
ex = grabarg(ex, i);
} else {
freeexpr(ex2);
*ep = ex->args[i];
ex = ex->args[3-i];
}
}
} else if (!strcmp(cp, setdiffname) && *setremname &&
(ex3 = singlevar(ex->args[0])) != NULL &&
exprsame(ex->args[0], ex->args[1], 0) &&
!exproccurs(ex3, ex->args[2])) {
ep = &ex->args[2];
while ((ex2 = *ep)->kind == EK_BICALL &&
!strcmp(ex2->val.s, setaddname))
ep = &ex2->args[0];
if (ex2->kind == EK_BICALL &&
!strcmp(ex2->val.s, setexpandname) &&
checkconst(ex2->args[1], 0) &&
(mp = istempvar(ex2->args[0])) != NULL) {
if (ex2 == ex->args[2]) {
ex = grabarg(ex, 1);
} else {
ex2 = ex->args[2];
while (ex2->kind == EK_BICALL &&
!strcmp(ex2->val.s, setaddname)) {
strchange(&ex2->val.s, setremname);
ex2 = ex2->args[0];
}
freeexpr(ex2);
*ep = ex->args[1];
ex = ex->args[2];
}
}
} else if (!strcmp(cp, setexpandname) && env == ENV_STMT &&
checkconst(ex->args[1], 0)) {
ex = makeexpr_assign(makeexpr_hat(ex->args[0], 0),
ex->args[1]);
} else if (!strcmp(cp, getbitsname)) {
type = ex->args[0]->val.type;
if (type->kind == TK_POINTER)
type = type->basetype;
sbuf[0] = (type->issigned) ? 'S' : 'U';
sbuf[1] = (type->kind == TK_ARRAY) ? 'B' : 'S';
sbuf[2] = 0;
if (sbuf[1] == 'S' &&
type->smax->val.type == tp_boolean) {
ex = makeexpr_rel(EK_NE,
makeexpr_bin(EK_BAND, tp_integer,
ex->args[0],
makeexpr_bin(EK_LSH, tp_integer,
makeexpr_longcast(makeexpr_long(1),
type->basetype
== tp_unsigned),
ex->args[1])),
makeexpr_long(0));
ex = fixexpr(ex, env);
} else
strchange(&ex->val.s, format_s(cp, sbuf));
} else if (!strcmp(cp, putbitsname)) {
type = ex->args[0]->val.type;
if (type->kind == TK_POINTER)
type = type->basetype;
sbuf[0] = (type->issigned) ? 'S' : 'U';
sbuf[1] = (type->kind == TK_ARRAY) ? 'B' : 'S';
sbuf[2] = 0;
if (sbuf[1] == 'S' &&
type->smax->val.type == tp_boolean) {
ex = makeexpr_assign(ex->args[0],
makeexpr_bin(EK_BOR, tp_integer,
copyexpr(ex->args[0]),
makeexpr_bin(EK_LSH, tp_integer,
makeexpr_longcast(ex->args[2],
type->basetype
== tp_unsigned),
ex->args[1])));
} else
strchange(&ex->val.s, format_s(cp, sbuf));
} else if (!strcmp(cp, storebitsname)) {
type = ex->args[0]->val.type;
if (type->kind == TK_POINTER)
type = type->basetype;
sbuf[0] = (type->issigned) ? 'S' : 'U';
sbuf[1] = (type->kind == TK_ARRAY) ? 'B' : 'S';
sbuf[2] = 0;
strchange(&ex->val.s, format_s(cp, sbuf));
} else if (!strcmp(cp, clrbitsname)) {
type = ex->args[0]->val.type;
if (type->kind == TK_POINTER)
type = type->basetype;
sbuf[0] = (type->kind == TK_ARRAY) ? 'B' : 'S';
sbuf[1] = 0;
if (sbuf[0] == 'S' &&
type->smax->val.type == tp_boolean) {
ex = makeexpr_assign(ex->args[0],
makeexpr_bin(EK_BAND, tp_integer,
copyexpr(ex->args[0]),
makeexpr_un(EK_BNOT, tp_integer,
makeexpr_bin(EK_LSH, tp_integer,
makeexpr_longcast(makeexpr_long(1),
type->basetype
== tp_unsigned),
ex->args[1]))));
} else
strchange(&ex->val.s, format_s(cp, sbuf));
} else if (!strcmp(cp, "fopen")) {
if (which_lang == LANG_HP &&
ex->args[0]->kind == EK_CONST &&
ex->args[0]->val.type->kind == TK_STRING &&
ex->args[0]->val.i >= 1 &&
ex->args[0]->val.i <= 2 &&
isdigit(ex->args[0]->val.s[0]) &&
(ex->args[0]->val.i == 1 ||
isdigit(ex->args[0]->val.s[1]))) {
strchange(&ex->val.s, "fdopen");
ex->args[0] = makeexpr_long(atoi(ex->args[0]->val.s));
}
}
}
break;
case EK_NOT:
ex = makeexpr_not(fixexpr(grabarg(ex, 0), ENV_BOOL));
break;
case EK_AND:
case EK_OR:
for (i = 0; i < ex->nargs; i++)
ex->args[i] = fixexpr(ex->args[i], ENV_BOOL);
break;
case EK_EQ:
case EK_NE:
ex->args[0] = fixexpr(ex->args[0], ENV_EXPR);
ex->args[1] = fixexpr(ex->args[1], ENV_EXPR);
if (checkconst(ex->args[1], 0) && env == ENV_BOOL &&
ord_type(ex->args[1]->val.type)->kind != TK_ENUM &&
(implicitzero > 0 ||
(implicitzero < 0 && ex->args[0]->kind == EK_BICALL &&
boolean_bicall(ex->args[0]->val.s)))) {
if (ex->kind == EK_EQ)
ex = makeexpr_not(grabarg(ex, 0));
else {
ex = grabarg(ex, 0);
ex->val.type = tp_boolean;
}
}
break;
case EK_COND:
ex->args[0] = fixexpr(ex->args[0], ENV_BOOL);
#if 0
val = eval_expr(ex->args[0]);
#else
val = ex->args[0]->val;
if (ex->args[0]->kind != EK_CONST)
val.type = NULL;
#endif
if (val.type == tp_boolean) {
ex = grabarg(ex, (val.i) ? 1 : 2);
ex = fixexpr(ex, env);
} else {
ex->args[1] = fixexpr(ex->args[1], env);
ex->args[2] = fixexpr(ex->args[2], env);
}
break;
case EK_COMMA:
for (i = 0; i < ex->nargs-1; ) {
ex->args[i] = fixexpr(ex->args[i], ENV_STMT);
if (nosideeffects(ex->args[i], 1))
delfreearg(&ex, i);
else
i++;
}
ex->args[ex->nargs-1] = fixexpr(ex->args[ex->nargs-1], env);
if (ex->nargs == 1)
ex = grabarg(ex, 0);
break;
case EK_CHECKNIL:
ex->args[0] = fixexpr(ex->args[0], ENV_EXPR);
if (ex->nargs == 2) {
ex->args[1] = fixexpr(ex->args[1], ENV_EXPR);
ex2 = makeexpr_assign(copyexpr(ex->args[1]), ex->args[0]);
ex3 = ex->args[1];
} else {
ex2 = copyexpr(ex->args[0]);
ex3 = ex->args[0];
}
type = ex->args[0]->val.type;
type2 = ex->val.type;
ex = makeexpr_cond(makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
ex3,
makeexpr_cast(makeexpr_bicall_0(name_NILCHECK,
tp_int),
type));
ex->val.type = type2;
ex = fixexpr(ex, env);
break;
case EK_CAST:
case EK_ACTCAST:
if (env == ENV_STMT) {
ex = fixexpr(grabarg(ex, 0), ENV_STMT);
} else {
ex->args[0] = fixexpr(ex->args[0], ENV_EXPR);
}
break;
default:
for (i = 0; i < ex->nargs; i++)
ex->args[i] = fixexpr(ex->args[i], ENV_EXPR);
break;
}
return fix_expression(ex, env);
}
/* Output an expression */
#define bitOp(k) ((k)==EK_BAND || (k)==EK_BOR || (k)==EK_BXOR)
#define shfOp(k) ((k)==EK_LSH || (k)==EK_RSH)
#define logOp(k) ((k)==EK_AND || (k)==EK_OR)
#define relOp(k) ((k)==EK_EQ || (k)==EK_LT || (k)==EK_GT || \
(k)==EK_NE || (k)==EK_GE || (k)==EK_LE)
#define mathOp(k) ((k)==EK_PLUS || (k)==EK_TIMES || (k)==EK_NEG || \
(k)==EK_DIV || (k)==EK_DIVIDE || (k)==EK_MOD)
#define divOp(k) ((k)==EK_DIV || (k)==EK_DIVIDE)
Static int incompat(ex, num, prec)
Expr *ex;
int num, prec;
{
Expr *subex = ex->args[num];
if (extraparens == 0)
return prec;
if (ex->kind == subex->kind) {
if (logOp(ex->kind) || bitOp(ex->kind) ||
(divOp(ex->kind) && num == 0))
return -99; /* not even invisible parens */
else if (extraparens != 2)
return prec;
}
if (extraparens == 2)
return 15;
if (divOp(ex->kind) && num == 0 &&
(subex->kind == EK_TIMES || divOp(subex->kind)))
return -99;
if (bitOp(ex->kind) || shfOp(ex->kind))
return 15;
if (relOp(ex->kind) && relOp(subex->kind))
return 15;
if ((relOp(ex->kind) || logOp(ex->kind)) && bitOp(subex->kind))
return 15;
if (ex->kind == EK_COMMA)
return 15;
if (ex->kind == EK_ASSIGN && relOp(subex->kind))
return 15;
if (extraparens != 1)
return prec;
if (ex->kind == EK_ASSIGN)
return prec;
if (relOp(ex->kind) && mathOp(subex->kind))
return prec;
return 15;
}
#define EXTRASPACE() if (spaceexprs == 1) output(" ")
#define NICESPACE() if (spaceexprs != 0) output(" ")
void outop3(breakbefore, name)
int breakbefore;
char *name;
{
if (breakbefore & BRK_LEFT) {
output("\002");
if (breakbefore & BRK_RPREF)
output("\013");
}
output(name);
if (breakbefore & BRK_HANG)
output("\015");
if (breakbefore & BRK_RIGHT) {
output("\002");
if (breakbefore & BRK_LPREF)
output("\013");
}
}
#define outop(name) do { \
NICESPACE(); outop3(breakflag, name); NICESPACE(); \
} while (0)
#define outop2(name) do { \
EXTRASPACE(); outop3(breakflag, name); EXTRASPACE(); \
} while (0)
#define checkbreak(code) do { \
breakflag=(code); \
if ((prec != -99) && (breakflag & BRK_ALLNONE)) output("\007"); \
} while (0)
Static void out_ctx(ctx, address)
Meaning *ctx;
int address;
{
Meaning *ctx2;
int breakflag = breakbeforedot;
if (ctx->kind == MK_FUNCTION && ctx->varstructflag) {
if (curctx != ctx) {
if (address && curctx->ctx && curctx->ctx != ctx) {
output("\003");
if (breakflag & BRK_ALLNONE)
output("\007");
}
output(format_s(name_LINK, curctx->ctx->name));
ctx2 = curctx->ctx;
while (ctx2 && ctx2 != ctx) {
outop2("->");
output(format_s(name_LINK, ctx2->ctx->name));
ctx2 = ctx2->ctx;
}
if (ctx2 != ctx)
intwarning("out_ctx",
format_s("variable from %s not present in context path [307]",
ctx->name));
if (address && curctx->ctx && curctx->ctx != ctx)
output("\004");
if (!address)
outop2("->");
} else {
if (address) {
output("&");
EXTRASPACE();
}
output(format_s(name_VARS, curctx->name));
if (!address) {
outop2(".");
}
}
} else {
if (address)
output("NULL");
}
}
void out_var(mp, prec)
Meaning *mp;
int prec;
{
switch (mp->kind) {
case MK_CONST:
output(mp->name);
return;
case MK_VAR:
case MK_VARREF:
case MK_VARMAC:
case MK_PARAM:
case MK_VARPARAM:
if (mp->varstructflag) {
output("\003");
out_ctx(mp->ctx, 0);
output(mp->name);
output("\004");
} else
output(mp->name);
return;
default:
if (mp->name)
output(mp->name);
else
intwarning("out_var", "mp->sym == NULL [308]");
return;
}
}