home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
379a.lha
/
p2c1_13a
/
src
/
src.zoo
/
pexpr1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-11
|
30KB
|
990 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_PEXPR1_C
#include "trans.h"
Expr *dots_n_hats(ex, target)
Expr *ex;
Type *target;
{
Expr *ex2, *ex3;
Type *tp, *tp2, *ot;
Meaning *mp, *tvar;
int bits, hassl;
for (;;) {
if ((ex->val.type->kind == TK_PROCPTR ||
ex->val.type->kind == TK_CPROCPTR) &&
curtok != TOK_ASSIGN &&
((mp = (tp2 = ex->val.type)->basetype->fbase) == NULL ||
(mp->isreturn && mp->xnext == NULL) ||
curtok == TOK_LPAR) &&
(tp2->basetype->basetype != tp_void || target == tp_void) &&
(!target || (target->kind != TK_PROCPTR &&
target->kind != TK_CPROCPTR))) {
hassl = tp2->escale;
ex2 = ex;
ex3 = copyexpr(ex2);
if (hassl != 0)
ex3 = makeexpr_cast(makeexpr_dotq(ex3, "proc", tp_anyptr),
makepointertype(tp2->basetype));
ex = makeexpr_un(EK_SPCALL, tp2->basetype->basetype, ex3);
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;
}
if (mp) {
if (wneedtok(TOK_LPAR)) {
ex = p_funcarglist(ex, mp, 0, 0);
skipcloseparen();
}
} else if (curtok == TOK_LPAR) {
gettok();
if (!wneedtok(TOK_RPAR))
skippasttoken(TOK_RPAR);
}
if (hassl != 1 || hasstaticlinks == 2) {
freeexpr(ex2);
} else {
ex2 = makeexpr_dotq(ex2, "link", tp_anyptr),
ex3 = copyexpr(ex);
insertarg(&ex3, ex3->nargs, copyexpr(ex2));
tp = maketype(TK_FUNCTION);
tp->basetype = tp2->basetype->basetype;
tp->fbase = tp2->basetype->fbase;
tp->issigned = 1;
ex3->args[0]->val.type = makepointertype(tp);
ex = makeexpr_cond(makeexpr_rel(EK_NE, ex2, makeexpr_nil()),
ex3, ex);
}
if (tp2->basetype->fbase &&
tp2->basetype->fbase->isreturn &&
tp2->basetype->fbase->kind == MK_VARPARAM)
ex = makeexpr_hat(ex, 0); /* returns pointer to structured result */
continue;
}
switch (curtok) {
case TOK_HAT:
case TOK_ADDR:
gettok();
ex = makeexpr_hat(ex, 1);
break;
case TOK_LBR:
do {
gettok();
tp = ex->val.type;
if (tp->kind == TK_STRING) {
ex2 = p_expr(tp_integer);
if (checkconst(ex2, 0)) /* is it "s[0]"? */
ex = makeexpr_bicall_1("strlen", tp_char, ex);
else
ex = makeexpr_index(ex, ex2, makeexpr_long(1));
} else if (tp->kind == TK_ARRAY ||
tp->kind == TK_SMALLARRAY) {
if (tp->smax) {
ord_range_expr(tp->indextype, &ex2, NULL);
ex2 = makeexpr_minus(p_ord_expr(),
copyexpr(ex2));
if (!nodependencies(ex2, 0) &&
*getbitsname == '*') {
mp = makestmttempvar(tp_integer, name_TEMP);
ex3 = makeexpr_assign(makeexpr_var(mp), ex2);
ex2 = makeexpr_var(mp);
} else
ex3 = NULL;
ex = makeexpr_bicall_3(getbitsname, tp_int,
ex, ex2,
makeexpr_long(tp->escale));
if (tp->kind == TK_ARRAY) {
if (tp->basetype == tp_sshort)
bits = 4;
else
bits = 3;
insertarg(&ex, 3, makeexpr_long(bits));
}
ex = makeexpr_comma(ex3, ex);
ot = ord_type(tp->smax->val.type);
if (ot->kind == TK_ENUM && ot->meaning && useenum)
ex = makeexpr_cast(ex, tp->smax->val.type);
ex->val.type = tp->smax->val.type;
} else {
ord_range_expr(ex->val.type->indextype, &ex2, NULL);
if (debug>2) { fprintf(outf, "ord_range_expr returns "); dumpexpr(ex2); fprintf(outf, "\n"); }
ex = makeexpr_index(ex, p_ord_expr(),
copyexpr(ex2));
}
} else {
warning("Index on a non-array variable [287]");
ex = makeexpr_bin(EK_INDEX, tp_integer, ex, p_expr(tp_integer));
}
} while (curtok == TOK_COMMA);
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
break;
case TOK_DOT:
gettok();
if (!wexpecttok(TOK_IDENT))
break;
if (ex->val.type->kind == TK_STRING) {
if (!strcicmp(curtokbuf, "LENGTH")) {
ex = makeexpr_bicall_1("strlen", tp_int, ex);
} else if (!strcicmp(curtokbuf, "BODY")) {
/* nothing to do */
}
gettok();
break;
}
mp = curtoksym->fbase;
while (mp && mp->rectype != ex->val.type)
mp = mp->snext;
if (mp)
ex = makeexpr_dot(ex, mp);
else {
warning(format_s("No field called %s in that record [288]", curtokbuf));
ex = makeexpr_dotq(ex, curtokcase, tp_integer);
}
gettok();
break;
case TOK_COLONCOLON:
gettok();
if (wexpecttok(TOK_IDENT)) {
ex = pascaltypecast(curtokmeaning->type, ex);
gettok();
}
break;
default:
return ex;
}
}
}
Expr *fake_dots_n_hats(ex)
Expr *ex;
{
for (;;) {
switch (curtok) {
case TOK_HAT:
case TOK_ADDR:
if (ex->val.type->kind == TK_POINTER)
ex = makeexpr_hat(ex, 0);
else {
ex->val.type = makepointertype(ex->val.type);
ex = makeexpr_un(EK_HAT, ex->val.type->basetype, ex);
}
gettok();
break;
case TOK_LBR:
do {
gettok();
ex = makeexpr_bin(EK_INDEX, tp_integer, ex, p_expr(tp_integer));
} while (curtok == TOK_COMMA);
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
break;
case TOK_DOT:
gettok();
if (!wexpecttok(TOK_IDENT))
break;
ex = makeexpr_dotq(ex, curtokcase, tp_integer);
gettok();
break;
case TOK_COLONCOLON:
gettok();
if (wexpecttok(TOK_IDENT)) {
ex = pascaltypecast(curtokmeaning->type, ex);
gettok();
}
break;
default:
return ex;
}
}
}
Static void bindnames(ex)
Expr *ex;
{
int i;
Symbol *sp;
Meaning *mp;
if (ex->kind == EK_NAME) {
sp = findsymbol_opt(fixpascalname(ex->val.s));
if (sp) {
mp = sp->mbase;
while (mp && !mp->isactive)
mp = mp->snext;
if (mp && !strcmp(mp->name, ex->val.s)) {
ex->kind = EK_VAR;
ex->val.i = (long)mp;
ex->val.type = mp->type;
}
}
}
i = ex->nargs;
while (--i >= 0)
bindnames(ex->args[i]);
}
void var_reference(mp)
Meaning *mp;
{
Meaning *mp2;
mp->refcount++;
if (mp->ctx && mp->ctx->kind == MK_FUNCTION &&
mp->ctx->needvarstruct &&
(mp->kind == MK_VAR ||
mp->kind == MK_VARREF ||
mp->kind == MK_VARMAC ||
mp->kind == MK_PARAM ||
mp->kind == MK_VARPARAM ||
(mp->kind == MK_CONST &&
(mp->type->kind == TK_ARRAY ||
mp->type->kind == TK_RECORD)))) {
if (debug>1) { fprintf(outf, "varstruct'ing %s\n", mp->name); }
if (!mp->varstructflag) {
mp->varstructflag = 1;
if (mp->constdefn && /* move init code into function body */
mp->kind != MK_VARMAC) {
mp2 = addmeaningafter(mp, curtoksym, MK_VAR);
curtoksym->mbase = mp2->snext; /* hide this fake variable */
mp2->snext = mp; /* remember true variable */
mp2->type = mp->type;
mp2->constdefn = mp->constdefn;
mp2->isforward = 1; /* declare it "static" */
mp2->refcount++; /* so it won't be purged! */
mp->constdefn = NULL;
mp->isforward = 0;
}
}
for (mp2 = curctx->ctx; mp2 != mp->ctx; mp2 = mp2->ctx)
mp2->varstructflag = 1;
mp2->varstructflag = 1;
}
}
Expr *p_variable(target)
Type *target;
{
Expr *ex, *ex2;
Meaning *mp;
Symbol *sym;
if (curtok != TOK_IDENT) {
warning("Expected a variable [289]");
return makeexpr_long(0);
}
if (!curtokmeaning) {
sym = curtoksym;
ex = makeexpr_name(curtokcase, tp_integer);
gettok();
if (curtok == TOK_LPAR) {
ex = makeexpr_bicall_0(ex->val.s, tp_integer);
do {
gettok();
insertarg(&ex, ex->nargs, p_expr(NULL));
} while (curtok == TOK_COMMA || curtok == TOK_ASSIGN);
if (!wneedtok(TOK_RPAR))
skippasttotoken(TOK_RPAR, TOK_SEMI);
}
if (!tryfuncmacro(&ex, NULL))
undefsym(sym);
return fake_dots_n_hats(ex);
}
var_reference(curtokmeaning);
mp = curtokmeaning;
if (mp->kind == MK_FIELD) {
ex = makeexpr_dot(copyexpr(withexprs[curtokint]), mp);
} else if (mp->kind == MK_CONST &&
mp->type->kind == TK_SET &&
mp->constdefn) {
ex = copyexpr(mp->constdefn);
mp = makestmttempvar(ex->val.type, name_SET);
ex2 = makeexpr(EK_MACARG, 0);
ex2->val.type = ex->val.type;
ex = replaceexprexpr(ex, ex2, makeexpr_var(mp));
freeexpr(ex2);
} else if (mp->kind == MK_CONST &&
(mp == mp_false ||
mp == mp_true ||
mp->anyvarflag ||
(foldconsts > 0 &&
(mp->type->kind == TK_INTEGER ||
mp->type->kind == TK_BOOLEAN ||
mp->type->kind == TK_CHAR ||
mp->type->kind == TK_ENUM ||
mp->type->kind == TK_SUBR ||
mp->type->kind == TK_REAL)) ||
(foldstrconsts > 0 &&
(mp->type->kind == TK_STRING)))) {
if (mp->constdefn) {
ex = copyexpr(mp->constdefn);
if (ex->val.type == tp_int) /* kludge! */
ex->val.type = tp_integer;
} else
ex = makeexpr_val(copyvalue(mp->val));
} else if (mp->kind == MK_VARPARAM ||
mp->kind == MK_VARREF) {
ex = makeexpr_hat(makeexpr_var(mp), 0);
} else if (mp->kind == MK_VARMAC) {
ex = copyexpr(mp->constdefn);
bindnames(ex);
ex = gentle_cast(ex, mp->type);
ex->val.type = mp->type;
} else if (mp->kind == MK_SPVAR && mp->handler) {
gettok();
ex = (*mp->handler)(mp);
return dots_n_hats(ex, target);
} else if (mp->kind == MK_VAR ||
mp->kind == MK_CONST ||
mp->kind == MK_PARAM) {
ex = makeexpr_var(mp);
} else {
symclass(mp->sym);
ex = makeexpr_name(mp->name, tp_integer);
}
gettok();
return dots_n_hats(ex, target);
}
Expr *p_ord_expr()
{
return makeexpr_charcast(p_expr(tp_integer));
}
Expr *makesmallsetconst(bits, type)
long bits;
Type *type;
{
Expr *ex;
ex = makeexpr_long(bits);
ex->val.type = type;
if (smallsetconst != 2)
insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer));
return ex;
}
Expr *packset(ex, type)
Expr *ex;
Type *type;
{
Meaning *mp;
Expr *ex2;
long max2;
if (ex->kind == EK_BICALL) {
if (!strcmp(ex->val.s, setexpandname) &&
(mp = istempvar(ex->args[0])) != NULL) {
canceltempvar(mp);
return grabarg(ex, 1);
}
if (!strcmp(ex->val.s, setunionname) &&
(mp = istempvar(ex->args[0])) != NULL &&
!exproccurs(ex->args[1], ex->args[0]) &&
!exproccurs(ex->args[2], ex->args[0])) {
canceltempvar(mp);
return makeexpr_bin(EK_BOR, type, packset(ex->args[1], type),
packset(ex->args[2], type));
}
if (!strcmp(ex->val.s, setaddname)) {
ex2 = makeexpr_bin(EK_LSH, type,
makeexpr_longcast(makeexpr_long(1), 1),
ex->args[1]);
ex = packset(ex->args[0], type);
if (checkconst(ex, 0))
return ex2;
else
return makeexpr_bin(EK_BOR, type, ex, ex2);
}
if (!strcmp(ex->val.s, setaddrangename)) {
if (ord_range(type->indextype, NULL, &max2) && max2 == setbits-1)
note("Range construction was implemented by a subtraction which may overflow [278]");
ex2 = makeexpr_minus(makeexpr_bin(EK_LSH, type,
makeexpr_longcast(makeexpr_long(1), 1),
makeexpr_plus(ex->args[2],
makeexpr_long(1))),
makeexpr_bin(EK_LSH, type,
makeexpr_longcast(makeexpr_long(1), 1),
ex->args[1]));
ex = packset(ex->args[0], type);
if (checkconst(ex, 0))
return ex2;
else
return makeexpr_bin(EK_BOR, type, ex, ex2);
}
}
return makeexpr_bicall_1(setpackname, type, ex);
}
#define MAXSETLIT 400
Expr *p_setfactor(type)
Type *type;
{
Expr *ex, *exmax = NULL, *ex2;
Expr *first[MAXSETLIT], *last[MAXSETLIT];
char doneflag[MAXSETLIT];
int i, j, num, donecount;
int isconst, guesstype = 0;
long maxv, max2;
Value val;
Type *tp;
Meaning *tvar;
if (curtok == TOK_LBRACE)
gettok();
else if (!wneedtok(TOK_LBR))
return makeexpr_long(0);
if (curtok == TOK_RBR || curtok == TOK_RBRACE) { /* empty set */
gettok();
val.type = tp_smallset;
val.i = 0;
val.s = NULL;
return makeexpr_val(val);
}
if (!type)
guesstype = 1;
maxv = -1;
isconst = 1;
num = 0;
for (;;) {
if (num >= MAXSETLIT) {
warning(format_d("Too many elements in set literal; max=%d [290]", MAXSETLIT));
ex = p_expr(type);
while (curtok != TOK_RBR && curtok != TOK_RBRACE) {
gettok();
ex = p_expr(type);
}
break;
}
if (guesstype && num == 0) {
ex = p_ord_expr();
type = ord_type(ex->val.type);
} else {
ex = p_expr(type);
}
first[num] = ex = gentle_cast(ex, type);
doneflag[num] = 0;
if (curtok == TOK_DOTS) {
val = eval_expr(ex);
if (val.type) {
if (val.i > maxv) { /* In case of [127..0] */
maxv = val.i;
exmax = ex;
}
} else
isconst = 0;
gettok();
last[num] = ex = gentle_cast(p_expr(type), type);
} else {
last[num] = NULL;
}
val = eval_expr(ex);
if (val.type) {
if (val.i > maxv) {
maxv = val.i;
exmax = ex;
}
} else {
isconst = 0;
maxv = LONG_MAX;
}
num++;
if (curtok == TOK_COMMA)
gettok();
else
break;
}
if (curtok == TOK_RBRACE)
gettok();
else if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
tp = ord_type(first[0]->val.type);
if (guesstype) { /* must determine type */
if (!exmax || maxv == LONG_MAX) {
maxv = defaultsetsize-1;
if (ord_range(tp, NULL, &max2) && maxv > max2)
maxv = max2;
exmax = makeexpr_long(maxv);
} else
exmax = copyexpr(exmax);
if (!ord_range(tp, NULL, &max2) || maxv != max2)
tp = makesubrangetype(tp, makeexpr_long(0), exmax);
type = makesettype(tp);
} else
type = makesettype(type);
donecount = 0;
if (smallsetconst > 0) {
val.i = 0;
for (i = 0; i < num; i++) {
if (first[i]->kind == EK_CONST && first[i]->val.i < setbits &&
(!last[i] || (last[i]->kind == EK_CONST &&
last[i]->val.i >= 0 &&
last[i]->val.i < setbits))) {
if (last[i]) {
for (j = first[i]->val.i; j <= last[i]->val.i; j++)
val.i |= 1<<j;
} else
val.i |= 1 << first[i]->val.i;
doneflag[i] = 1;
donecount++;
}
}
}
if (donecount) {
ex = makesmallsetconst(val.i, tp_smallset);
} else
ex = NULL;
if (type->kind == TK_SMALLSET) {
for (i = 0; i < num; i++) {
if (!doneflag[i]) {
ex2 = makeexpr_bin(EK_LSH, type,
makeexpr_longcast(makeexpr_long(1), 1),
enum_to_int(first[i]));
if (last[i]) {
if (ord_range(type->indextype, NULL, &max2) && max2 == setbits-1)
note("Range construction was implemented by a subtraction which may overflow [278]");
ex2 = makeexpr_minus(makeexpr_bin(EK_LSH, type,
makeexpr_longcast(makeexpr_long(1), 1),
makeexpr_plus(enum_to_int(last[i]),
makeexpr_long(1))),
ex2);
}
if (ex)
ex = makeexpr_bin(EK_BOR, type, makeexpr_longcast(ex, 1), ex2);
else
ex = ex2;
}
}
} else {
tvar = makestmttempvar(type, name_SET);
if (!ex) {
val.type = tp_smallset;
val.i = 0;
val.s = NULL;
ex = makeexpr_val(val);
}
ex = makeexpr_bicall_2(setexpandname, type,
makeexpr_var(tvar), makeexpr_arglong(ex, 1));
for (i = 0; i < num; i++) {
if (!doneflag[i]) {
if (last[i])
ex = makeexpr_bicall_3(setaddrangename, type,
ex, makeexpr_arglong(enum_to_int(first[i]), 0),
makeexpr_arglong(enum_to_int(last[i]), 0));
else
ex = makeexpr_bicall_2(setaddname, type,
ex, makeexpr_arglong(enum_to_int(first[i]), 0));
}
}
}
return ex;
}
Expr *p_funcarglist(ex, args, firstarg, ismacro)
Expr *ex;
Meaning *args;
int firstarg, ismacro;
{
Meaning *mp, *mp2, *arglist = args, *prevarg = NULL;
Expr *ex2;
int i, fi, fakenum = -1, castit, isconf, isnonpos = 0;
Type *tp, *tp2;
char *name;
castit = castargs;
if (castit < 0)
castit = (prototypes == 0);
while (args) {
if (isnonpos) {
while (curtok == TOK_COMMA)
gettok();
if (curtok == TOK_RPAR) {
args = arglist;
i = firstarg;
while (args) {
if (ex->nargs <= i)
insertarg(&ex, ex->nargs, NULL);
if (!ex->args[i]) {
if (args->constdefn)
ex->args[i] = copyexpr(args->constdefn);
else {
warning(format_s("Missing value for parameter %s [291]",
args->name));
ex->args[i] = makeexpr_long(0);
}
}
args = args->xnext;
i++;
}
break;
}
}
if (args->isreturn || args->fakeparam) {
if (args->fakeparam) {
if (fakenum < 0)
fakenum = ex->nargs;
if (args->constdefn)
insertarg(&ex, ex->nargs, copyexpr(args->constdefn));
else
insertarg(&ex, ex->nargs, makeexpr_long(0));
}
args = args->xnext; /* return value parameter */
continue;
}
if (curtok == TOK_RPAR) {
if (args->constdefn) {
insertarg(&ex, ex->nargs, copyexpr(args->constdefn));
args = args->xnext;
continue;
} else {
if (ex->kind == EK_FUNCTION) {
name = ((Meaning *)ex->val.i)->name;
ex->kind = EK_BICALL;
ex->val.s = stralloc(name);
} else
name = "function";
warning(format_s("Too few arguments for %s [292]", name));
return ex;
}
}
if (curtok == TOK_COMMA) {
if (args->constdefn)
insertarg(&ex, ex->nargs, copyexpr(args->constdefn));
else {
warning(format_s("Missing parameter %s [293]", args->name));
insertarg(&ex, ex->nargs, makeexpr_long(0));
}
gettok();
args = args->xnext;
continue;
}
p_mech_spec(0);
if (curtok == TOK_IDENT) {
mp = arglist;
mp2 = NULL;
i = firstarg;
fi = -1;
while (mp && strcmp(curtokbuf, mp->sym->name)) {
if (mp->fakeparam) {
if (fi < 0)
fi = i;
} else
fi = -1;
i++;
mp2 = mp;
mp = mp->xnext;
}
if (mp &&
(peeknextchar() == ':' || !curtokmeaning || isnonpos)) {
gettok();
wneedtok(TOK_ASSIGN);
prevarg = mp2;
args = mp;
fakenum = fi;
isnonpos = 1;
} else
i = ex->nargs;
} else
i = ex->nargs;
while (ex->nargs <= i)
insertarg(&ex, ex->nargs, NULL);
if (ex->args[i])
warning(format_s("Multiple values for parameter %s [294]",
args->name));
tp = args->type;
ex2 = p_expr(tp);
if (args->kind == MK_VARPARAM)
tp = tp->basetype;
tp2 = ex2->val.type;
isconf = ((tp->kind == TK_ARRAY ||
tp->kind == TK_STRING) && tp->structdefd);
switch (args->kind) {
case MK_PARAM:
if (castit && tp->kind == TK_REAL &&
ex2->val.type->kind != TK_REAL)
ex2 = makeexpr_cast(ex2, tp);
else if (ord_type(tp)->kind == TK_INTEGER && !ismacro)
ex2 = makeexpr_arglong(ex2, long_type(tp));
else if (args->othername && args->rectype != tp &&
tp->kind != TK_STRING && args->type == tp2)
ex2 = makeexpr_addr(ex2);
else
ex2 = gentle_cast(ex2, tp);
ex->args[i] = ex2;
break;
case MK_VARPARAM:
if (args->type == tp_strptr && args->anyvarflag) {
ex->args[i] = strmax_func(ex2);
insertarg(&ex, ex->nargs-1, makeexpr_addr(ex2));
if (isnonpos)
note("Non-positional conformant parameters may not work [279]");
} else { /* regular VAR parameter */
ex2 = makeexpr_addrf(ex2);
if (args->anyvarflag ||
(tp->kind == TK_POINTER && tp2->kind == TK_POINTER &&
(tp == tp_anyptr || tp2 == tp_anyptr))) {
if (!ismacro)
ex2 = makeexpr_cast(ex2, args->type);
} else {
if (tp2 != tp && !isconf &&
(tp2->kind != TK_STRING ||
tp->kind != TK_STRING))
warning(format_s("Type mismatch in VAR parameter %s [295]",
args->name));
}
ex->args[i] = ex2;
}
break;
default:
intwarning("p_funcarglist",
format_s("Parameter type is %s [296]",
meaningkindname(args->kind)));
break;
}
if (isconf && /* conformant array or string */
(!prevarg || prevarg->type != args->type)) {
while (tp->kind == TK_ARRAY && tp->structdefd) {
if (tp2->kind == TK_SMALLARRAY) {
warning("Trying to pass a small-array for a conformant array [297]");
/* this has a chance of working... */
ex->args[ex->nargs-1] =
makeexpr_addr(ex->args[ex->nargs-1]);
} else if (tp2->kind == TK_STRING) {
ex->args[fakenum++] =
makeexpr_arglong(makeexpr_long(1), integer16 == 0);
ex->args[fakenum++] =
makeexpr_arglong(strmax_func(ex->args[ex->nargs-1]),
integer16 == 0);
break;
} else if (tp2->kind != TK_ARRAY) {
warning("Type mismatch for conformant array [298]");
break;
}
ex->args[fakenum++] =
makeexpr_arglong(copyexpr(tp2->indextype->smin),
integer16 == 0);
ex->args[fakenum++] =
makeexpr_arglong(copyexpr(tp2->indextype->smax),
integer16 == 0);
tp = tp->basetype;
tp2 = tp2->basetype;
}
if (tp->kind == TK_STRING && tp->structdefd) {
ex->args[fakenum] =
makeexpr_arglong(strmax_func(ex->args[ex->nargs-1]),
integer16 == 0);
}
}
fakenum = -1;
if (!isnonpos) {
prevarg = args;
args = args->xnext;
if (args) {
if (curtok != TOK_RPAR && !wneedtok(TOK_COMMA))
skiptotoken2(TOK_RPAR, TOK_SEMI);
}
}
}
if (curtok == TOK_COMMA) {
if (ex->kind == EK_FUNCTION) {
name = ((Meaning *)ex->val.i)->name;
ex->kind = EK_BICALL;
ex->val.s = stralloc(name);
} else
name = "function";
warning(format_s("Too many arguments for %s [299]", name));
while (curtok == TOK_COMMA) {
gettok();
insertarg(&ex, ex->nargs, p_expr(tp_integer));
}
}
return ex;
}
Expr *replacemacargs(ex, fex)
Expr *ex, *fex;
{
int i;
Expr *ex2;
for (i = 0; i < ex->nargs; i++)
ex->args[i] = replacemacargs(ex->args[i], fex);
if (ex->kind == EK_MACARG) {
if (ex->val.i <= fex->nargs) {
ex2 = copyexpr(fex->args[ex->val.i - 1]);
} else {
ex2 = makeexpr_name("<meef>", tp_integer);
note("FuncMacro specified more arguments than call [280]");
}
freeexpr(ex);
return ex2;
}
return resimplify(ex);
}
Expr *p_noarglist(ex, mp, args)
Expr *ex;
Meaning *mp, *args;
{
while (args && args->constdefn) {
insertarg(&ex, ex->nargs, copyexpr(args->constdefn));
args = args->xnext;
}
if (args) {
warning(format_s("Expected an argument list for %s [300]", mp->name));
ex->kind = EK_BICALL;
ex->val.s = stralloc(mp->name);
}
return ex;
}
void func_reference(func)
Meaning *func;
{
Meaning *mp;
if (func->ctx && func->ctx != curctx &&func->ctx->kind == MK_FUNCTION &&
func->ctx->varstructflag && !curctx->ctx->varstructflag) {
for (mp = curctx->ctx; mp != func->ctx; mp = mp->ctx)
mp->varstructflag = 1;
}
}
Expr *p_funccall(mp)
Meaning *mp;
{
Meaning *mp2, *tvar;
Expr *ex, *ex2;
int firstarg = 0;
func_reference(mp);
ex = makeexpr(EK_FUNCTION, 0);
ex->val.i = (long)mp;
ex->val.type = mp->type->basetype;
mp2 = mp->type->fbase;
if (mp2 && mp2->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, 0, makeexpr_addr(makeexpr_var(tvar)));
mp2 = mp2->xnext;
firstarg++;
}
if (mp2 && curtok != TOK_LPAR) {
ex = p_noarglist(ex, mp, mp2);
} else if (curtok == TOK_LPAR) {
gettok();
ex = p_funcarglist(ex, mp2, firstarg, (mp->constdefn != NULL));
skipcloseparen();
}
if (mp->constdefn) {
ex2 = replacemacargs(copyexpr(mp->constdefn), ex);
ex2 = gentle_cast(ex2, ex->val.type);
ex2->val.type = ex->val.type;
freeexpr(ex);
return ex2;
}
return ex;
}
Expr *accumulate_strlit()
{
char buf[256], ch, *cp, *cp2;
int len, i, danger = 0;
len = 0;
cp = buf;
for (;;) {
if (curtok == TOK_STRLIT) {
cp2 = curtokbuf;
i = curtokint;
while (--i >= 0) {
if (++len <= 255) {
ch = *cp++ = *cp2++;
if (ch & 128)
danger++;
}
}
} else if (curtok == TOK_HAT) { /* Turbo */
i = getchartok() & 0x1f;
if (++len <= 255)
*cp++ = i;
} else if (curtok == TOK_LPAR) { /* VAX */
Value val;
do {
gettok();
val = p_constant(tp_integer);
if (++len <= 255)
*cp++ = val.i;
} while (curtok == TOK_COMMA);
skipcloseparen();
continue;
} else
break;
gettok();
}
if (len > 255) {
warning("String literal too long [301]");
len = 255;
}
if (danger &&
!(unsignedchar == 1 ||
(unsignedchar != 0 && signedchars == 0)))
note(format_s("Character%s >= 128 encountered [281]", (danger > 1) ? "s" : ""));
return makeexpr_lstring(buf, len);
}