diff --git a/sourcepawn/compiler/sc.h b/sourcepawn/compiler/sc.h index 43d0ae15..d89b282f 100644 --- a/sourcepawn/compiler/sc.h +++ b/sourcepawn/compiler/sc.h @@ -138,6 +138,7 @@ typedef struct s_symbol { constvalue *enumlist;/* list of names for the "root" of an enumeration */ struct { cell length; /* arrays: length (size) */ + cell slength; /* if a string index, this will be set to the original size */ short level; /* number of dimensions below this level */ } array; } dim; /* for 'dimension', both functions and arrays */ @@ -223,6 +224,7 @@ typedef struct s_symbol { #define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */ +#define uCOUNTOF 0x20 /* set in the "hasdefault" field of the arginfo struct */ #define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */ #define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */ @@ -286,7 +288,7 @@ typedef struct s_stringpair { */ #define tFIRST 256 /* value of first multi-character operator */ #define tMIDDLE 280 /* value of last multi-character operator */ -#define tLAST 331 /* value of last multi-character match-able token */ +#define tLAST 332 /* value of last multi-character match-able token */ /* multi-character operators */ #define taMULT 256 /* *= */ #define taDIV 257 /* /= */ @@ -318,65 +320,66 @@ typedef struct s_stringpair { #define tBEGIN 282 #define tBREAK 283 #define tCASE 284 -#define tCHAR 285 -#define tCONST 286 -#define tCONTINUE 287 -#define tDEFAULT 288 -#define tDEFINED 289 -#define tDO 290 -#define tELSE 291 -#define tEND 292 -#define tENUM 293 -#define tEXIT 294 -#define tFOR 295 -#define tFORWARD 296 -#define tFUNCENUM 297 -#define tGOTO 298 -#define tIF 299 -#define tNATIVE 300 -#define tNEW 301 -#define tDECL 302 -#define tOPERATOR 303 -#define tPUBLIC 304 -#define tRETURN 305 -#define tSIZEOF 306 -#define tSLEEP 307 -#define tSTATE 308 -#define tSTATIC 309 -#define tSTOCK 310 -#define tSTRUCT 311 -#define tSWITCH 312 -#define tTAGOF 313 -#define tTHEN 314 -#define tWHILE 315 +#define tCELLSOF 285 +#define tCHAR 286 +#define tCONST 287 +#define tCONTINUE 288 +#define tDEFAULT 289 +#define tDEFINED 290 +#define tDO 291 +#define tELSE 292 +#define tEND 293 +#define tENUM 294 +#define tEXIT 295 +#define tFOR 296 +#define tFORWARD 297 +#define tFUNCENUM 298 +#define tGOTO 299 +#define tIF 300 +#define tNATIVE 301 +#define tNEW 302 +#define tDECL 303 +#define tOPERATOR 304 +#define tPUBLIC 305 +#define tRETURN 306 +#define tSIZEOF 307 +#define tSLEEP 308 +#define tSTATE 309 +#define tSTATIC 310 +#define tSTOCK 311 +#define tSTRUCT 312 +#define tSWITCH 313 +#define tTAGOF 314 +#define tTHEN 315 +#define tWHILE 316 /* compiler directives */ -#define tpASSERT 316 /* #assert */ -#define tpDEFINE 317 -#define tpELSE 318 /* #else */ -#define tpELSEIF 319 /* #elseif */ -#define tpEMIT 320 -#define tpENDIF 321 -#define tpENDINPUT 322 -#define tpENDSCRPT 323 -#define tpERROR 324 -#define tpFILE 325 -#define tpIF 326 /* #if */ -#define tINCLUDE 327 -#define tpLINE 328 -#define tpPRAGMA 329 -#define tpTRYINCLUDE 330 -#define tpUNDEF 331 +#define tpASSERT 317 /* #assert */ +#define tpDEFINE 318 +#define tpELSE 319 /* #else */ +#define tpELSEIF 320 /* #elseif */ +#define tpEMIT 321 +#define tpENDIF 322 +#define tpENDINPUT 323 +#define tpENDSCRPT 324 +#define tpERROR 325 +#define tpFILE 326 +#define tpIF 327 /* #if */ +#define tINCLUDE 328 +#define tpLINE 329 +#define tpPRAGMA 330 +#define tpTRYINCLUDE 331 +#define tpUNDEF 332 /* semicolon is a special case, because it can be optional */ -#define tTERM 332 /* semicolon or newline */ -#define tENDEXPR 333 /* forced end of expression */ +#define tTERM 333 /* semicolon or newline */ +#define tENDEXPR 334 /* forced end of expression */ /* other recognized tokens */ -#define tNUMBER 334 /* integer number */ -#define tRATIONAL 335 /* rational number */ -#define tSYMBOL 336 -#define tLABEL 337 -#define tSTRING 338 -#define tEXPR 339 /* for assigment to "lastst" only (see SC1.C) */ -#define tENDLESS 340 /* endless loop, for assigment to "lastst" only */ +#define tNUMBER 335 /* integer number */ +#define tRATIONAL 336 /* rational number */ +#define tSYMBOL 337 +#define tLABEL 338 +#define tSTRING 339 +#define tEXPR 340 /* for assigment to "lastst" only (see SC1.C) */ +#define tENDLESS 341 /* endless loop, for assigment to "lastst" only */ /* (reversed) evaluation of staging buffer */ #define sSTARTREORDER 0x01 @@ -562,6 +565,8 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage); SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag, int dim[],int numdim,int idxtag[]); +SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag, + int dim[],int numdim,int idxtag[],int slength); SC_FUNC int getlabel(void); SC_FUNC char *itoh(ucell val); diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.c index 91a49386..784c6138 100644 --- a/sourcepawn/compiler/sc1.c +++ b/sourcepawn/compiler/sc1.c @@ -1930,6 +1930,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst char *str; int dim[sDIMEN_MAX]; int numdim; + int slength=0; short filenum; symbol *sym; constvalue *enumroot; @@ -1978,8 +1979,10 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst #endif dim[numdim++]=(int)size; } /* while */ - if (ident == iARRAY && tag == pc_tag_string && dim[numdim-1]) + if (ident == iARRAY && tag == pc_tag_string && dim[numdim-1]) { + slength=dim[numdim-1]; dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell); + } assert(sc_curstates==0); sc_curstates=getstates(name); if (sc_curstates<0) { @@ -2142,7 +2145,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst } /* if */ litidx=0; if (sym==NULL) { /* define only if not yet defined */ - sym=addvariable(name,address,ident,sGLOBAL,tag,dim,numdim,idxtag); + sym=addvariable2(name,address,ident,sGLOBAL,tag,dim,numdim,idxtag,slength); if (sc_curstates>0) attachstatelist(sym,sc_curstates); } else { /* if declared but not yet defined, adjust the variable's address */ @@ -2198,6 +2201,7 @@ static int declloc(int fstatic) int numdim; int fconst; int staging_start; + int slength = 0; fconst=matchtoken(tCONST); do { @@ -2270,8 +2274,10 @@ static int declloc(int fstatic) } while (matchtoken('[')); if (all_constant) { /* Change the last dimension to be based on chars instead if we have a string */ - if (tag == pc_tag_string && numdim && dim[numdim-1]) + if (tag == pc_tag_string && numdim && dim[numdim-1]) { + slength = dim[numdim-1]; dim[numdim-1] = (dim[numdim-1] + sizeof(cell)-1) / sizeof(cell); + } /* Scrap the code generated */ ident = iARRAY; stgdel(_index, _code); @@ -2307,12 +2313,12 @@ static int declloc(int fstatic) /* write zeros for uninitialized fields */ while (litidxx.tags.field=fieldtag; sym->dim.array.length=size; sym->dim.array.level=0; + sym->dim.array.slength=0; sym->parent=enumsym; /* add the constant to a separate list as well */ if (enumroot!=NULL) { @@ -4082,7 +4089,7 @@ static int argcompare(arginfo *a1,arginfo *a2) * Pawn currently does not forbid them) */ } else { if (result) { - if ((a1->hasdefault & uSIZEOF)!=0 || (a1->hasdefault & uTAGOF)!=0) + if ((a1->hasdefault & uSIZEOF)!=0 || (a1->hasdefault & uTAGOF)!=0 || (a1->hasdefault & uCOUNTOF)!=0) result= a1->hasdefault==a2->hasdefault && strcmp(a1->defvalue.size.symname,a2->defvalue.size.symname)==0 && a1->defvalue.size.level==a2->defvalue.size.level; @@ -4198,7 +4205,7 @@ static int declargs(symbol *sym,int chkshadow) if (arg.ident==iREFARRAY && arg.hasdefault) free(arg.defvalue.array.data); else if (arg.ident==iVARIABLE - && ((arg.hasdefault & uSIZEOF)!=0 || (arg.hasdefault & uTAGOF)!=0)) + && ((arg.hasdefault & uSIZEOF)!=0 || (arg.hasdefault & uTAGOF)!=0) || (arg.hasdefault & uCOUNTOF)!=0) free(arg.defvalue.size.symname); free(arg.tags); } /* if */ @@ -4245,7 +4252,9 @@ static int declargs(symbol *sym,int chkshadow) assert(sym->dim.arglist!=NULL); arglist=sym->dim.arglist; for (idx=0; idxname,name); arg->hasdefault=FALSE; /* preset (most common case) */ @@ -4321,8 +4333,10 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, arg->numdim+=1; } while (matchtoken('[')); ident=iREFARRAY; /* "reference to array" (is a pointer) */ - if (checktag(tags, numtags, pc_tag_string)) + if (checktag(tags, numtags, pc_tag_string)) { + slength = arg->dim[arg->numdim - 1]; arg->dim[arg->numdim - 1] = (size + sizeof(cell) - 1) / sizeof(cell); + } if (matchtoken('=')) { lexpush(); /* initials() needs the "=" token again */ assert(litidx==0); /* at the start of a function, this is reset */ @@ -4354,6 +4368,8 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, size_tag_token=(unsigned char)(matchtoken(tSIZEOF) ? uSIZEOF : 0); if (size_tag_token==0) size_tag_token=(unsigned char)(matchtoken(tTAGOF) ? uTAGOF : 0); + if (size_tag_token==0) + size_tag_token=(unsigned char)(matchtoken(tCELLSOF) ? uCOUNTOF : 0); if (size_tag_token!=0) { int paranthese; if (ident==iREFERENCE) @@ -4369,7 +4385,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, if ((arg->defvalue.size.symname=duplicatestring(name)) == NULL) error(103); /* insufficient memory */ arg->defvalue.size.level=0; - if (size_tag_token==uSIZEOF) { + if (size_tag_token==uSIZEOF || size_tag_token==uCOUNTOF) { while (matchtoken('[')) { arg->defvalue.size.level+=(short)1; needtoken(']'); @@ -4403,8 +4419,8 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, error(219,name); /* variable shadows another symbol */ /* add details of type and address */ assert(numtags>0); - argsym=addvariable(name,offset,ident,sLOCAL,tags[0], - arg->dim,arg->numdim,arg->idxtag); + argsym=addvariable2(name,offset,ident,sLOCAL,tags[0], + arg->dim,arg->numdim,arg->idxtag,slength); argsym->compound=0; if (ident==iREFERENCE) argsym->usage|=uREAD; /* because references are passed back */ diff --git a/sourcepawn/compiler/sc2.c b/sourcepawn/compiler/sc2.c index a1efb2aa..77365892 100644 --- a/sourcepawn/compiler/sc2.c +++ b/sourcepawn/compiler/sc2.c @@ -1877,7 +1877,7 @@ char *sc_tokens[] = { "*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=", "||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--", "...", "..", "::", - "assert", "*begin", "break", "case", "chars", "const", "continue", "default", + "assert", "*begin", "break", "case", "cellsof", "chars", "const", "continue", "default", "defined", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum", "goto", "if", "native", "new", "decl", "operator", "public", "return", "sizeof", "sleep", "state", "static", "stock", "struct", "switch", "tagof", "*then", "while", @@ -2793,6 +2793,12 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag, int dim[],int numdim,int idxtag[]) +{ + return addvariable2(name,addr,ident,vclass,tag,dim,numdim,idxtag,0); +} + +SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag, + int dim[],int numdim,int idxtag[],int slength) { symbol *sym; @@ -2814,6 +2820,10 @@ SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int for (level=0; leveldim.array.length=dim[level]; + if (tag == pc_tag_string && level == numdim - 1) + top->dim.array.slength=slength; + else + top->dim.array.slength=0; top->dim.array.level=(short)(numdim-level-1); top->x.tags.index=idxtag[level]; top->parent=parent; diff --git a/sourcepawn/compiler/sc3.c b/sourcepawn/compiler/sc3.c index e31e195c..f7fde4c9 100644 --- a/sourcepawn/compiler/sc3.c +++ b/sourcepawn/compiler/sc3.c @@ -992,7 +992,7 @@ static cell array_levelsize(symbol *sym,int level) sym=finddepend(sym); assert(sym!=NULL); } /* if */ - return sym->dim.array.length; + return (sym->dim.array.slength ? sym->dim.array.slength : sym->dim.array.length); } /* hier14 @@ -1559,12 +1559,67 @@ static int hier2(value *lval) if (subsym!=NULL) subsym=finddepend(subsym); } /* for */ - if (level>sym->dim.array.level+1) + if (level>sym->dim.array.level+1) { error(28,sym->name); /* invalid subscript */ - else if (level==sym->dim.array.level+1) + } else if (level==sym->dim.array.level+1) { lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1; - else + } else { lval->constval=array_levelsize(sym,level); + } + if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL) + error(224,st); /* indeterminate array size in "sizeof" expression */ + } /* if */ + ldconst(lval->constval,sPRI); + while (paranthese--) + needtoken(')'); + return FALSE; + case tCELLSOF: + paranthese=0; + while (matchtoken('(')) + paranthese++; + tok=lex(&val,&st); + if (tok!=tSYMBOL) + return error(20,st); /* illegal symbol name */ + sym=findloc(st); + if (sym==NULL) + sym=findglb(st,sSTATEVAR); + if (sym==NULL) + return error(17,st); /* undefined symbol */ + if (sym->ident==iCONSTEXPR) + error(39); /* constant symbol has no size */ + else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) + error(72); /* "function" symbol has no size */ + else if ((sym->usage & uDEFINE)==0) + return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */ + clear_value(lval); + lval->ident=iCONSTEXPR; + lval->constval=1; /* preset */ + if (sym->ident==iARRAY || sym->ident==iREFARRAY) { + int level; + symbol *idxsym=NULL; + symbol *subsym=sym; + for (level=0; matchtoken('['); level++) { + idxsym=NULL; + if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) { + char *idxname; + int cmptag=subsym->x.tags.index; + tokeninfo(&val,&idxname); + if ((idxsym=findconst(idxname,&cmptag))==NULL) + error(80,idxname); /* unknown symbol, or non-constant */ + else if (cmptag>1) + error(91,idxname); /* ambiguous constant */ + } /* if */ + needtoken(']'); + if (subsym!=NULL) + subsym=finddepend(subsym); + } /* for */ + if (level>sym->dim.array.level+1) { + error(28,sym->name); /* invalid subscript */ + } else if (level==sym->dim.array.level+1) { + lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1; + } else { + lval->constval=array_levelsize(sym,level); + } if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL) error(224,st); /* indeterminate array size in "sizeof" expression */ } /* if */