added experimental new String tag. this tag will revert array usage to "char" sizing and packed strings
added experimental new String tag. this tag will revert array usage to "char" sizing and packed strings
1.1 --- a/sourcepawn/compiler/sc.h Tue Nov 07 00:53:06 2006 +0000
1.2 +++ b/sourcepawn/compiler/sc.h Tue Nov 07 09:50:09 2006 +0000
1.3 @@ -567,9 +567,13 @@
1.4 SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
1.5 value *lval,int *resulttag);
1.6 SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
1.7 +SC_FUNC int checktag(int tags[],int numtags,int exprtag);
1.8 SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult);
1.9 SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state);
1.10 SC_FUNC cell array_totalsize(symbol *sym);
1.11 +SC_FUNC int matchtag_string(int ident, int tag);
1.12 +SC_FUNC int checktag_string(value *sym1, value *sym2);
1.13 +SC_FUNC int checktags_string(int tags[], int numtags, value *sym1);
1.14
1.15 /* function prototypes in SC4.C */
1.16 SC_FUNC void writeleader(symbol *root);
1.17 @@ -809,6 +813,7 @@
1.18 SC_VDECL int pc_optimize; /* (peephole) optimization level */
1.19 SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
1.20 SC_VDECL int pc_functag; /* global function tag */
1.21 +SC_VDECL int pc_tag_string; /* global string tag */
1.22
1.23 SC_VDECL constvalue sc_automaton_tab; /* automaton table */
1.24 SC_VDECL constvalue sc_state_tab; /* state table */
2.1 --- a/sourcepawn/compiler/sc1.c Tue Nov 07 00:53:06 2006 +0000
2.2 +++ b/sourcepawn/compiler/sc1.c Tue Nov 07 09:50:09 2006 +0000
2.3 @@ -71,6 +71,7 @@
2.4 #define VERSION_INT 0x0302
2.5
2.6 int pc_functag = 0;
2.7 +int pc_tag_string = 0;
2.8
2.9 static void resetglobals(void);
2.10 static void initglobals(void);
2.11 @@ -683,7 +684,7 @@
2.12 verbosity=1; /* verbosity level, no copyright banner */
2.13 sc_debug=sCHKBOUNDS|sSYMBOLIC; /* sourcemod: full debug stuff */
2.14 pc_optimize=sOPTIMIZE_DEFAULT; /* sourcemod: full optimization */
2.15 - sc_packstr=FALSE; /* strings are unpacked by default */
2.16 + sc_packstr=TRUE; /* strings are packed by default */
2.17 sc_compress=FALSE; /* always disable compact encoding! */
2.18 sc_needsemicolon=FALSE;/* semicolon required to terminate expressions? */
2.19 sc_dataalign=sizeof(cell);
2.20 @@ -1248,6 +1249,7 @@
2.21 append_constval(&tagname_tab,"_",0,0);/* "untagged" */
2.22 append_constval(&tagname_tab,"bool",1,0);
2.23 pc_functag = pc_addfunctag("Function");
2.24 + pc_tag_string = pc_addtag("String");
2.25
2.26 add_constant("true",1,sGLOBAL,1); /* boolean flags */
2.27 add_constant("false",0,sGLOBAL,1);
2.28 @@ -1731,6 +1733,8 @@
2.29 #endif
2.30 dim[numdim++]=(int)size;
2.31 } /* while */
2.32 + if (ident == iARRAY && tag == pc_tag_string)
2.33 + dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell);
2.34 assert(sc_curstates==0);
2.35 sc_curstates=getstates(name);
2.36 if (sc_curstates<0) {
2.37 @@ -1989,6 +1993,9 @@
2.38 #endif
2.39 dim[numdim++]=(int)size;
2.40 } while (matchtoken('['));
2.41 + /* Change the last dimension to be based on chars instead if we have a string */
2.42 + if (tag == pc_tag_string)
2.43 + dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell);
2.44 } else if (matchtoken('(')) {
2.45 int dim_ident;
2.46 symbol *dim_sym;
2.47 @@ -2072,10 +2079,11 @@
2.48 /* simple variable, also supports initialization */
2.49 int ctag = tag; /* set to "tag" by default */
2.50 int explicit_init=FALSE;/* is the variable explicitly initialized? */
2.51 + int cident=ident;
2.52 if (matchtoken('=')) {
2.53 if (!autozero)
2.54 error(10);
2.55 - doexpr(FALSE,FALSE,FALSE,FALSE,&ctag,NULL,TRUE);
2.56 + cident=doexpr(FALSE,FALSE,FALSE,FALSE,&ctag,NULL,TRUE);
2.57 explicit_init=TRUE;
2.58 } else {
2.59 if (autozero)
2.60 @@ -2094,7 +2102,7 @@
2.61 assert(staging); /* end staging phase (optimize expression) */
2.62 stgout(staging_start);
2.63 stgset(FALSE);
2.64 - if (!matchtag(tag,ctag,TRUE))
2.65 + if (!matchtag_string(cident, ctag) && !matchtag(tag,ctag,TRUE))
2.66 error(213); /* tag mismatch */
2.67 /* if the variable was not explicitly initialized, reset the
2.68 * "uWRITTEN" flag that store() set */
2.69 @@ -2501,7 +2509,7 @@
2.70 error(6); /* must be assigned to an array */
2.71 litidx=1; /* reset literal queue */
2.72 } /* if */
2.73 - *tag=0;
2.74 + *tag=pc_tag_string;
2.75 } else if (constexpr(&i,tag,NULL)){
2.76 litadd(i); /* store expression result in literal table */
2.77 } else {
2.78 @@ -2702,6 +2710,7 @@
2.79 }
2.80 if (matchtoken('['))
2.81 {
2.82 + cell size;
2.83 if (arg->ident == iREFERENCE)
2.84 {
2.85 error(67, str);
2.86 @@ -2709,7 +2718,6 @@
2.87 do
2.88 {
2.89 constvalue *enumroot;
2.90 - cell size;
2.91 int ignore_tag;
2.92 if (arg->dimcount == sDIMEN_MAX)
2.93 {
2.94 @@ -2720,6 +2728,11 @@
2.95 arg->dims[arg->dimcount] = size;
2.96 arg->dimcount += 1;
2.97 } while (matchtoken('['));
2.98 + /* Handle strings */
2.99 + if (arg->tagcount == 1 && arg->tags[0] == pc_tag_string)
2.100 + {
2.101 + arg->dims[arg->dimcount-1] = (size + sizeof(cell)-1) / sizeof(cell);
2.102 + }
2.103 arg->ident=iREFARRAY;
2.104 } else if (arg->ident == 0) {
2.105 arg->ident = iVARIABLE;
2.106 @@ -2850,6 +2863,7 @@
2.107 constexpr(&size,&fieldtag,NULL); /* get size */
2.108 needtoken(']');
2.109 } /* if */
2.110 + /* :TODO: do we need a size modifier here for pc_tag_string? */
2.111 if (matchtoken('='))
2.112 constexpr(&value,NULL,NULL); /* get value */
2.113 /* add_constant() checks whether a variable (global or local) or
2.114 @@ -3355,6 +3369,9 @@
2.115 dim[numdim++]=(int)size;
2.116 } /* while */
2.117
2.118 + if (tag == pc_tag_string)
2.119 + dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell);
2.120 +
2.121 tok=lex(&val,&str);
2.122 fpublic=(tok==tPUBLIC) || (tok==tSYMBOL && str[0]==PUBLIC_CHAR);
2.123 if (fnative) {
2.124 @@ -3933,6 +3950,8 @@
2.125 arg->numdim+=1;
2.126 } while (matchtoken('['));
2.127 ident=iREFARRAY; /* "reference to array" (is a pointer) */
2.128 + if (checktag(tags, numtags, pc_tag_string))
2.129 + arg->dim[arg->numdim - 1] = (size + sizeof(cell) - 1) / sizeof(cell);
2.130 if (matchtoken('=')) {
2.131 lexpush(); /* initials() needs the "=" token again */
2.132 assert(litidx==0); /* at the start of a function, this is reset */
2.133 @@ -5682,7 +5701,7 @@
2.134 rettype|=uRETVALUE; /* function returns a value */
2.135 /* check tagname with function tagname */
2.136 assert(curfunc!=NULL);
2.137 - if (!matchtag(curfunc->tag,tag,TRUE))
2.138 + if (!matchtag_string(ident, tag) && !matchtag(curfunc->tag,tag,TRUE))
2.139 error(213); /* tagname mismatch */
2.140 if (ident==iARRAY || ident==iREFARRAY) {
2.141 int dim[sDIMEN_MAX],numdim;
3.1 --- a/sourcepawn/compiler/sc2.c Tue Nov 07 00:53:06 2006 +0000
3.2 +++ b/sourcepawn/compiler/sc2.c Tue Nov 07 09:50:09 2006 +0000
3.3 @@ -1795,7 +1795,7 @@
3.4 int i;
3.5 ucell val,c;
3.6
3.7 - i=sizeof(ucell)-(sCHARBITS/8); /* start at most significant byte */
3.8 + i=0; /* start at least significant byte */
3.9 val=0;
3.10 while (*lptr!='\"' && *lptr!='\0') {
3.11 if (*lptr=='\a') { /* ignore '\a' (which was inserted at a line concatenation) */
3.12 @@ -1806,14 +1806,16 @@
3.13 if (c>=(ucell)(1 << sCHARBITS))
3.14 error(43); /* character constant exceeds range */
3.15 val |= (c << 8*i);
3.16 - if (i==0) {
3.17 + if (i==sizeof(ucell)-(sCHARBITS/8)) {
3.18 litadd(val);
3.19 val=0;
3.20 - } /* if */
3.21 - i=(i+sizeof(ucell)-(sCHARBITS/8)) % sizeof(ucell);
3.22 + i=0;
3.23 + } else {
3.24 + i=i+1;
3.25 + }
3.26 } /* if */
3.27 /* save last code; make sure there is at least one terminating zero character */
3.28 - if (i!=(int)(sizeof(ucell)-(sCHARBITS/8)))
3.29 + if (i!=0)
3.30 litadd(val); /* at least one zero character in "val" */
3.31 else
3.32 litadd(0); /* add full cell of zeros */
3.33 @@ -1875,7 +1877,7 @@
3.34 "*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
3.35 "||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
3.36 "...", "..", "::",
3.37 - "assert", "*begin", "break", "case", "char", "const", "continue", "default",
3.38 + "assert", "*begin", "break", "case", "chars", "const", "continue", "default",
3.39 "defined", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum", "goto",
3.40 "if", "native", "new", "decl", "operator", "public", "return", "sizeof",
3.41 "sleep", "state", "static", "stock", "switch", "tagof", "*then", "while",
3.42 @@ -2008,6 +2010,7 @@
3.43 lptr+=1; /* skip double quote */
3.44 if ((stringflags & RAWMODE)!=0)
3.45 lptr+=1; /* skip "escape" character too */
3.46 + /* Note that this should always be packedstring() for SourcePawn */
3.47 lptr=sc_packstr ? packedstring(lptr,stringflags) : unpackedstring(lptr,stringflags);
3.48 if (*lptr=='\"')
3.49 lptr+=1; /* skip final quote */
4.1 --- a/sourcepawn/compiler/sc3.c Tue Nov 07 00:53:06 2006 +0000
4.2 +++ b/sourcepawn/compiler/sc3.c Tue Nov 07 09:50:09 2006 +0000
4.3 @@ -282,6 +282,44 @@
4.4 return TRUE;
4.5 }
4.6
4.7 +SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
4.8 +{
4.9 + int i;
4.10 + if (sym1->ident == iARRAY || sym1->ident == iREFARRAY)
4.11 + {
4.12 + return FALSE;
4.13 + }
4.14 + for (i=0; i<numtags; i++) {
4.15 + if ((sym1->tag == pc_tag_string && tags[i] == 0) ||
4.16 + (sym1->tag == 0 && tags[i] == pc_tag_string))
4.17 + return TRUE;
4.18 + }
4.19 + return FALSE;
4.20 +}
4.21 +
4.22 +SC_FUNC int checktag_string(value *sym1, value *sym2)
4.23 +{
4.24 + if (sym1->ident == iARRAY || sym2->ident == iARRAY
4.25 + || sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
4.26 + {
4.27 + return FALSE;
4.28 + }
4.29 + if ((sym1->tag == pc_tag_string && sym2->tag == 0)
4.30 + || (sym1->tag == 0 && sym2->tag == pc_tag_string))
4.31 + {
4.32 + return TRUE;
4.33 + }
4.34 +
4.35 + return FALSE;
4.36 +}
4.37 +
4.38 +SC_FUNC int matchtag_string(int ident, int tag)
4.39 +{
4.40 + if (ident == iARRAY || ident == iREFARRAY)
4.41 + return FALSE;
4.42 + return (tag == pc_tag_string) ? TRUE : FALSE;
4.43 +}
4.44 +
4.45 SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
4.46 {
4.47 if (formaltag!=actualtag) {
4.48 @@ -781,7 +819,7 @@
4.49 error(213); /* tagname mismatch */
4.50 lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult);
4.51 } else {
4.52 - if (!matchtag(lval1->tag,lval2->tag,FALSE))
4.53 + if (!checktag_string(lval1, lval2) && !matchtag(lval1->tag,lval2->tag,FALSE))
4.54 error(213); /* tagname mismatch */
4.55 (*oper)(); /* do the (signed) operation */
4.56 lval1->ident=iEXPRESSION;
4.57 @@ -1205,7 +1243,7 @@
4.58 check_userop(NULL,lval2.tag,lval3.tag,2,&lval3,&lval2.tag);
4.59 store(&lval3); /* now, store the expression result */
4.60 } /* if */
4.61 - if (!oper && !matchtag(lval3.tag,lval2.tag,TRUE))
4.62 + if (!oper && !checktag_string(&lval3, &lval2) && !matchtag(lval3.tag,lval2.tag,TRUE))
4.63 error(213); /* tagname mismatch (if "oper", warning already given in plunge2()) */
4.64 if (lval3.sym)
4.65 markusage(lval3.sym,uWRITTEN);
4.66 @@ -1658,6 +1696,10 @@
4.67 popreg(sPRI); /* restore PRI (result of rvalue()) */
4.68 sideeffect=TRUE;
4.69 return FALSE;
4.70 +/* This is temporarily disabled because we detect it automatically.
4.71 + * Thus, it could be weird if both were used at once
4.72 + */
4.73 +#if 0
4.74 case tCHAR: /* char (compute required # of cells */
4.75 if (lval->ident==iCONSTEXPR) {
4.76 lval->constval *= sCHARBITS/8; /* from char to bytes */
4.77 @@ -1670,6 +1712,7 @@
4.78 addr2cell(); /* truncate to number of cells */
4.79 } /* if */
4.80 return FALSE;
4.81 +#endif
4.82 default:
4.83 lexpush();
4.84 return lvalue;
4.85 @@ -1745,7 +1788,7 @@
4.86 assert(sym->dim.array.level>=0 && sym->dim.array.level<sDIMEN_MAX);
4.87 lval1->arrayidx[sym->dim.array.level]=lval2.constval;
4.88 } /* if */
4.89 - if (close==']') {
4.90 + if (close==']' && !(sym->tag == pc_tag_string && sym->dim.array.level == 0)) {
4.91 /* normal array index */
4.92 if (lval2.constval<0 || sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval)
4.93 error(32,sym->name); /* array index out of bounds */
4.94 @@ -1826,7 +1869,11 @@
4.95 } /* if */
4.96 assert(sym->dim.array.level==0);
4.97 /* set type to fetch... INDIRECTLY */
4.98 - lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
4.99 + if (sym->tag == pc_tag_string) {
4.100 + lval1->ident = iARRAYCHAR;
4.101 + } else {
4.102 + lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
4.103 + }
4.104 /* if the array index is a field from an enumeration, get the tag name
4.105 * from the field and save the size of the field too. Otherwise, the
4.106 * tag is the one from the array symbol.
4.107 @@ -2105,7 +2152,7 @@
4.108 return -1;
4.109 }
4.110
4.111 -static int checktag(int tags[],int numtags,int exprtag)
4.112 +int checktag(int tags[],int numtags,int exprtag)
4.113 {
4.114 int i;
4.115
4.116 @@ -2281,12 +2328,8 @@
4.117 heapalloc+=markheap(MEMUSE_STATIC, 1);
4.118 nest_stkusage++;
4.119 } /* if */
4.120 - } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION
4.121 - || lval.ident==iARRAYCHAR)
4.122 + } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION)
4.123 {
4.124 - /* fetch value if needed */
4.125 - if (lval.ident==iARRAYCHAR)
4.126 - rvalue(&lval);
4.127 /* allocate a cell on the heap and store the
4.128 * value (already in PRI) there */
4.129 setheap_pri(); /* address of the value on the heap in PRI */
4.130 @@ -2297,7 +2340,8 @@
4.131 /* otherwise, the address is already in PRI */
4.132 if (lval.sym!=NULL)
4.133 markusage(lval.sym,uWRITTEN);
4.134 - if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
4.135 + if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
4.136 + && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
4.137 error(213);
4.138 if (lval.tag!=0)
4.139 append_constval(&taglst,arg[argidx].name,lval.tag,0);
4.140 @@ -2311,14 +2355,15 @@
4.141 /* otherwise, the expression result is already in PRI */
4.142 assert(arg[argidx].numtags>0);
4.143 check_userop(NULL,lval.tag,arg[argidx].tags[0],2,NULL,&lval.tag);
4.144 - if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
4.145 + if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
4.146 + && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
4.147 error(213);
4.148 if (lval.tag!=0)
4.149 append_constval(&taglst,arg[argidx].name,lval.tag,0);
4.150 argidx++; /* argument done */
4.151 break;
4.152 case iREFERENCE:
4.153 - if (!lvalue || lval.ident==iARRAYCHAR)
4.154 + if (!lvalue)
4.155 error(35,argidx+1); /* argument type mismatch */
4.156 if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
4.157 error(35,argidx+1); /* argument type mismatch */
4.158 @@ -2343,7 +2388,7 @@
4.159 break;
4.160 case iREFARRAY:
4.161 if (lval.ident!=iARRAY && lval.ident!=iREFARRAY
4.162 - && lval.ident!=iARRAYCELL)
4.163 + && lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR)
4.164 {
4.165 error(35,argidx+1); /* argument type mismatch */
4.166 break;
4.167 @@ -2354,7 +2399,7 @@
4.168 * A literal array always has a single dimension.
4.169 * An iARRAYCELL parameter is also assumed to have a single dimension.
4.170 */
4.171 - if (lval.sym==NULL || lval.ident==iARRAYCELL) {
4.172 + if (lval.sym==NULL || lval.ident==iARRAYCELL || lval.ident==iARRAYCHAR) {
4.173 if (arg[argidx].numdim!=1) {
4.174 error(48); /* array dimensions must match */
4.175 } else if (arg[argidx].dim[0]!=0) {
4.176 @@ -2372,14 +2417,14 @@
4.177 error(47); /* array sizes must match */
4.178 } /* if */
4.179 } /* if */
4.180 - if (lval.ident!=iARRAYCELL) {
4.181 + if (lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR) {
4.182 /* save array size, for default values with uSIZEOF flag */
4.183 cell array_sz=lval.constval;
4.184 assert(array_sz!=0);/* literal array must have a size */
4.185 if (array_sz<0)
4.186 array_sz= -array_sz;
4.187 append_constval(&arrayszlst,arg[argidx].name,array_sz,0);
4.188 - } /* if */
4.189 + }/* if */
4.190 } else {
4.191 symbol *sym=lval.sym;
4.192 short level=0;
4.193 @@ -2669,6 +2714,7 @@
4.194 * value distinguishes between literal arrays
4.195 * and literal strings (this was done for
4.196 * array assignment). */
4.197 + lval->tag=pc_tag_string;
4.198 } else if (tok=='{') {
4.199 int tag,lasttag=-1;
4.200 val=litidx;
5.1 --- a/sourcepawn/compiler/sc4.c Tue Nov 07 00:53:06 2006 +0000
5.2 +++ b/sourcepawn/compiler/sc4.c Tue Nov 07 09:50:09 2006 +0000
5.3 @@ -961,12 +961,16 @@
5.4 * The ALIGN.pri/alt instructions must solve this machine dependence;
5.5 * that is, on Big Endian computers, ALIGN.pri/alt shuold do nothing
5.6 * and on Little Endian computers they should toggle the address.
5.7 + *
5.8 + * NOTE: For Source Pawn, this is fliped. It will do nothing on Little-Endian.
5.9 */
5.10 SC_FUNC void charalign(void)
5.11 {
5.12 +#if 0 /* TEMPORARILY DISABLED BECAUSE WE DON'T USE BIG ENDIAN */
5.13 stgwrite("\talign.pri ");
5.14 outval(sCHARBITS/8,TRUE);
5.15 code_idx+=opcodes(1)+opargs(1);
5.16 +#endif
5.17 }
5.18
5.19 /*