home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
379a.lha
/
p2c1_13a
/
src
/
src.zoo
/
decl4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-10
|
28KB
|
999 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_DECL4_C
#include "trans.h"
#define MAXIMPORTS 100
extern struct ptrdesc {
struct ptrdesc *next;
Symbol *sym;
Type *tp;
} *ptrbase;
extern struct ctxstack {
struct ctxstack *next;
Meaning *ctx, *ctxlast;
struct tempvarlist *tempvars;
int tempvarcount, importmark;
} *ctxtop;
extern struct tempvarlist {
struct tempvarlist *next;
Meaning *tvar;
int active;
} *tempvars, *stmttempvars;
extern int tempvarcount;
extern int stringtypecachesize;
extern Type **stringtypecache;
extern Meaning *importlist[MAXIMPORTS];
extern int firstimport;
extern Type *tp_special_anyptr;
extern int wasaliased;
extern int deferallptrs;
extern int anydeferredptrs;
extern int silentalreadydef;
extern int nonloclabelcount;
extern Strlist *varstructdecllist;
extern Meaning *enum_tname;
Static Type *p_arraydecl(tname, ispacked, confp)
char *tname;
int ispacked;
Meaning ***confp;
{
Type *tp, *tp2;
Meaning *mp;
long size, smin, smax, bitsize, fullbitsize;
int issigned, bpower, hasrange;
tp = maketype(TK_ARRAY);
if (confp == NULL) {
tp->indextype = p_type(NULL);
if (tp->indextype->kind == TK_SUBR) {
if (ord_range(tp->indextype, &smin, NULL) &&
smin > 0 && smin <= skipindices && !ispacked) {
tp->smin = makeexpr_val(make_ord(tp->indextype->basetype, smin));
tp->indextype = makesubrangetype(tp->indextype->basetype,
makeexpr_val(make_ord(
tp->indextype->basetype, 0)),
copyexpr(tp->indextype->smax));
}
}
} else {
if (modula2) {
**confp = mp = addmeaning(findsymbol(format_s(name_ALOW, tname)), MK_PARAM);
mp->fakeparam = 1;
mp->constqual = 1;
mp->xnext = addmeaning(findsymbol(format_s(name_AHIGH, tname)), MK_PARAM);
mp->xnext->fakeparam = 1;
mp->xnext->constqual = 1;
*confp = &mp->xnext->xnext;
tp2 = maketype(TK_SUBR);
tp2->basetype = tp_integer;
mp->type = tp_integer;
mp->xnext->type = mp->type;
tp2->smin = makeexpr_long(0);
tp2->smax = makeexpr_minus(makeexpr_var(mp->xnext),
makeexpr_var(mp));
tp->indextype = tp2;
tp->structdefd = 1;
} else {
wexpecttok(TOK_IDENT);
tp2 = maketype(TK_SUBR);
if (peeknextchar() != ',' &&
(!curtokmeaning || curtokmeaning->kind != MK_TYPE)) {
mp = addmeaning(curtoksym, MK_PARAM);
gettok();
wneedtok(TOK_DOTS);
wexpecttok(TOK_IDENT);
mp->xnext = addmeaning(curtoksym, MK_PARAM);
gettok();
if (wneedtok(TOK_COLON)) {
tp2->basetype = p_type(NULL);
} else {
tp2->basetype = tp_integer;
}
} else {
mp = addmeaning(findsymbol(format_s(name_ALOW, tname)), MK_PARAM);
mp->xnext = addmeaning(findsymbol(format_s(name_AHIGH, tname)), MK_PARAM);
tp2->basetype = p_type(NULL);
}
mp->fakeparam = 1;
mp->constqual = 1;
mp->xnext->fakeparam = 1;
mp->xnext->constqual = 1;
**confp = mp;
*confp = &mp->xnext->xnext;
mp->type = tp2->basetype;
mp->xnext->type = tp2->basetype;
tp2->smin = makeexpr_var(mp);
tp2->smax = makeexpr_var(mp->xnext);
tp->indextype = tp2;
tp->structdefd = 1; /* conformant array flag */
}
}
if (curtok == TOK_COMMA || curtok == TOK_SEMI) {
gettok();
tp->basetype = p_arraydecl(tname, ispacked, confp);
return tp;
} else {
if (!modula2) {
if (!wneedtok(TOK_RBR))
skiptotoken(TOK_OF);
}
if (!wneedtok(TOK_OF))
skippasttotoken(TOK_OF, TOK_COMMA);
checkkeyword(TOK_VARYING);
if (confp != NULL &&
(curtok == TOK_ARRAY || curtok == TOK_PACKED ||
curtok == TOK_VARYING)) {
tp->basetype = p_conformant_array(tname, confp);
} else
tp->basetype = p_type(NULL);
if (!ispacked)
return tp;
size = 0;
tp2 = tp->basetype;
if (!tname)
tname = "array";
issigned = packedsize(tname, &tp2, &size, 1);
if (!size || size > 8 ||
(issigned && !packsigned) ||
(size > 4 &&
(!issigned || (signedchars == 1 || hassignedchar))))
return tp;
bpower = 0;
while ((1<<bpower) < size)
bpower++; /* round size up to power of two */
size = 1<<bpower; /* size = # bits in an array element */
tp->escale = bpower;
tp->issigned = issigned;
hasrange = ord_range(tp->indextype, &smin, &smax) &&
(smax < 100000); /* don't be confused by giant arrays */
if (hasrange &&
(bitsize = (smax - smin + 1) * size)
<= ((sizeof_integer > 0) ? sizeof_integer : 32)) {
if (bitsize > ((sizeof_short > 0) ? sizeof_short : 16)) {
tp2 = (issigned) ? tp_integer : tp_unsigned;
fullbitsize = ((sizeof_integer > 0) ? sizeof_integer : 32);
} else if (bitsize > ((sizeof_char > 0) ? sizeof_char : 8) ||
(issigned && !(signedchars == 1 || hassignedchar))) {
tp2 = (issigned) ? tp_sshort : tp_ushort;
fullbitsize = ((sizeof_short > 0) ? sizeof_short : 16);
} else {
tp2 = (issigned) ? tp_sbyte : tp_ubyte;
fullbitsize = ((sizeof_char > 0) ? sizeof_char : 8);
}
tp->kind = TK_SMALLARRAY;
if (ord_range(tp->indextype, &smin, NULL) &&
smin > 0 && smin <= fullbitsize - bitsize) {
tp->smin = makeexpr_val(make_ord(tp->indextype->basetype, smin));
tp->indextype = makesubrangetype(tp->indextype->basetype,
makeexpr_val(make_ord(
tp->indextype->basetype, 0)),
copyexpr(tp->indextype->smax));
}
} else {
if (!issigned)
tp2 = tp_ubyte;
else if (signedchars == 1 || hassignedchar)
tp2 = tp_sbyte;
else
tp2 = tp_sshort;
}
tp->smax = makeexpr_type(tp->basetype);
tp->basetype = tp2;
return tp;
}
}
Static Type *p_conformant_array(tname, confp)
char *tname;
Meaning ***confp;
{
int ispacked;
Meaning *mp;
Type *tp, *tp2;
p_attributes();
ignore_attributes();
if (curtok == TOK_PACKED) {
ispacked = 1;
gettok();
} else
ispacked = 0;
checkkeyword(TOK_VARYING);
if (curtok == TOK_VARYING) {
gettok();
wneedtok(TOK_LBR);
wexpecttok(TOK_IDENT);
mp = addmeaning(curtoksym, MK_PARAM);
mp->fakeparam = 1;
mp->constqual = 1;
**confp = mp;
*confp = &mp->xnext;
mp->type = tp_integer;
tp2 = maketype(TK_SUBR);
tp2->basetype = tp_integer;
tp2->smin = makeexpr_long(1);
tp2->smax = makeexpr_var(mp);
tp = maketype(TK_STRING);
tp->indextype = tp2;
tp->basetype = tp_char;
tp->structdefd = 1; /* conformant array flag */
gettok();
wneedtok(TOK_RBR);
skippasttoken(TOK_OF);
tp->basetype = p_type(NULL);
return tp;
}
if (wneedtok(TOK_ARRAY) &&
(modula2 || wneedtok(TOK_LBR))) {
return p_arraydecl(tname, ispacked, confp);
} else {
return tp_integer;
}
}
/* VAX Pascal: */
void p_attributes()
{
Strlist *l1;
if (modula2)
return;
while (curtok == TOK_LBR) {
implementationmodules = 1; /* auto-detect VAX Pascal */
do {
gettok();
if (!wexpecttok(TOK_IDENT)) {
skippasttoken(TOK_RBR);
return;
}
l1 = strlist_append(&attrlist, strupper(curtokbuf));
l1->value = -1;
gettok();
if (curtok == TOK_LPAR) {
gettok();
if (!strcmp(l1->s, "CHECK") ||
!strcmp(l1->s, "OPTIMIZE") ||
!strcmp(l1->s, "KEY") ||
!strcmp(l1->s, "COMMON") ||
!strcmp(l1->s, "PSECT") ||
!strcmp(l1->s, "EXTERNAL") ||
!strcmp(l1->s, "GLOBAL") ||
!strcmp(l1->s, "WEAK_EXTERNAL") ||
!strcmp(l1->s, "WEAK_GLOBAL")) {
l1->value = (long)stralloc(curtokbuf);
gettok();
while (curtok == TOK_COMMA) {
gettok();
gettok();
}
} else if (!strcmp(l1->s, "INHERIT") ||
!strcmp(l1->s, "IDENT") ||
!strcmp(l1->s, "ENVIRONMENT")) {
p_expr(NULL);
while (curtok == TOK_COMMA) {
gettok();
p_expr(NULL);
}
} else {
l1->value = ord_value(p_constant(tp_integer));
while (curtok == TOK_COMMA) {
gettok();
p_expr(NULL);
}
}
if (!wneedtok(TOK_RPAR)) {
skippasttotoken(TOK_RPAR, TOK_LBR);
}
}
} while (curtok == TOK_COMMA);
if (!wneedtok(TOK_RBR)) {
skippasttoken(TOK_RBR);
}
}
}
void ignore_attributes()
{
while (attrlist) {
if (strcmp(attrlist->s, "HIDDEN") &&
strcmp(attrlist->s, "INHERIT") &&
strcmp(attrlist->s, "ENVIRONMENT"))
warning(format_s("Type attribute %s ignored [128]", attrlist->s));
strlist_eat(&attrlist);
}
}
int size_attributes()
{
int size = -1;
Strlist *l1;
if ((l1 = strlist_find(attrlist, "BIT")) != NULL)
size = 1;
else if ((l1 = strlist_find(attrlist, "BYTE")) != NULL)
size = 8;
else if ((l1 = strlist_find(attrlist, "WORD")) != NULL)
size = 16;
else if ((l1 = strlist_find(attrlist, "LONG")) != NULL)
size = 32;
else if ((l1 = strlist_find(attrlist, "QUAD")) != NULL)
size = 64;
else if ((l1 = strlist_find(attrlist, "OCTA")) != NULL)
size = 128;
else
return -1;
if (l1->value >= 0)
size *= l1->value;
strlist_delete(&attrlist, l1);
return size;
}
void p_mech_spec(doref)
int doref;
{
if (curtok == TOK_IDENT && doref &&
!strcicmp(curtokbuf, "%REF")) {
note("Mechanism specified %REF treated like VAR [107]");
curtok = TOK_VAR;
return;
}
if (curtok == TOK_IDENT &&
(!strcicmp(curtokbuf, "%REF") ||
!strcicmp(curtokbuf, "%IMMED") ||
!strcicmp(curtokbuf, "%DESCR") ||
!strcicmp(curtokbuf, "%STDESCR"))) {
note(format_s("Mechanism specifier %s ignored [108]", curtokbuf));
gettok();
}
}
Type *p_modula_subrange(basetype)
Type *basetype;
{
Type *tp;
Value val;
wneedtok(TOK_LBR);
tp = maketype(TK_SUBR);
tp->smin = p_ord_expr();
if (basetype)
tp->smin = gentle_cast(tp->smin, basetype);
if (wexpecttok(TOK_DOTS)) {
gettok();
tp->smax = p_ord_expr();
if (tp->smax->val.type->kind == TK_REAL &&
tp->smax->kind == EK_CONST &&
strlen(tp->smax->val.s) == 12 &&
strcmp(tp->smax->val.s, "2147483648.0") >= 0 &&
strcmp(tp->smax->val.s, "4294967295.0") <= 0) {
tp = tp_unsigned;
} else if (basetype) {
tp->smin = gentle_cast(tp->smin, basetype);
tp->basetype = basetype;
} else {
basetype = ord_type(tp->smin->val.type);
if (basetype->kind == TK_INTEGER) {
val = eval_expr(tp->smin);
if (val.type && val.i >= 0)
basetype = tp_unsigned;
else
basetype = tp_integer;
}
tp->basetype = basetype;
}
} else {
tp = tp_integer;
}
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
return tp;
}
void makefakestruct(tp, tname)
Type *tp;
Meaning *tname;
{
Symbol *sym;
if (!tname)
return;
while (tp && (tp->kind == TK_ARRAY || tp->kind == TK_FILE))
tp = tp->basetype;
if (tp && tp->kind == TK_RECORD && !tp->meaning) {
sym = findsymbol(format_s(name_FAKESTRUCT, tname->name));
silentalreadydef++;
tp->meaning = addmeaning(sym, MK_TYPE);
silentalreadydef--;
tp->meaning->type = tp;
tp->meaning->refcount++;
declaretype(tp->meaning);
}
}
Type *p_type(tname)
Meaning *tname;
{
Type *tp;
int ispacked = 0;
Meaning **flast;
Meaning *mp;
Strlist *sl;
int num, isfunc, saveind, savenotephase, sizespec;
Expr *ex;
Value val;
static int proctypecount = 0;
p_attributes();
sizespec = size_attributes();
ignore_attributes();
tp = tp_integer;
if (curtok == TOK_PACKED) {
ispacked = 1;
gettok();
}
checkkeyword(TOK_VARYING);
if (modula2)
checkkeyword(TOK_POINTER);
switch (curtok) {
case TOK_RECORD:
gettok();
savenotephase = notephase;
notephase = 1;
tp = maketype(TK_RECORD);
p_fieldlist(tp, &(tp->fbase), ispacked, tname);
notephase = savenotephase;
if (!wneedtok(TOK_END)) {
skippasttoken(TOK_END);
}
break;
case TOK_ARRAY:
gettok();
if (!modula2) {
if (!wneedtok(TOK_LBR))
break;
}
tp = p_arraydecl(tname ? tname->name : NULL, ispacked, NULL);
makefakestruct(tp, tname);
break;
case TOK_VARYING:
gettok();
tp = maketype(TK_STRING);
if (wneedtok(TOK_LBR)) {
ex = p_ord_expr();
if (!wneedtok(TOK_RBR))
skippasttoken(TOK_RBR);
} else
ex = makeexpr_long(stringdefault);
if (wneedtok(TOK_OF))
tp->basetype = p_type(NULL);
else
tp->basetype = tp_char;
val = eval_expr(ex);
if (val.type) {
if (val.i > 255 && val.i > stringceiling) {
note(format_d("Strings longer than %d may have problems [109]",
stringceiling));
}
if (stringceiling != 255 &&
(val.i >= 255 || val.i > stringceiling)) {
freeexpr(ex);
ex = makeexpr_long(stringceiling);
}
}
tp->indextype = makesubrangetype(tp_integer, makeexpr_long(0), ex);
break;
case TOK_SET:
gettok();
if (!wneedtok(TOK_OF))
break;
tp = p_type(NULL);
if (tp == tp_integer || tp == tp_unsigned)
tp = makesubrangetype(tp, makeexpr_long(0),
makeexpr_long(defaultsetsize-1));
tp = makesettype(tp);
break;
case TOK_FILE:
gettok();
tp = maketype(TK_FILE);
if (curtok == TOK_OF) {
gettok();
tp->basetype = p_type(NULL);
} else {
tp->basetype = tp_abyte;
}
if (tp->basetype->kind == TK_CHAR && charfiletext) {
tp = tp_text;
} else {
makefakestruct(tp, tname);
tp = makepointertype(tp);
}
break;
case TOK_PROCEDURE:
case TOK_FUNCTION:
isfunc = (curtok == TOK_FUNCTION);
gettok();
if (curtok != TOK_LPAR && !isfunc && hasstaticlinks == 1) {
tp = tp_proc;
break;
}
proctypecount++;
mp = addmeaning(findsymbol(format_d("__PROCPTR%d",
proctypecount)),
MK_FUNCTION);
pushctx(mp);
tp = maketype((hasstaticlinks != 0) ? TK_PROCPTR : TK_CPROCPTR);
tp->basetype = p_funcdecl(&isfunc, 1);
tp->fbase = mp; /* (saved, but not currently used) */
tp->escale = hasstaticlinks;
popctx();
break;
case TOK_HAT:
case TOK_ADDR:
case TOK_POINTER:
if (curtok == TOK_POINTER) {
gettok();
wneedtok(TOK_TO);
if (curtok == TOK_IDENT && !strcmp(curtokbuf, "WORD")) {
tp = tp_anyptr;
gettok();
break;
}
} else
gettok();
p_attributes();
ignore_attributes();
tp = maketype(TK_POINTER);
if (curtok == TOK_IDENT &&
(!curtokmeaning || curtokmeaning->kind != MK_TYPE ||
(deferallptrs && curtokmeaning->ctx != curctx))) {
struct ptrdesc *pd;
pd = ALLOC(1, struct ptrdesc, ptrdescs);
pd->sym = curtoksym;
pd->tp = tp;
pd->next = ptrbase;
ptrbase = pd;
tp->basetype = tp_abyte;
anydeferredptrs = 1;
gettok();
} else {
tp->basetype = p_type(NULL);
if (!tp->basetype->pointertype)
tp->basetype->pointertype = tp;
}
break;
case TOK_LPAR:
if (!useenum)
outsection(minorspace);
enum_tname = tname;
tp = maketype(TK_ENUM);
flast = &(tp->fbase);
num = 0;
do {
gettok();
if (!wexpecttok(TOK_IDENT)) {
skiptotoken(TOK_RPAR);
break;
}
sl = strlist_find(constmacros, curtoksym->name);
mp = addmeaningas(curtoksym, MK_CONST,
(*enumformat) ? MK_VARIANT :
(useenum) ? MK_VAR : MK_CONST);
mp->val.type = tp;
mp->val.i = num++;
mp->type = tp;
if (sl) {
mp->constdefn = (Expr *)sl->value;
mp->anyvarflag = 1; /* Make sure constant is folded */
strlist_delete(&constmacros, sl);
if (mp->constdefn->kind == EK_NAME)
strchange(&mp->name, mp->constdefn->val.s);
} else {
if (!useenum) {
output(format_s("#define %s", mp->name));
mp->isreturn = 1;
out_spaces(constindent, 0, 0, 0);
saveind = outindent;
outindent = cur_column();
output(format_d("%d\n", mp->val.i));
outindent = saveind;
}
}
*flast = mp;
flast = &(mp->xnext);
gettok();
} while (curtok == TOK_COMMA);
if (!wneedtok(TOK_RPAR))
skippasttoken(TOK_RPAR);
tp->smin = makeexpr_long(0);
tp->smax = makeexpr_long(num-1);
if (!useenum)
outsection(minorspace);
break;
case TOK_LBR:
tp = p_modula_subrange(NULL);
break;
case TOK_IDENT:
if (!curtokmeaning) {
undefsym(curtoksym);
tp = tp_integer;
mp = addmeaning(curtoksym, MK_TYPE);
mp->type = tp;
gettok();
break;
} else if (curtokmeaning == mp_string) {
gettok();
tp = maketype(TK_STRING);
tp->basetype = tp_char;
if (curtok == TOK_LBR) {
gettok();
ex = p_ord_expr();
if (!wneedtok(TOK_RBR))
skippasttoken(TOK_RBR);
} else {
ex = makeexpr_long(stringdefault);
}
val = eval_expr(ex);
if (val.type && stringceiling != 255 &&
(val.i >= 255 || val.i > stringceiling)) {
freeexpr(ex);
ex = makeexpr_long(stringceiling);
}
tp->indextype = makesubrangetype(tp_integer, makeexpr_long(0), ex);
break;
} else if (curtokmeaning->kind == MK_TYPE) {
tp = curtokmeaning->type;
if (sizespec > 0) {
if (ord_type(tp)->kind == TK_INTEGER && sizespec <= 32) {
if (checkconst(tp->smin, 0)) {
if (sizespec == 32)
tp = tp_unsigned;
else
tp = makesubrangetype(tp_unsigned,
makeexpr_long(0),
makeexpr_long((1L << sizespec) - 1));
} else {
tp = makesubrangetype(tp_integer,
makeexpr_long(- ((1L << (sizespec-1)))),
makeexpr_long((1L << (sizespec-1)) - 1));
}
sizespec = -1;
}
}
gettok();
if (curtok == TOK_LBR) {
if (modula2) {
tp = p_modula_subrange(tp);
} else {
gettok();
ex = p_expr(tp_integer);
note("UCSD size spec ignored; using 'long int' [110]");
if (ord_type(tp)->kind == TK_INTEGER)
tp = tp_integer;
if (!wneedtok(TOK_RBR))
skippasttotoken(TOK_RBR, TOK_SEMI);
}
}
break;
}
/* fall through */
default:
tp = maketype(TK_SUBR);
tp->smin = p_ord_expr();
if (wexpecttok(TOK_DOTS)) {
gettok();
tp->smax = p_ord_expr();
if (tp->smax->val.type->kind == TK_REAL &&
tp->smax->kind == EK_CONST &&
strlen(tp->smax->val.s) == 12 &&
strcmp(tp->smax->val.s, "2147483648.0") >= 0 &&
strcmp(tp->smax->val.s, "4294967295.0") <= 0) {
tp = tp_unsigned;
break;
}
tp->basetype = ord_type(tp->smin->val.type);
} else {
tp = tp_integer;
}
break;
}
if (sizespec >= 0)
note(format_d("Don't know how to interpret size = %d bits [111]", sizespec));
return tp;
}
Type *p_funcdecl(isfunc, istype)
int *isfunc, istype;
{
Meaning *retmp = NULL, *mp, *firstmp, *lastmp, **prevm, **oldprevm;
Type *type, *tp;
enum meaningkind parkind;
int anyvarflag, constflag, volatileflag, num = 0;
Symbol *sym;
Expr *defval;
Token savetok;
Strlist *l1;
if (*isfunc || modula2) {
sym = findsymbol(format_s(name_RETV, curctx->name));
retmp = addmeaning(sym, MK_VAR);
retmp->isreturn = 1;
}
type = maketype(TK_FUNCTION);
if (curtok == TOK_LPAR) {
prevm = &type->fbase;
do {
gettok();
p_mech_spec(1);
p_attributes();
checkkeyword(TOK_ANYVAR);
if (curtok == TOK_VAR || curtok == TOK_ANYVAR) {
parkind = MK_VARPARAM;
anyvarflag = (curtok == TOK_ANYVAR);
gettok();
} else if (curtok == TOK_PROCEDURE || curtok == TOK_FUNCTION) {
savetok = curtok;
gettok();
wexpecttok(TOK_IDENT);
*prevm = firstmp = addmeaning(curtoksym, MK_PARAM);
prevm = &firstmp->xnext;
firstmp->anyvarflag = 0;
curtok = savetok; /* rearrange tokens to a proc ptr type! */
firstmp->type = p_type(firstmp);
continue;
} else {
parkind = MK_PARAM;
anyvarflag = 0;
}
oldprevm = prevm;
if (modula2 && istype) {
firstmp = addmeaning(findsymbol(format_d("_A%d", ++num)), parkind);
} else {
wexpecttok(TOK_IDENT);
firstmp = addmeaning(curtoksym, parkind);
gettok();
}
*prevm = firstmp;
prevm = &firstmp->xnext;
firstmp->isactive = 0; /* nit-picking Turbo compatibility */
lastmp = firstmp;
while (curtok == TOK_COMMA) {
gettok();
if (wexpecttok(TOK_IDENT)) {
*prevm = lastmp = addmeaning(curtoksym, parkind);
prevm = &lastmp->xnext;
lastmp->isactive = 0;
}
gettok();
}
constflag = volatileflag = 0;
defval = NULL;
if (curtok != TOK_COLON && !modula2) {
if (parkind != MK_VARPARAM)
wexpecttok(TOK_COLON);
parkind = MK_VARPARAM;
tp = tp_anyptr;
anyvarflag = 1;
} else {
if (curtok == TOK_COLON)
gettok();
if (curtok == TOK_IDENT && !curtokmeaning &&
!strcicmp(curtokbuf, "UNIV")) {
if (parkind == MK_PARAM)
note("UNIV may not work for non-VAR parameters [112]");
anyvarflag = 1;
gettok();
}
p_attributes();
if ((l1 = strlist_find(attrlist, "READONLY")) != NULL) {
constflag = 1;
strlist_delete(&attrlist, l1);
}
if ((l1 = strlist_find(attrlist, "VOLATILE")) != NULL) {
volatileflag = 1;
strlist_delete(&attrlist, l1);
}
if ((l1 = strlist_find(attrlist, "UNSAFE")) != NULL &&
parkind == MK_VARPARAM) {
anyvarflag = 1;
strlist_delete(&attrlist, l1);
}
if ((l1 = strlist_find(attrlist, "REFERENCE")) != NULL) {
note("REFERENCE attribute treated like VAR [107]");
parkind = MK_VARPARAM;
strlist_delete(&attrlist, l1);
}
checkkeyword(TOK_VARYING);
if (curtok == TOK_IDENT && curtokmeaning == mp_string &&
!anyvarflag && parkind == MK_VARPARAM) {
anyvarflag = (varstrings > 0);
tp = tp_str255;
gettok();
if (curtok == TOK_LBR) {
wexpecttok(TOK_SEMI);
skipparens();
}
} else if (curtok == TOK_ARRAY || curtok == TOK_PACKED ||
curtok == TOK_VARYING) {
prevm = oldprevm;
tp = p_conformant_array(firstmp->name, &prevm);
*prevm = firstmp;
while (*prevm)
prevm = &(*prevm)->xnext;
} else {
tp = p_type(firstmp);
}
if (!varfiles && isfiletype(tp))
parkind = MK_PARAM;
if (parkind == MK_VARPARAM)
tp = makepointertype(tp);
}
if (curtok == TOK_ASSIGN) { /* check for parameter default */
gettok();
p_mech_spec(0);
defval = gentle_cast(p_expr(tp), tp);
if ((tp->kind == TK_STRING || tp->kind == TK_ARRAY) &&
tp->basetype->kind == TK_CHAR &&
tp->structdefd && /* conformant string */
defval->val.type->kind == TK_STRING) {
mp = *oldprevm;
if (tp->kind == TK_ARRAY) {
mp->constdefn = makeexpr_long(1);
mp = mp->xnext;
}
mp->constdefn = strmax_func(defval);
}
}
while (firstmp) {
firstmp->type = tp;
firstmp->kind = parkind; /* in case it changed */
firstmp->isactive = 1;
firstmp->anyvarflag = anyvarflag;
firstmp->constqual = constflag;
firstmp->volatilequal = volatileflag;
if (defval) {
if (firstmp == lastmp)
firstmp->constdefn = defval;
else
firstmp->constdefn = copyexpr(defval);
}
if (parkind == MK_PARAM &&
(tp->kind == TK_STRING ||
tp->kind == TK_ARRAY ||
tp->kind == TK_SET ||
((tp->kind == TK_RECORD || tp->kind == TK_PROCPTR) && copystructs < 2))) {
firstmp->othername = stralloc(format_s(name_COPYPAR, firstmp->name));
firstmp->rectype = makepointertype(tp);
}
if (firstmp == lastmp)
break;
firstmp = firstmp->xnext;
}
} while (curtok == TOK_SEMI || curtok == TOK_COMMA);
if (!wneedtok(TOK_RPAR))
skippasttotoken(TOK_RPAR, TOK_SEMI);
}
if (modula2) {
if (curtok == TOK_COLON) {
*isfunc = 1;
} else {
unaddmeaning(retmp);
}
}
if (*isfunc) {
if (wneedtok(TOK_COLON)) {
retmp->type = type->basetype = p_type(NULL);
switch (retmp->type->kind) {
case TK_RECORD:
case TK_PROCPTR:
if (copystructs >= 3)
break;
/* fall through */
case TK_ARRAY:
case TK_STRING:
case TK_SET:
type->basetype = retmp->type = makepointertype(retmp->type);
retmp->kind = MK_VARPARAM;
retmp->anyvarflag = 0;
retmp->xnext = type->fbase;
type->fbase = retmp;
retmp->refcount++;
break;
default:
break;
}
} else
retmp->type = type->basetype = tp_integer;
} else
type->basetype = tp_void;
return type;
}
Symbol *findlabelsym()
{
if (curtok == TOK_IDENT &&
curtokmeaning && curtokmeaning->kind == MK_LABEL) {
#if 0
if (curtokmeaning->ctx != curctx && curtokmeaning->val.i != 0)
curtokmeaning->val.i = --nonloclabelcount;
#endif
} else if (curtok == TOK_INTLIT) {
strcpy(curtokcase, curtokbuf);
curtoksym = findsymbol(curtokbuf);
curtokmeaning = curtoksym->mbase;
while (curtokmeaning && !curtokmeaning->isactive)
curtokmeaning = curtokmeaning->snext;
if (!curtokmeaning || curtokmeaning->kind != MK_LABEL)
return NULL;
#if 0
if (curtokmeaning->ctx != curctx && curtokmeaning->val.i != 0)
if (curtokint == 0)
curtokmeaning->val.i = -1;
else
curtokmeaning->val.i = curtokint;
#endif
} else
return NULL;
return curtoksym;
}