Add unstaged changes.

This commit is contained in:
David Anderson 2014-06-30 20:11:18 -07:00
parent 6f3b08bbae
commit beb557aa56
3 changed files with 160 additions and 164 deletions

View File

@ -1,3 +1,4 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
/* Pawn compiler
*
* Drafted after the Small-C compiler Version 2.01, originally created
@ -272,6 +273,7 @@ typedef struct {
int numdim;
int dim[sDIMEN_MAX];
int idxtag[sDIMEN_MAX];
cell array_size;
constvalue *enumroot;
// Type information.

View File

@ -121,8 +121,7 @@ static void attachstatelist(symbol *sym, int state_id);
static symbol *funcstub(int fnative, const funcstub_setup_t *setup);
static int newfunc(const funcstub_setup_t *setup,int fpublic,int fstatic,int stock,symbol **symp);
static int declargs(symbol *sym, int chkshadow, const int *thistag);
static void doarg(char *name,int ident,int offset,int tags[],int numtags,
int fpublic,int fconst,int chkshadow,arginfo *arg);
static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, arginfo *arg);
static void make_report(symbol *root,FILE *log,char *sourcefile);
static void reduce_referrers(symbol *root);
static long max_stacksize(symbol *root,int *recursion);
@ -3271,14 +3270,16 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
else
lextok(&tok);
type->ident = iVARIABLE;
if (tok.id == tCONST) {
if (type->usage & uCONST)
error(138);
type->usage |= uCONST;
lextok(&tok);
}
if (tok.id == '[') {
// Note: we could have already filled in the prefix array bits below, so we
// check that ident != iARRAY before looking for an open bracket.
if (type->ident != iARRAY && tok.id == '[') {
// Not yet supported for return vals. This is allowed with old decls, but
// it's a huge hack. For now we forbid it in new code until it works right.
if (flags & TYPEFLAG_RETURN)
@ -3291,7 +3292,7 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
}
type->dim[type->numdim++] = 0;
if (!needtoken(']'))
return FALSE;
goto err_out;
lextok(&tok);
}
type->ident = iARRAY;
@ -3330,14 +3331,14 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
break;
default:
error(122);
return FALSE;
goto err_out;
}
if (flags & TYPEFLAG_ARGUMENT) {
if (matchtoken('&')) {
if (type->ident == iARRAY) {
error(137);
return FALSE;
goto err_out;
}
type->ident = iREFERENCE;
}
@ -3346,6 +3347,11 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
type->tags[0] = type->tag;
type->numtags = 1;
return TRUE;
err_out:
type->tags[0] = type->tag;
type->numtags = 1;
return FALSE;
}
static void parse_old_array_dims(declinfo_t *decl, int flags)
@ -3370,11 +3376,11 @@ static void parse_old_array_dims(declinfo_t *decl, int flags)
return;
}
size = needsub(&type->idxtag[type->numdim], enumrootp);
if (size > INT_MAX)
type->array_size = needsub(&type->idxtag[type->numdim], enumrootp);
if (type->array_size > INT_MAX)
error(165);
type->dim[type->numdim++] = (int)size;
type->dim[type->numdim++] = type->array_size;
} while (matchtoken('['));
type->ident = iARRAY;
@ -3385,10 +3391,11 @@ static int parse_old_decl(declinfo_t *decl, int flags)
token_t tok;
typeinfo_t *type = &decl->type;
type->ident = iVARIABLE;
if (matchtoken(tCONST))
if (matchtoken(tCONST)) {
if (type->usage & uCONST)
error(138);
type->usage |= uCONST;
}
if (flags & TYPEFLAG_ARGUMENT) {
if (matchtoken('&'))
@ -3413,9 +3420,22 @@ static int parse_old_decl(declinfo_t *decl, int flags)
}
needtoken(':');
}
} else {
}
if (type->numtags == 0) {
if (matchtoken2(tLABEL, &tok))
type->tags[type->numtags++] = pc_addtag(tok.str);
else
type->tags[type->numtags++] = 0;
}
// All finished with tag stuff.
type->tag = type->tags[0];
// Look for varargs and end early.
if (matchtoken(tELLIPS)) {
type->ident = iVARARGS;
return TRUE;
}
if (flags & TYPEMASK_NAMED_DECL) {
@ -3430,15 +3450,14 @@ static int parse_old_decl(declinfo_t *decl, int flags)
parse_old_array_dims(decl, flags);
}
type->tag = type->tags[0];
return TRUE;
}
static int parse_new_decl(declinfo_t *decl, int flags)
static int parse_new_decl(declinfo_t *decl, const token_t *first, int flags)
{
token_t tok;
if (!parse_new_typeexpr(&decl->type, NULL, flags))
if (!parse_new_typeexpr(&decl->type, first, flags))
return FALSE;
if (!expecttoken(tSYMBOL, &tok))
return FALSE;
@ -3465,9 +3484,16 @@ static int parse_new_decl(declinfo_t *decl, int flags)
int parse_decl(declinfo_t *decl, int flags)
{
token_t tok;
token_ident_t ident;
memset(decl, 0, sizeof(*decl));
decl->type.ident = iVARIABLE;
// Must attempt to match const first, since it's a common prefix.
if (matchtoken(tCONST))
decl->type.usage |= uCONST;
// If parsing an argument, there are two simple checks for whether this is a
// new or old-style declaration.
if ((flags & TYPEFLAG_ARGUMENT) && (lexpeek('&') || lexpeek('{')))
@ -3478,22 +3504,51 @@ int parse_decl(declinfo_t *decl, int flags)
return parse_old_decl(decl, flags);
// Otherwise, we have to eat a symbol to tell.
if (lextok(&tok) == tSYMBOL) {
if (lexpeek('[') || lexpeek(tSYMBOL)) {
if (matchsymbol(&ident)) {
if (lexpeek(tSYMBOL)) {
// A new-style declaration only allows array dims or a symbol name, so
// this is a new-style declaration. Make sure to push back the first
// symbol.
lexpush();
return parse_new_decl(decl, flags);
return parse_new_decl(decl, &ident.tok, flags);
}
// Push the symbol back, we've got an old-style decl.
if ((flags & TYPEMASK_NAMED_DECL) && matchtoken('[')) {
// If we're not allowing postdims here, then it must be a newdecl.
if (flags & TYPEFLAG_NO_POSTDIMS) {
// Give the '[' and symbol back, since we're going to parse from the start.
lexpush();
lexpush();
return parse_new_decl(decl, NULL, flags);
}
// Oh no - we have to parse array dims before we can tell what kind of
// declarator this is. It could be either:
// "x[] y" (new-style), or
// "y[]," (old-style)
parse_old_array_dims(decl, flags);
if (matchtoken(tSYMBOL) || matchtoken('&')) {
// This must be a newdecl, "x[] y" or "x[] &y", the latter of which
// is illegal, but we flow it through the right path anyway.
lexpush();
return parse_new_decl(decl, &ident.tok, flags);
}
// The most basic - "x[]" and that's it. Well, we know it has no tag and
// we know its name. We might as well just complete the entire decl.
strcpy(decl->name, ident.name);
decl->type.tags[decl->type.numtags++] = 0;
decl->type.tag = decl->type.tags[0];
return TRUE;
}
// Give the symbol back to the lexer. This is an old decl.
lexpush();
return parse_old_decl(decl, flags);
}
// All else has failed. Probably got a type keyword. New-style.
return parse_new_decl(decl, flags);
return parse_new_decl(decl, NULL, flags);
}
void define_constructor(methodmap_t *map, methodmap_method_t *method)
@ -5318,11 +5373,11 @@ static int argcompare(arginfo *a1,arginfo *a2)
static int declargs(symbol *sym, int chkshadow, const int *thistag)
{
char *ptr;
int argcnt,oldargcnt,tok,tags[MAXTAGS],numtags;
int argcnt,oldargcnt,tok;
cell val;
arginfo arg, *arglist;
char name[sNAMEMAX+1];
int ident,fpublic,fconst;
int ident,fpublic;
int idx;
/* if the function is already defined earlier, get the number of arguments
@ -5333,9 +5388,6 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
while (sym->dim.arglist[oldargcnt].ident!=0)
oldargcnt++;
argcnt=0; /* zero aruments up to now */
ident=iVARIABLE;
numtags=0;
fconst=FALSE;
fpublic = (sym->usage & (uPUBLIC|uSTOCK))!=0;
if (thistag && *thistag != -1) {
@ -5370,52 +5422,43 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
/* the '(' parantheses has already been parsed */
if (!matchtoken(')')){
do { /* there are arguments; process them */
/* any legal name increases argument count (and stack offset) */
tok=lex(&val,&ptr);
switch (tok) {
case 0:
/* nothing */
break;
case '&':
if (ident!=iVARIABLE || numtags>0)
error(1,"-identifier-","&");
ident=iREFERENCE;
break;
case tCONST:
if (ident!=iVARIABLE || numtags>0)
error(1,"-identifier-","const");
fconst=TRUE;
break;
case tLABEL:
if (numtags>0)
error(1,"-identifier-","-tagname-");
tags[0]=pc_addtag(ptr);
numtags=1;
break;
case '{':
if (numtags>0)
error(1,"-identifier-","-tagname-");
numtags=0;
while (numtags<MAXTAGS) {
if (!matchtoken('_') && !needtoken(tSYMBOL))
break;
tokeninfo(&val,&ptr);
tags[numtags++]=pc_addtag(ptr);
if (matchtoken('}'))
break;
needtoken(',');
} /* for */
needtoken(':');
tok=tLABEL; /* for outer loop: flag that we have seen a tagname */
break;
case tSYMBOL:
if (argcnt>=sMAXARGS)
error(45); /* too many function arguments */
strcpy(name,ptr); /* save symbol name */
if (name[0]==PUBLIC_CHAR)
error(56,name); /* function arguments cannot be public */
if (numtags==0)
tags[numtags++]=0; /* default tag */
declinfo_t decl;
parse_decl(&decl, TYPEFLAG_ARGUMENT|TYPEFLAG_ENUMROOT);
assert(decl.type.numtags > 0);
if (decl.type.ident == iVARARGS) {
assert(decl.type.numtags > 0);
if ((sym->usage & uPROTOTYPED)==0) {
/* redimension the argument list, add the entry iVARARGS */
sym->dim.arglist=(arginfo*)realloc(sym->dim.arglist,(argcnt+2)*sizeof(arginfo));
if (sym->dim.arglist==0)
error(163); /* insufficient memory */
memset(&sym->dim.arglist[argcnt+1],0,sizeof(arginfo)); /* keep the list terminated */
sym->dim.arglist[argcnt].ident=iVARARGS;
sym->dim.arglist[argcnt].hasdefault=FALSE;
sym->dim.arglist[argcnt].defvalue.val=0;
sym->dim.arglist[argcnt].defvalue_tag=0;
sym->dim.arglist[argcnt].numtags=decl.type.numtags;
sym->dim.arglist[argcnt].tags=(int*)malloc(decl.type.numtags*sizeof decl.type.tags[0]);
if (sym->dim.arglist[argcnt].tags==NULL)
error(163); /* insufficient memory */
memcpy(sym->dim.arglist[argcnt].tags,decl.type.tags,decl.type.numtags*sizeof decl.type.tags[0]);
} else {
if (argcnt>oldargcnt || sym->dim.arglist[argcnt].ident!=iVARARGS)
error(25); /* function definition does not match prototype */
} /* if */
argcnt++;
continue;
}
if (argcnt>=sMAXARGS)
error(45);
if (decl.name[0] == PUBLIC_CHAR)
error(56,name); /* function arguments cannot be public */
if (1) {
if (decl.type.ident == iARRAY)
decl.type.ident = iREFARRAY;
/* Stack layout:
* base + 0*sizeof(cell) == previous "base"
* base + 1*sizeof(cell) == function return address
@ -5423,10 +5466,11 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
* base + 3*sizeof(cell) == first argument of the function
* So the offset of each argument is "(argcnt+3) * sizeof(cell)".
*/
doarg(name,ident,(argcnt+3)*sizeof(cell),tags,numtags,fpublic,fconst,chkshadow,&arg);
/* :TODO: fix this so stocks that are func pointers can't have default arguments? */
doarg(&decl,(argcnt+3)*sizeof(cell),fpublic,chkshadow,&arg);
if ((sym->usage & uPUBLIC) && arg.hasdefault)
error(59,name); /* arguments of a public function may not have a default value */
if ((sym->usage & uPROTOTYPED)==0) {
/* redimension the argument list, add the entry */
sym->dim.arglist=(arginfo*)realloc(sym->dim.arglist,(argcnt+2)*sizeof(arginfo));
@ -5447,41 +5491,8 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
free(arg.tags);
} /* if */
argcnt++;
ident=iVARIABLE;
numtags=0;
fconst=FALSE;
break;
case tELLIPS:
if (ident!=iVARIABLE)
error(10); /* illegal function or declaration */
if (numtags==0)
tags[numtags++]=0; /* default tag */
if ((sym->usage & uPROTOTYPED)==0) {
/* redimension the argument list, add the entry iVARARGS */
sym->dim.arglist=(arginfo*)realloc(sym->dim.arglist,(argcnt+2)*sizeof(arginfo));
if (sym->dim.arglist==0)
error(163); /* insufficient memory */
memset(&sym->dim.arglist[argcnt+1],0,sizeof(arginfo)); /* keep the list terminated */
sym->dim.arglist[argcnt].ident=iVARARGS;
sym->dim.arglist[argcnt].hasdefault=FALSE;
sym->dim.arglist[argcnt].defvalue.val=0;
sym->dim.arglist[argcnt].defvalue_tag=0;
sym->dim.arglist[argcnt].numtags=numtags;
sym->dim.arglist[argcnt].tags=(int*)malloc(numtags*sizeof tags[0]);
if (sym->dim.arglist[argcnt].tags==NULL)
error(163); /* insufficient memory */
memcpy(sym->dim.arglist[argcnt].tags,tags,numtags*sizeof tags[0]);
} else {
if (argcnt>oldargcnt || sym->dim.arglist[argcnt].ident!=iVARARGS)
error(25); /* function definition does not match prototype */
} /* if */
argcnt++;
break;
default:
error(10); /* illegal function or declaration */
} /* switch */
} while (tok=='&' || tok==tLABEL || tok==tCONST
|| (tok!=tELLIPS && matchtoken(','))); /* more? */
}
} while (matchtoken(','));
/* if the next token is not ",", it should be ")" */
needtoken(')');
} /* if */
@ -5540,50 +5551,29 @@ static int declargs(symbol *sym, int chkshadow, const int *thistag)
* "fpublic" indicates whether the function for this argument list is public.
* The arguments themselves are never public.
*/
static void doarg(char *name,int ident,int offset,int tags[],int numtags,
int fpublic,int fconst,int chkshadow,arginfo *arg)
static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, arginfo *arg)
{
symbol *argsym;
constvalue *enumroot;
cell size;
int slength=0;
typeinfo_t *type = &decl->type;
strcpy(arg->name,name);
strcpy(arg->name, decl->name);
arg->hasdefault=FALSE; /* preset (most common case) */
arg->defvalue.val=0; /* clear */
arg->defvalue_tag=0;
arg->numdim=0;
if (matchtoken('[')) {
if (ident==iREFERENCE)
error(67,name); /* illegal declaration ("&name[]" is unsupported) */
do {
if (arg->numdim == sDIMEN_MAX) {
error(53); /* exceeding maximum number of dimensions */
return;
} /* if */
size=needsub(&arg->idxtag[arg->numdim],&enumroot);/* may be zero here, it is a pointer anyway */
#if INT_MAX < LONG_MAX
if (size > INT_MAX)
error(165); /* overflow, exceeding capacity */
#endif
arg->dim[arg->numdim]=(int)size;
arg->numdim+=1;
} while (matchtoken('['));
ident=iREFARRAY; /* "reference to array" (is a pointer) */
#if 0 /* For SM, multiple tags including string don't make sense,
so just check the first tag. Done manually so the string
tag isn't matched with the any tag. */
if (checktag(tags, numtags, pc_tag_string)) {
#endif
assert(tags!=0);
assert(numtags>0);
if (tags[0] == pc_tag_string) {
if (type->ident == iREFARRAY) {
arg->numdim = type->numdim;
memcpy(arg->dim, type->dim, sizeof(int) * type->numdim);
memcpy(arg->idxtag, type->idxtag, sizeof(int) * type->numdim);
assert(type->numtags > 0);
if (type->tags[0] == pc_tag_string) {
slength = arg->dim[arg->numdim - 1];
arg->dim[arg->numdim - 1] = (size + sizeof(cell) - 1) / sizeof(cell);
arg->dim[arg->numdim - 1] = (type->array_size + sizeof(cell) - 1) / sizeof(cell);
}
if (matchtoken('=')) {
assert(litidx==0); /* at the start of a function, this is reset */
assert(numtags>0);
/* Check if there is a symbol */
if (matchtoken(tSYMBOL)) {
symbol *sym;
@ -5603,8 +5593,8 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags,
}
}
} else {
initials2(ident,tags[0],&size,arg->dim,arg->numdim,enumroot, 1, 0);
assert(size>=litidx);
initials2(type->ident, type->tags[0], &type->array_size, arg->dim, arg->numdim, type->enumroot, 1, 0);
assert(type->array_size >= litidx);
/* allocate memory to hold the initial values */
arg->defvalue.array.data=(cell *)malloc(litidx*sizeof(cell));
if (arg->defvalue.array.data!=NULL) {
@ -5626,7 +5616,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags,
} else {
if (matchtoken('=')) {
unsigned char size_tag_token;
assert(ident==iVARIABLE || ident==iREFERENCE);
assert(type->ident==iVARIABLE || type->ident==iREFERENCE);
arg->hasdefault=TRUE; /* argument has a default value */
size_tag_token=(unsigned char)(matchtoken(tSIZEOF) ? uSIZEOF : 0);
if (size_tag_token==0)
@ -5635,8 +5625,8 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags,
size_tag_token=(unsigned char)(matchtoken(tCELLSOF) ? uCOUNTOF : 0);
if (size_tag_token!=0) {
int paranthese;
if (ident==iREFERENCE)
error(66,name); /* argument may not be a reference */
if (type->ident==iREFERENCE)
error(66, decl->name); /* argument may not be a reference */
paranthese=0;
while (matchtoken('('))
paranthese++;
@ -5654,41 +5644,41 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags,
needtoken(']');
} /* while */
} /* if */
if (ident==iVARIABLE) /* make sure we set this only if not a reference */
if (type->ident==iVARIABLE) /* make sure we set this only if not a reference */
arg->hasdefault |= size_tag_token; /* uSIZEOF or uTAGOF */
} /* if */
while (paranthese--)
needtoken(')');
} else {
constexpr(&arg->defvalue.val,&arg->defvalue_tag,NULL);
assert(numtags>0);
matchtag(tags[0],arg->defvalue_tag,TRUE);
assert(type->numtags > 0);
matchtag(type->tags[0], arg->defvalue_tag, TRUE);
} /* if */
} /* if */
} /* if */
arg->ident=(char)ident;
arg->usage=(char)(fconst ? uCONST : 0);
arg->numtags=numtags;
arg->tags=(int*)malloc(numtags*sizeof tags[0]);
arg->ident=(char)type->ident;
arg->usage=type->usage;
arg->numtags=type->numtags;
arg->tags=(int*)malloc(type->numtags * sizeof(type->tags[0]));
if (arg->tags==NULL)
error(163); /* insufficient memory */
memcpy(arg->tags,tags,numtags*sizeof tags[0]);
argsym=findloc(name);
memcpy(arg->tags, type->tags, type->numtags * sizeof(type->tags[0]));
argsym=findloc(decl->name);
if (argsym!=NULL) {
error(21,name); /* symbol already defined */
error(21, decl->name); /* symbol already defined */
} else {
if (chkshadow && (argsym=findglb(name,sSTATEVAR))!=NULL && argsym->ident!=iFUNCTN)
error(219,name); /* variable shadows another symbol */
if (chkshadow && (argsym=findglb(decl->name,sSTATEVAR))!=NULL && argsym->ident!=iFUNCTN)
error(219, decl->name); /* variable shadows another symbol */
/* add details of type and address */
assert(numtags>0);
argsym=addvariable2(name,offset,ident,sLOCAL,tags[0],
assert(type->numtags > 0);
argsym=addvariable2(decl->name,offset,type->ident,sLOCAL,type->tags[0],
arg->dim,arg->numdim,arg->idxtag,slength);
argsym->compound=0;
if (ident==iREFERENCE)
if (type->ident==iREFERENCE)
argsym->usage|=uREAD; /* because references are passed back */
if (fpublic)
argsym->usage|=uREAD; /* arguments of public functions are always "used" */
if (fconst)
if (type->usage & uCONST)
argsym->usage|=uCONST;
} /* if */
}

View File

@ -75,6 +75,10 @@ static short lastfile;
char *msg,*pre;
va_list argptr;
if (number == 47) {
printf("EGG\n");
}
// sErrLine is used to temporarily change the line number of reported errors.
// Pawn has an upstream bug where this is not reset on early-return, which
// can lead to broken line numbers in error messages.