Update CS:GO team score gamedata.
1 /* Pawn compiler - Recursive descend expresion parser
3 * Copyright (c) ITB CompuPhase, 1997-2005
5 * This software is provided "as-is", without any express or implied warranty.
6 * In no event will the authors be held liable for any damages arising from
7 * the use of this software.
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software in
15 * a product, an acknowledgment in the product documentation would be
16 * appreciated but is not reeq;quired.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
25 #include <stdlib.h> /* for _MAX_PATH */
28 #include <alloc/fortify.h>
31 #include "sctracker.h"
33 static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
34 int (*hier)(value*),value *lval);
35 static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval);
36 static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
37 char *forcetag,int chkbitwise);
38 static int plnge1(int (*hier)(value *lval),value *lval);
39 static void plnge2(void (*oper)(void),
40 int (*hier)(value *lval),
41 value *lval1,value *lval2);
42 static cell calc(cell left,void (*oper)(),cell right,char *boolresult);
43 static int hier14(value *lval);
44 static int hier13(value *lval);
45 static int hier12(value *lval);
46 static int hier11(value *lval);
47 static int hier10(value *lval);
48 static int hier9(value *lval);
49 static int hier8(value *lval);
50 static int hier7(value *lval);
51 static int hier6(value *lval);
52 static int hier5(value *lval);
53 static int hier4(value *lval);
54 static int hier3(value *lval);
55 static int hier2(value *lval);
56 static int hier1(value *lval1);
57 static int primary(value *lval);
58 static void clear_value(value *lval);
59 static void callfunction(symbol *sym,value *lval_result,int matchparanthesis);
60 static int dbltest(void (*oper)(),value *lval1,value *lval2);
61 static int commutative(void (*oper)());
62 static int constant(value *lval);
64 static char lastsymbol[sNAMEMAX+1]; /* name of last function/variable */
65 static int bitwise_opercount; /* count of bitwise operators in an expression */
67 /* Function addresses of binary operators for signed operations */
68 static void (*op1[17])(void) = {
69 os_mult,os_div,os_mod, /* hier3, index 0 */
70 ob_add,ob_sub, /* hier4, index 3 */
71 ob_sal,os_sar,ou_sar, /* hier5, index 5 */
72 ob_and, /* hier6, index 8 */
73 ob_xor, /* hier7, index 9 */
74 ob_or, /* hier8, index 10 */
75 os_le,os_ge,os_lt,os_gt, /* hier9, index 11 */
76 ob_eq,ob_ne, /* hier10, index 15 */
78 /* These two functions are defined because the functions inc() and dec() in
79 * SC4.C have a different prototype than the other code generation functions.
80 * The arrays for user-defined functions use the function pointers for
81 * identifying what kind of operation is requested; these functions must all
82 * have the same prototype. As inc() and dec() are special cases already, it
83 * is simplest to add two "do-nothing" functions.
85 static void user_inc(void) {}
86 static void user_dec(void) {}
89 * Searches for a binary operator a list of operators. The list is stored in
90 * the array "list". The last entry in the list should be set to 0.
92 * The index of an operator in "list" (if found) is returned in "opidx". If
93 * no operator is found, nextop() returns 0.
95 * If an operator is found in the expression, it cannot be used in a function
96 * call with omitted parantheses. Mark this...
98 * Global references: sc_allowproccall (modified)
100 static int nextop(int *opidx,int *list)
104 if (matchtoken(*list)){
105 sc_allowproccall=FALSE;
106 return TRUE; /* found! */
112 return FALSE; /* entire list scanned, nothing found */
115 SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
116 value *lval,int *resulttag)
118 static char *binoperstr[] = { "*", "/", "%", "+", "-", "", "", "",
119 "", "", "", "<=", ">=", "<", ">", "==", "!=" };
120 static int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
121 FALSE, FALSE, FALSE, FALSE, FALSE,
122 TRUE, TRUE, TRUE, TRUE, FALSE, FALSE };
123 static char *unoperstr[] = { "!", "-", "++", "--" };
124 static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
125 char opername[4] = "", symbolname[sNAMEMAX+1];
126 int i,swapparams,savepri,savealt;
130 /* since user-defined operators on untagged operands are forbidden, we have
133 assert(numparam==1 || numparam==2);
134 if (tag1==0 && (numparam==1 || tag2==0))
137 savepri=savealt=FALSE;
138 /* find the name with the operator */
141 /* assignment operator: a special case */
142 strcpy(opername,"=");
143 if (lval!=NULL && (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR))
146 assert( (sizeof binoperstr / sizeof binoperstr[0]) == (sizeof op1 / sizeof op1[0]) );
147 for (i=0; i<sizeof op1 / sizeof op1[0]; i++) {
149 strcpy(opername,binoperstr[i]);
150 savepri=binoper_savepri[i];
158 /* try a select group of unary operators */
159 assert( (sizeof unoperstr / sizeof unoperstr[0]) == (sizeof unopers / sizeof unopers[0]) );
160 if (opername[0]=='\0') {
161 for (i=0; i<sizeof unopers / sizeof unopers[0]; i++) {
162 if (oper==unopers[i]) {
163 strcpy(opername,unoperstr[i]);
169 /* if not found, quit */
170 if (opername[0]=='\0')
173 /* create a symbol name from the tags and the operator name */
174 assert(numparam==1 || numparam==2);
175 operator_symname(symbolname,opername,tag1,tag2,numparam,tag2);
177 sym=findglb(symbolname,sGLOBAL);
178 if (sym==NULL /*|| (sym->usage & uDEFINE)==0*/) { /* ??? should not check uDEFINE; first pass clears these bits */
179 /* check for commutative operators */
180 if (tag1==tag2 || oper==NULL || !commutative(oper))
181 return FALSE; /* not commutative, cannot swap operands */
182 /* if arrived here, the operator is commutative and the tags are different,
183 * swap tags and try again
185 assert(numparam==2); /* commutative operator must be a binary operator */
186 operator_symname(symbolname,opername,tag2,tag1,numparam,tag1);
188 sym=findglb(symbolname,sGLOBAL);
189 if (sym==NULL /*|| (sym->usage & uDEFINE)==0*/)
193 /* check existance and the proper declaration of this function */
194 if ((sym->usage & uMISSING)!=0 || (sym->usage & uPROTOTYPED)==0) {
195 char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
196 funcdisplayname(symname,sym->name);
197 if ((sym->usage & uMISSING)!=0)
198 error(4,symname); /* function not defined */
199 if ((sym->usage & uPROTOTYPED)==0)
200 error(71,symname); /* operator must be declared before use */
203 /* we don't want to use the redefined operator in the function that
204 * redefines the operator itself, otherwise the snippet below gives
205 * an unexpected recursion:
206 * fixed:operator+(fixed:a, fixed:b)
212 /* for increment and decrement operators, the symbol must first be loaded
213 * (and stored back afterwards)
215 if (oper==user_inc || oper==user_dec) {
218 if (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR)
219 pushreg(sPRI); /* save current address in PRI */
220 rvalue(lval); /* get the symbol's value in PRI */
223 assert(!savepri || !savealt); /* either one MAY be set, but not both */
225 /* the chained comparison operators require that the ALT register is
226 * unmodified, so we save it here; actually, we save PRI because the normal
227 * instruction sequence (without user operator) swaps PRI and ALT
229 pushreg(sPRI); /* right-hand operand is in PRI */
230 } else if (savealt) {
231 /* for the assignment operator, ALT may contain an address at which the
232 * result must be stored; this address must be preserved accross the
235 assert(lval!=NULL); /* this was checked earlier */
236 assert(lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR); /* checked earlier */
240 /* push parameters, call the function */
241 paramspassed= (oper==NULL) ? 1 : numparam;
242 switch (paramspassed) {
247 /* note that 1) a function expects that the parameters are pushed
248 * in reversed order, and 2) the left operand is in the secondary register
249 * and the right operand is in the primary register */
261 markexpr(sPARM,NULL,0); /* mark the end of a sub-expression */
262 pushval((cell)paramspassed /* *sizeof(cell)*/ );
263 assert(sym->ident==iFUNCTN);
264 ffcall(sym,NULL,paramspassed);
265 if (sc_status!=statSKIP)
266 markusage(sym,uREAD); /* do not mark as "used" when this call itself is skipped */
267 if ((sym->usage & uNATIVE)!=0 && sym->x.lib!=NULL)
268 sym->x.lib->value += 1; /* increment "usage count" of the library */
269 sideeffect=TRUE; /* assume functions carry out a side-effect */
270 assert(resulttag!=NULL);
271 *resulttag=sym->tag; /* save tag of the called function */
273 if (savepri || savealt)
274 popreg(sALT); /* restore the saved PRI/ALT that into ALT */
275 if (oper==user_inc || oper==user_dec) {
277 if (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR)
278 popreg(sALT); /* restore address (in ALT) */
279 store(lval); /* store PRI in the symbol */
280 moveto1(); /* make sure PRI is restored on exit */
285 SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
288 if (sym1->ident == iARRAY || sym1->ident == iREFARRAY)
292 for (i=0; i<numtags; i++) {
293 if ((sym1->tag == pc_tag_string && tags[i] == 0) ||
294 (sym1->tag == 0 && tags[i] == pc_tag_string))
300 SC_FUNC int checktag_string(value *sym1, value *sym2)
302 if (sym1->ident == iARRAY || sym2->ident == iARRAY
303 || sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
307 if ((sym1->tag == pc_tag_string && sym2->tag == 0)
308 || (sym1->tag == 0 && sym2->tag == pc_tag_string))
316 SC_FUNC int matchtag_string(int ident, int tag)
318 if (ident == iARRAY || ident == iREFARRAY)
320 return (tag == pc_tag_string) ? TRUE : FALSE;
323 SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
325 if (formaltag != actualtag) {
326 /* if the formal tag is zero and the actual tag is not "fixed", the actual
327 * tag is "coerced" to zero
329 if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0) {
330 if (formaltag == pc_anytag || actualtag == pc_anytag)
335 if (formaltag & FUNCTAG)
337 if (actualtag == pc_functag || (formaltag == pc_functag && actualtag & FUNCTAG))
340 } else if (actualtag & FUNCTAG) {
341 constvalue *v = find_tag_byval(actualtag);
343 short usage = uPUBLIC;
344 symbol *sym, *found = NULL;
348 if (strncmp(v->name, "$Func", 5) != 0)
353 /* Now we have to go about looking up each function in this enum. WHICH IS IT. */
354 e = funcenums_find_byval(formaltag);
360 assert(v->name[5] == '@' || v->name[5] == '!');
362 /* Deduce which function type this is */
363 if (v->name[5] == '@')
366 } else if (v->name[5] == '!') {
370 index = atoi(&v->name[6]);
374 /* Find the function, either by public idx or code addr */
375 if (usage == uPUBLIC)
377 for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
378 if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->vclass == sGLOBAL))
387 } else if (usage == uSTOCK) {
388 for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
389 if (sym->ident==iFUNCTN && (sym->vclass == sGLOBAL))
391 if (sym->codeaddr == index)
407 * 1) The functional enum deduced from formaltag
408 * 2) The function trying to be shoved in deduced from actualtag
409 * Now we have to check if it matches any one of the functags inside the enum.
417 /* Check return type first. */
418 if (t->ret_tag != sym->tag)
424 if (t->type != usage)
429 /* Begin iterating arguments */
430 for (curarg=0; curarg<t->argcount; curarg++)
432 enum_arg = &t->args[curarg];
433 /* Check whether we've exhausted our arguments */
434 if (sym->dim.arglist[curarg].ident == 0)
436 /* Can we bail out early? */
437 if (!enum_arg->ommittable)
444 func_arg = &sym->dim.arglist[curarg];
445 /* First check the ident type */
446 if (enum_arg->ident != func_arg->ident)
451 /* Next check arrayness */
452 if (enum_arg->dimcount != func_arg->numdim)
457 if (enum_arg->dimcount > 0)
459 for (i=0; i<enum_arg->dimcount; i++)
461 if (enum_arg->dims[i] != func_arg->dim[i])
472 /* Lastly, check the tags */
473 if (enum_arg->tagcount != func_arg->numtags)
478 /* They should all be in the same order just for clarity... */
479 for (i=0; i<enum_arg->tagcount; i++)
481 if (enum_arg->tags[i] != func_arg->tags[i])
494 /* Make sure there are no trailing arguments */
495 if (sym->dim.arglist[curarg].ident == 0)
511 * The AMX pseudo-processor has no direct support for logical (boolean)
512 * operations. These have to be done via comparing and jumping. Since we are
513 * already jumping through the code, we might as well implement an "early
514 * drop-out" evaluation (also called "short-circuit"). This conforms to
517 * expr1 || expr2 expr2 will only be evaluated if expr1 is false.
518 * expr1 && expr2 expr2 will only be evaluated if expr1 is true.
520 * expr1 || expr2 && expr3 expr2 will only be evaluated if expr1 is false
521 * and expr3 will only be evaluated if expr1 is
522 * false and expr2 is true.
524 * Code generation for the last example proceeds thus:
528 * jump to "l1" if result of expr1 not equal to 0
530 * -> operator && found; skip to higher level in hierarchy diagram
531 * jump to "l2" if result of expr2 equal to 0
533 * jump to "l2" if result of expr3 equal to 0
534 * set expression result to 1 (true)
536 * l2: set expression result to 0 (false)
538 * <- drop back to previous hierarchy level
539 * jump to "l1" if result of expr2 && expr3 not equal to 0
540 * set expression result to 0 (false)
542 * l1: set expression result to 1 (true)
547 /* Skim over terms adjoining || and && operators
548 * dropval The value of the expression after "dropping out". An "or" drops
549 * out when the left hand is TRUE, so dropval must be 1 on "or"
551 * endval The value of the expression when no expression drops out. In an
552 * "or" expression, this happens when both the left hand and the
553 * right hand are FALSE, so endval must be 0 for "or" expressions.
555 static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
556 int (*hier)(value*),value *lval)
558 int lvalue,hits,droplab,endlab,opidx;
559 int allconst,foundop;
564 stgget(&index,&cidx); /* mark position in code generator */
565 hits=FALSE; /* no logical operators "hit" yet */
566 allconst=TRUE; /* assume all values "const" */
568 droplab=0; /* to avoid a compiler warning */
570 lvalue=plnge1(hier,lval); /* evaluate left expression */
572 allconst= allconst && (lval->ident==iCONSTEXPR);
575 /* one operator was already found */
576 if (testfunc==jmp_ne0)
577 lval->constval= lval->constval || constval;
579 lval->constval= lval->constval && constval;
581 constval=lval->constval; /* save result accumulated so far */
584 foundop=nextop(&opidx,opstr);
585 if ((foundop || hits) && (lval->ident==iARRAY || lval->ident==iREFARRAY))
586 error(33, lval->sym ? (lval->sym->name ? lval->sym->name : "-unknown") : "-unknown-"); /* array was not indexed in an expression */
589 /* this is the first operator in the list */
593 dropout(lvalue,testfunc,droplab,lval);
594 } else if (hits) { /* no (more) identical operators */
595 dropout(lvalue,testfunc,droplab,lval); /* found at least one operator! */
596 ldconst(endval,sPRI);
597 jumplabel(endlab=getlabel());
599 ldconst(dropval,sPRI);
602 lval->tag=pc_addtag("bool"); /* force tag to be "bool" */
604 lval->ident=iCONSTEXPR;
605 lval->constval=constval;
606 stgdel(index,cidx); /* scratch generated code and calculate */
608 lval->ident=iEXPRESSION;
613 return lvalue; /* none of the operators in "opstr" were found */
620 * Reads into the primary register the variable pointed to by lval if
621 * plunging through the hierarchy levels detected an lvalue. Otherwise
622 * if a constant was detected, it is loaded. If there is no constant and
623 * no lvalue, the primary register must already contain the expression
626 * After that, the compare routines "jmp_ne0" or "jmp_eq0" are called, which
627 * compare the primary register against 0, and jump to the "early drop-out"
628 * label "exit1" if the condition is true.
630 static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval)
634 else if (lval->ident==iCONSTEXPR)
635 ldconst(lval->constval,sPRI);
639 static void checkfunction(value *lval)
641 symbol *sym=lval->sym;
643 if (sym==NULL || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
644 return; /* no known symbol, or not a function result */
646 if ((sym->usage & uDEFINE)!=0) {
647 /* function is defined, can now check the return value (but make an
648 * exception for directly recursive functions)
650 if (sym!=curfunc && (sym->usage & uRETVALUE)==0) {
651 char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
652 funcdisplayname(symname,sym->name);
653 error(209,symname); /* function should return a value */
656 /* function not yet defined, set */
657 sym->usage|=uRETVALUE; /* make sure that a future implementation of
658 * the function uses "return <value>" */
663 * Plunge to a lower level
665 static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
666 char *forcetag,int chkbitwise)
672 lvalue=plnge1(hier,lval);
673 if (nextop(&opidx,opstr)==0)
674 return lvalue; /* no operator in "opstr" found */
679 if (chkbitwise && count++>0 && bitwise_opercount!=0)
681 opidx+=opoff; /* add offset to index returned by nextop() */
682 plnge2(op1[opidx],hier,lval,&lval2);
683 if (op1[opidx]==ob_and || op1[opidx]==ob_or)
686 lval->tag=pc_addtag(forcetag);
687 } while (nextop(&opidx,opstr)); /* do */
688 return FALSE; /* result of expression is not an lvalue */
693 * Binary plunge to lower level; this is very simular to plnge, but
694 * it has special code generation sequences for chained operations.
696 static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval)
703 /* this function should only be called for relational operators */
704 assert(op1[opoff]==os_le);
705 lvalue=plnge1(hier,lval);
706 if (nextop(&opidx,opstr)==0)
707 return lvalue; /* no operator in "opstr" found */
711 lval->boolresult=TRUE;
713 /* same check as in plnge(), but "chkbitwise" is always TRUE */
714 if (count>0 && bitwise_opercount!=0)
718 boolresult=lval->boolresult;
719 *lval=lval2; /* copy right hand expression of the previous iteration */
720 lval->boolresult=boolresult;
723 plnge2(op1[opidx],hier,lval,&lval2);
726 } while (nextop(&opidx,opstr)); /* enddo */
727 lval->constval=lval->boolresult;
728 lval->tag=pc_addtag("bool"); /* force tag to be "bool" */
729 return FALSE; /* result of expression is not an lvalue */
734 * Unary plunge to lower level
735 * Called by: skim(), plnge(), plnge2(), plnge_rel(), hier14() and hier13()
737 static int plnge1(int (*hier)(value *lval),value *lval)
742 stgget(&index,&cidx); /* mark position in code generator */
743 lvalue=(*hier)(lval);
744 if (lval->ident==iCONSTEXPR)
745 stgdel(index,cidx); /* load constant later */
751 * Binary plunge to lower level
752 * Called by: plnge(), plnge_rel(), hier14() and hier1()
754 static void plnge2(void (*oper)(void),
755 int (*hier)(value *lval),
756 value *lval1,value *lval2)
761 stgget(&index,&cidx); /* mark position in code generator */
762 if (lval1->ident==iCONSTEXPR) { /* constant on left side; it is not yet loaded */
763 if (plnge1(hier,lval2))
764 rvalue(lval2); /* load lvalue now */
765 else if (lval2->ident==iCONSTEXPR)
766 ldconst(lval2->constval<<dbltest(oper,lval2,lval1),sPRI);
767 ldconst(lval1->constval<<dbltest(oper,lval2,lval1),sALT);
768 /* ^ doubling of constants operating on integer addresses */
769 /* is restricted to "add" and "subtract" operators */
770 } else { /* non-constant on left side */
772 if (plnge1(hier,lval2))
774 if (lval2->ident==iCONSTEXPR) { /* constant on right side */
775 if (commutative(oper)) { /* test for commutative operators */
777 stgdel(index,cidx); /* scratch pushreg() and constant fetch (then
778 * fetch the constant again */
779 ldconst(lval2->constval<<dbltest(oper,lval1,lval2),sALT);
780 /* now, the primary register has the left operand and the secondary
781 * register the right operand; swap the "lval" variables so that lval1
782 * is associated with the secondary register and lval2 with the
783 * primary register, as is the "normal" case.
789 ldconst(lval2->constval<<dbltest(oper,lval1,lval2),sPRI);
790 popreg(sALT); /* pop result of left operand into secondary register */
792 } else { /* non-constants on both sides */
794 if (dbltest(oper,lval1,lval2))
795 cell2addr(); /* double primary register */
796 if (dbltest(oper,lval2,lval1))
797 cell2addr_alt(); /* double secondary register */
801 /* If used in an expression, a function should return a value.
802 * If the function has been defined, we can check this. If the
803 * function was not defined, we can set this requirement (so that
804 * a future function definition can check this bit.
806 checkfunction(lval1);
807 checkfunction(lval2);
808 if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
809 char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-";
810 error(33,ptr); /* array must be indexed */
811 } else if (lval2->ident==iARRAY || lval2->ident==iREFARRAY) {
812 char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-";
813 error(33,ptr); /* array must be indexed */
815 /* ??? ^^^ should do same kind of error checking with functions */
817 /* check whether an "operator" function is defined for the tag names
818 * (a constant expression cannot be optimized in that case)
820 if (check_userop(oper,lval1->tag,lval2->tag,2,NULL,&lval1->tag)) {
821 lval1->ident=iEXPRESSION;
823 } else if (lval1->ident==iCONSTEXPR && lval2->ident==iCONSTEXPR) {
824 /* only constant expression if both constant */
825 stgdel(index,cidx); /* scratch generated code and calculate */
826 if (!matchtag(lval1->tag,lval2->tag,FALSE))
827 error(213); /* tagname mismatch */
828 lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult);
830 if (!checktag_string(lval1, lval2) && !matchtag(lval1->tag,lval2->tag,FALSE))
831 error(213); /* tagname mismatch */
832 (*oper)(); /* do the (signed) operation */
833 lval1->ident=iEXPRESSION;
838 static cell flooreddiv(cell a,cell b,int return_remainder)
846 /* first implement truncated division in a portable way */
847 #define IABS(a) ((a)>=0 ? (a) : (-a))
850 q=-q; /* swap sign if either "a" or "b" is negative (but not both) */
851 r=a-q*b; /* calculate the matching remainder */
852 /* now "fiddle" with the values to get floored division */
853 if (r!=0 && (cell)(r ^ b)<0) {
857 return return_remainder ? r : q;
860 static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
863 return (left | right);
864 else if (oper==ob_xor)
865 return (left ^ right);
866 else if (oper==ob_and)
867 return (left & right);
868 else if (oper==ob_eq)
869 return (left == right);
870 else if (oper==ob_ne)
871 return (left != right);
872 else if (oper==os_le)
873 return *boolresult &= (char)(left <= right), right;
874 else if (oper==os_ge)
875 return *boolresult &= (char)(left >= right), right;
876 else if (oper==os_lt)
877 return *boolresult &= (char)(left < right), right;
878 else if (oper==os_gt)
879 return *boolresult &= (char)(left > right), right;
880 else if (oper==os_sar)
881 return (left >> (int)right);
882 else if (oper==ou_sar)
883 return ((ucell)left >> (ucell)right);
884 else if (oper==ob_sal)
885 return ((ucell)left << (int)right);
886 else if (oper==ob_add)
887 return (left + right);
888 else if (oper==ob_sub)
889 return (left - right);
890 else if (oper==os_mult)
891 return (left * right);
892 else if (oper==os_div)
893 return flooreddiv(left,right,0);
894 else if (oper==os_mod)
895 return flooreddiv(left,right,1);
897 error(29); /* invalid expression, assumed 0 (this should never occur) */
901 SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval)
908 /* scrap any arrays left on the heap */
911 if (lval.ident==iCONSTEXPR && val!=NULL) /* constant expression */
918 checkfunction(&lval);
924 SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
926 char name[sNAMEMAX+1];
931 assert(automaton!=NULL);
933 if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL))
936 tokeninfo(&val,&str);
937 assert(strlen(str)<sizeof name);
939 if (islabel || matchtoken(':')) {
940 /* token is an automaton name, add the name and get a new token */
941 *automaton=automaton_find(name);
942 /* read in the state name before checking the automaton, to keep the parser
943 * going (an "unknown automaton" error may occur when the "state" instruction
944 * precedes any state definition)
946 if (!needtoken(tSYMBOL))
948 tokeninfo(&val,&str); /* do not copy the name yet, must check automaton first */
949 if (*automaton==NULL) {
950 error(86,name); /* unknown automaton */
953 assert((*automaton)->index>0);
954 assert(strlen(str)<sizeof name);
957 *automaton=automaton_find("");
958 assert(*automaton!=NULL);
959 assert((*automaton)->index==0);
961 assert(*automaton!=NULL);
962 fsa=(*automaton)->index;
964 assert(*automaton!=NULL);
965 *state=state_find(name,fsa);
967 char *fsaname=(*automaton)->name;
970 error(87,name,fsaname); /* unknown state for automaton */
977 SC_FUNC cell array_totalsize(symbol *sym)
982 assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
983 length=sym->dim.array.length;
984 if (sym->dim.array.level > 0) {
985 cell sublength=array_totalsize(finddepend(sym));
987 length=length+length*sublength;
994 static cell array_levelsize(symbol *sym,int level)
997 assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
998 assert(level <= sym->dim.array.level);
999 while (level-- > 0) {
1000 sym=finddepend(sym);
1003 return (sym->dim.array.slength ? sym->dim.array.slength : sym->dim.array.length);
1008 * Lowest hierarchy level (except for the , operator).
1010 * Global references: sc_intest (reffered to only)
1011 * sc_allowproccall (modified)
1013 static int hier14(value *lval1)
1016 value lval2={0},lval3={0};
1021 int bwcount,leftarray;
1022 cell arrayidx1[sDIMEN_MAX],arrayidx2[sDIMEN_MAX]; /* last used array indices */
1025 bwcount=bitwise_opercount;
1026 bitwise_opercount=0;
1027 /* initialize the index arrays with unlikely constant indices; note that
1028 * these indices will only be changed when the array is indexed with a
1029 * constant, and that negative array indices are invalid (so actually, any
1030 * negative value would do).
1032 for (i=0; i<sDIMEN_MAX; i++)
1033 arrayidx1[i]=arrayidx2[i]=(cell)(-1L << (sizeof(cell)*8-1));
1034 org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */
1035 if (lval1->arrayidx==NULL)
1036 lval1->arrayidx=arrayidx1;
1037 lvalue=plnge1(hier13,lval1);
1038 if (lval1->ident!=iARRAYCELL && lval1->ident!=iARRAYCHAR)
1039 lval1->arrayidx=NULL;
1040 if (lval1->ident==iCONSTEXPR) /* load constant here */
1041 ldconst(lval1->constval,sPRI);
1077 case '=': /* simple assignment */
1080 error(211); /* possibly unintended assignment */
1084 bitwise_opercount=bwcount;
1085 lval1->arrayidx=org_arrayidx; /* restore array index pointer */
1089 /* if we get here, it was an assignment; first check a few special cases
1090 * and then the general */
1091 if (lval1->ident==iARRAYCHAR) {
1092 /* special case, assignment to packed character in a cell is permitted */
1094 } else if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
1095 /* array assignment is permitted too (with restrictions) */
1097 return error(23); /* array assignment must be simple assigment */
1098 assert(lval1->sym!=NULL);
1099 if (array_totalsize(lval1->sym)==0)
1100 return error(46,lval1->sym->name); /* unknown array size */
1104 /* operand on left side of assignment must be lvalue */
1106 return error(22); /* must be lvalue */
1107 /* may not change "constant" parameters */
1108 assert(lval1->sym!=NULL);
1109 if ((lval1->sym->usage & uCONST)!=0)
1110 return error(22); /* assignment to const argument */
1111 sc_allowproccall=FALSE; /* may no longer use "procedure call" syntax */
1113 lval3=*lval1; /* save symbol to enable storage of expresion result */
1114 lval1->arrayidx=org_arrayidx; /* restore array index pointer */
1115 if (lval1->ident==iARRAYCELL || lval1->ident==iARRAYCHAR
1116 || lval1->ident==iARRAY || lval1->ident==iREFARRAY)
1118 /* if indirect fetch: save PRI (cell address) */
1123 lval2.arrayidx=arrayidx2;
1124 plnge2(oper,hier14,lval1,&lval2);
1125 if (lval2.ident!=iARRAYCELL && lval2.ident!=iARRAYCHAR)
1126 lval2.arrayidx=NULL;
1129 if (!oper && lval3.arrayidx!=NULL && lval2.arrayidx!=NULL
1130 && lval3.ident==lval2.ident && lval3.sym==lval2.sym)
1133 assert(lval2.arrayidx==arrayidx2);
1134 for (i=0; i<sDIMEN_MAX; i++)
1135 same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
1137 error(226,lval3.sym->name); /* self-assignment */
1142 plnge2(oper,hier14,lval1,&lval2);
1144 /* if direct fetch and simple assignment: no "push"
1145 * and "pop" needed -> call hier14() directly, */
1147 rvalue(&lval2); /* instead of plnge2(). */
1148 else if (lval2.ident==iVARIABLE)
1149 lval2.ident=iEXPRESSION;/* mark as "rvalue" if it is not an "lvalue" */
1150 checkfunction(&lval2);
1151 /* check whether lval2 and lval3 (old lval1) refer to the same variable */
1152 if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) {
1153 assert(lval3.sym!=NULL);
1154 error(226,lval3.sym->name); /* self-assignment */
1158 /* Array elements are sometimes considered as sub-arrays --when the
1159 * array index is an enumeration field and the enumeration size is greater
1160 * than 1. If the expression on the right side of the assignment is a cell,
1161 * or if an operation is in effect, this does not apply.
1163 leftarray= lval3.ident==iARRAY || lval3.ident==iREFARRAY
1164 || ((lval3.ident==iARRAYCELL || lval3.ident==iARRAYCHAR)
1165 && lval3.constval>1 && lval3.sym->dim.array.level==0
1166 && !oper && (lval2.ident==iARRAY || lval2.ident==iREFARRAY));
1168 /* Left operand is an array, right operand should be an array variable
1169 * of the same size and the same dimension, an array literal (of the
1170 * same size) or a literal string. For single-dimensional arrays without
1171 * tag for the index, it is permitted to assign a smaller array into a
1172 * larger one (without warning). This is to make it easier to work with
1175 int exactmatch=TRUE;
1177 int ltlength=(int)lval3.sym->dim.array.length;
1178 if ((lval3.ident==iARRAYCELL || lval3.ident==iARRAYCHAR)
1179 && lval3.constval>0 && lval3.sym->dim.array.level==0)
1181 ltlength=(int)lval3.constval;
1183 if (lval2.ident!=iARRAY && lval2.ident!=iREFARRAY
1184 && (lval2.sym==NULL || lval2.constval<=0))
1185 error(33,lval3.sym->name); /* array must be indexed */
1186 if (lval2.sym!=NULL) {
1187 if (lval2.constval==0) {
1188 val=lval2.sym->dim.array.length;/* array variable */
1191 if (lval2.sym->dim.array.level!=0)
1192 error(28,lval2.sym->name);
1194 level=lval2.sym->dim.array.level;
1195 idxtag=lval2.sym->x.tags.index;
1196 if (level==0 && idxtag==0 && lval3.sym->x.tags.index==0)
1199 val=lval2.constval; /* literal array */
1201 /* If val is negative, it means that lval2 is a literal string.
1202 * The string array size may be smaller than the destination
1203 * array, provided that the destination array does not have an
1208 if (lval3.sym->x.tags.index==0)
1212 if (lval3.sym->dim.array.level!=level)
1213 return error(47); /* array dimensions must match */
1214 else if (ltlength<val || (exactmatch && ltlength>val) || val==0)
1215 return error(47); /* array sizes must match */
1216 else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE))
1217 error(229,(lval2.sym!=NULL) ? lval2.sym->name : lval3.sym->name); /* index tag mismatch */
1219 /* check the sizes of all sublevels too */
1220 symbol *sym1 = lval3.sym;
1221 symbol *sym2 = lval2.sym;
1224 assert(sym1!=NULL && sym2!=NULL);
1225 /* ^^^ sym2 must be valid, because only variables can be
1226 * multi-dimensional (there are no multi-dimensional literals),
1227 * sym1 must be valid because it must be an lvalue
1230 for (i=0; i<level; i++) {
1231 sym1=finddepend(sym1);
1232 sym2=finddepend(sym2);
1233 assert(sym1!=NULL && sym2!=NULL);
1234 /* ^^^ both arrays have the same dimensions (this was checked
1235 * earlier) so the dependend should always be found
1237 if (sym1->dim.array.length!=sym2->dim.array.length)
1238 error(47); /* array sizes must match */
1239 else if (!matchtag(sym1->x.tags.index,sym2->x.tags.index,TRUE))
1240 error(229,sym2->name); /* index tag mismatch */
1242 /* get the total size in cells of the multi-dimensional array */
1243 val=array_totalsize(lval3.sym);
1244 assert(val>0); /* already checked */
1247 /* left operand is not an array, right operand should then not be either */
1248 if (lval2.ident==iARRAY || lval2.ident==iREFARRAY)
1249 error(6); /* must be assigned to an array */
1252 memcopy(val*sizeof(cell));
1254 check_userop(NULL,lval2.tag,lval3.tag,2,&lval3,&lval2.tag);
1255 store(&lval3); /* now, store the expression result */
1257 if (!oper && !checktag_string(&lval3, &lval2) && !matchtag(lval3.tag,lval2.tag,TRUE))
1258 error(213); /* tagname mismatch (if "oper", warning already given in plunge2()) */
1260 markusage(lval3.sym,uWRITTEN);
1262 bitwise_opercount=bwcount;
1263 lval1->ident=iEXPRESSION;
1264 return FALSE; /* expression result is never an lvalue */
1268 * Sums up array usage in the current heap tracer and convert it into a dynamic array.
1269 * This is used for the ternary operator, which needs to convert its array usage into
1270 * something dynamically managed.
1272 * This might break if expressions can ever return dynamic arrays.
1273 * Thus, we assert() if something is non-static here.
1274 * Right now, this poses no problem because this type of expression is impossible:
1275 * (a() ? return_array() : return_array()) ? return_array() : return_array()
1278 long dynarray_from_heaplist(memuse_list_t *heap)
1280 memuse_t *use=heap->head;
1284 assert(use->type==MEMUSE_STATIC);
1292 setheap_save(-total*sizeof(cell));
1296 static int hier13(value *lval)
1298 int lvalue=plnge1(hier12,lval);
1299 if (matchtoken('?')) {
1300 int flab1=getlabel();
1301 int flab2=getlabel();
1305 memuse_list_t *heap;
1310 } else if (lval->ident==iCONSTEXPR) {
1311 ldconst(lval->constval,sPRI);
1312 error(lval->constval ? 206 : 205); /* redundant test */
1314 jmp_eq0(flab1); /* go to second expression if primary register==0 */
1315 PUSHSTK_I(sc_allowtags);
1316 sc_allowtags=FALSE; /* do not allow tagnames here (colon is a special token) */
1319 if (lval->ident==iCONSTEXPR) /* load constant here */
1320 ldconst(lval->constval,sPRI);
1321 sc_allowtags=(short)POPSTK_I(); /* restore */
1322 heap=popsaveheaplist();
1323 total1=dynarray_from_heaplist(heap);
1330 if (lval2.ident==iCONSTEXPR) /* load constant here */
1331 ldconst(lval2.constval,sPRI);
1332 array1= (lval->ident==iARRAY || lval->ident==iREFARRAY);
1333 array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY);
1334 if (!array1 && array2) {
1335 const char *ptr = "-unknown-";
1336 if (lval->sym != NULL && lval->sym->name != NULL)
1337 ptr = lval->sym->name;
1338 error(33,ptr); /* array must be indexed */
1339 } else if (array1 && !array2) {
1340 const char *ptr = "-unknown-";
1341 if (lval2.sym != NULL && lval2.sym->name != NULL)
1342 ptr = lval2.sym->name;
1343 error(33,ptr); /* array must be indexed */
1345 /* ??? if both are arrays, should check dimensions */
1346 if (!matchtag(lval->tag,lval2.tag,FALSE))
1347 error(213); /* tagname mismatch ('true' and 'false' expressions) */
1348 heap=popsaveheaplist();
1349 total2=dynarray_from_heaplist(heap);
1351 if ((array1 && array2) && (total1 && total2)) {
1352 markheap(MEMUSE_DYNAMIC, 0);
1354 /* If both sides are arrays, we should return the maximal as the lvalue.
1355 * Otherwise we could buffer overflow and the compiler is too stupid.
1356 * Literal strings have a constval == -(num_cells) so the cmp is flipped.
1358 if (lval->ident==iARRAY && lval2.ident==iARRAY
1359 && lval->constval < 0
1360 && lval->constval > lval2.constval) {
1363 if (lval->ident==iARRAY)
1364 lval->ident=iREFARRAY; /* iARRAY becomes iREFARRAY */
1365 else if (lval->ident!=iREFARRAY)
1366 lval->ident=iEXPRESSION; /* iREFARRAY stays iREFARRAY, rest becomes iEXPRESSION */
1367 return FALSE; /* conditional expression is no lvalue */
1373 /* the order of the operators in these lists is important and must be
1374 * the same as the order of the operators in the array "op1"
1376 static int list3[] = {'*','/','%',0};
1377 static int list4[] = {'+','-',0};
1378 static int list5[] = {tSHL,tSHR,tSHRU,0};
1379 static int list6[] = {'&',0};
1380 static int list7[] = {'^',0};
1381 static int list8[] = {'|',0};
1382 static int list9[] = {tlLE,tlGE,'<','>',0};
1383 static int list10[] = {tlEQ,tlNE,0};
1384 static int list11[] = {tlAND,0};
1385 static int list12[] = {tlOR,0};
1387 static int hier12(value *lval)
1389 return skim(list12,jmp_ne0,1,0,hier11,lval);
1392 static int hier11(value *lval)
1394 return skim(list11,jmp_eq0,0,1,hier10,lval);
1397 static int hier10(value *lval)
1399 return plnge(list10,15,hier9,lval,"bool",TRUE);
1400 } /* ^ this variable is the starting index in the op1[]
1401 * array of the operators of this hierarchy level */
1403 static int hier9(value *lval)
1404 { /* <=, >=, <, > */
1405 return plnge_rel(list9,11,hier8,lval);
1408 static int hier8(value *lval)
1410 return plnge(list8,10,hier7,lval,NULL,FALSE);
1413 static int hier7(value *lval)
1415 return plnge(list7,9,hier6,lval,NULL,FALSE);
1418 static int hier6(value *lval)
1420 return plnge(list6,8,hier5,lval,NULL,FALSE);
1423 static int hier5(value *lval)
1425 return plnge(list5,5,hier4,lval,NULL,FALSE);
1428 static int hier4(value *lval)
1430 return plnge(list4,3,hier3,lval,NULL,FALSE);
1433 static int hier3(value *lval)
1435 return plnge(list3,0,hier2,lval,NULL,FALSE);
1438 static int hier2(value *lval)
1449 case tINC: /* ++lval */
1451 return error(22); /* must be lvalue */
1452 assert(lval->sym!=NULL);
1453 if ((lval->sym->usage & uCONST)!=0)
1454 return error(22); /* assignment to const argument */
1455 if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag))
1456 inc(lval); /* increase variable first */
1457 rvalue(lval); /* and read the result into PRI */
1459 return FALSE; /* result is no longer lvalue */
1460 case tDEC: /* --lval */
1462 return error(22); /* must be lvalue */
1463 assert(lval->sym!=NULL);
1464 if ((lval->sym->usage & uCONST)!=0)
1465 return error(22); /* assignment to const argument */
1466 if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag))
1467 dec(lval); /* decrease variable first */
1468 rvalue(lval); /* and read the result into PRI */
1470 return FALSE; /* result is no longer lvalue */
1471 case '~': /* ~ (one's complement) */
1474 invert(); /* bitwise NOT */
1475 lval->constval=~lval->constval;
1477 case '!': /* ! (logical negate) */
1480 if (check_userop(lneg,lval->tag,0,1,NULL,&lval->tag)) {
1481 lval->ident=iEXPRESSION;
1484 lneg(); /* 0 -> 1, !0 -> 0 */
1485 lval->constval=!lval->constval;
1486 lval->tag=pc_addtag("bool");
1489 case '-': /* unary - (two's complement) */
1492 /* make a special check for a constant expression with the tag of a
1493 * rational number, so that we can simple swap the sign of that constant.
1495 if (lval->ident==iCONSTEXPR && lval->tag==sc_rationaltag && sc_rationaltag!=0) {
1496 if (rational_digits==0) {
1497 #if PAWN_CELL_SIZE==32
1498 float *f = (float *)&lval->constval;
1499 #elif PAWN_CELL_SIZE==64
1500 double *f = (double *)&lval->constval;
1502 #error Unsupported cell size
1504 *f= - *f; /* this modifies lval->constval */
1506 /* the negation of a fixed point number is just an integer negation */
1507 lval->constval=-lval->constval;
1509 } else if (check_userop(neg,lval->tag,0,1,NULL,&lval->tag)) {
1510 lval->ident=iEXPRESSION;
1513 neg(); /* arithmic negation */
1514 lval->constval=-lval->constval;
1517 case tLABEL: /* tagname override */
1525 while (matchtoken('('))
1529 return error(20,st); /* illegal symbol name */
1532 sym=findglb(st,sSTATEVAR);
1533 if (sym!=NULL && sym->ident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0)
1534 sym=NULL; /* symbol is not a function, it is in the table, but not "defined" */
1536 if (!val && find_subst(st,strlen(st))!=NULL)
1539 lval->ident=iCONSTEXPR;
1540 lval->constval= val;
1541 lval->tag=pc_addtag("bool");
1542 ldconst(lval->constval,sPRI);
1543 while (paranthese--)
1548 while (matchtoken('('))
1552 return error(20,st); /* illegal symbol name */
1555 sym=findglb(st,sSTATEVAR);
1557 return error(17,st); /* undefined symbol */
1558 if (sym->ident==iCONSTEXPR)
1559 error(39); /* constant symbol has no size */
1560 else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC)
1561 error(72); /* "function" symbol has no size */
1562 else if ((sym->usage & uDEFINE)==0)
1563 return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
1565 lval->ident=iCONSTEXPR;
1566 lval->constval=1; /* preset */
1567 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
1569 symbol *idxsym=NULL;
1571 for (level=0; matchtoken('['); level++) {
1573 if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
1575 int cmptag=subsym->x.tags.index;
1576 tokeninfo(&val,&idxname);
1577 if ((idxsym=findconst(idxname,&cmptag))==NULL)
1578 error(80,idxname); /* unknown symbol, or non-constant */
1580 error(91,idxname); /* ambiguous constant */
1584 subsym=finddepend(subsym);
1586 if (level>sym->dim.array.level+1) {
1587 error(28,sym->name); /* invalid subscript */
1588 } else if (level==sym->dim.array.level+1) {
1589 lval->constval=(idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
1591 lval->constval=array_levelsize(sym,level);
1593 if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL)
1594 error(224,st); /* indeterminate array size in "sizeof" expression */
1596 ldconst(lval->constval,sPRI);
1597 while (paranthese--)
1602 while (matchtoken('('))
1606 return error(20,st); /* illegal symbol name */
1609 sym=findglb(st,sSTATEVAR);
1611 return error(17,st); /* undefined symbol */
1612 if (sym->ident==iCONSTEXPR)
1613 error(39); /* constant symbol has no size */
1614 else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC)
1615 error(72); /* "function" symbol has no size */
1616 else if ((sym->usage & uDEFINE)==0)
1617 return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
1619 lval->ident=iCONSTEXPR;
1620 lval->constval=1; /* preset */
1621 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
1623 symbol *idxsym=NULL;
1625 for (level=0; matchtoken('['); level++) {
1627 if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
1629 int cmptag=subsym->x.tags.index;
1630 tokeninfo(&val,&idxname);
1631 if ((idxsym=findconst(idxname,&cmptag))==NULL)
1632 error(80,idxname); /* unknown symbol, or non-constant */
1634 error(91,idxname); /* ambiguous constant */
1638 subsym=finddepend(subsym);
1640 if (level>sym->dim.array.level+1) {
1641 error(28,sym->name); /* invalid subscript */
1642 } else if (level==sym->dim.array.level+1) {
1643 lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
1645 lval->constval=array_levelsize(sym,level);
1647 if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL)
1648 error(224,st); /* indeterminate array size in "sizeof" expression */
1650 ldconst(lval->constval,sPRI);
1651 while (paranthese--)
1656 while (matchtoken('('))
1659 if (tok!=tSYMBOL && tok!=tLABEL)
1660 return error(20,st); /* illegal symbol name */
1662 constvalue *tagsym=find_constval(&tagname_tab,st,0);
1663 tag=(int)((tagsym!=NULL) ? tagsym->value : 0);
1667 sym=findglb(st,sSTATEVAR);
1669 return error(17,st); /* undefined symbol */
1670 if ((sym->usage & uDEFINE)==0)
1671 return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
1674 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
1676 symbol *idxsym=NULL;
1678 for (level=0; matchtoken('['); level++) {
1680 if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
1682 int cmptag=subsym->x.tags.index;
1683 tokeninfo(&val,&idxname);
1684 if ((idxsym=findconst(idxname,&cmptag))==NULL)
1685 error(80,idxname); /* unknown symbol, or non-constant */
1687 error(91,idxname); /* ambiguous constant */
1691 subsym=finddepend(subsym);
1693 if (level>sym->dim.array.level+1)
1694 error(28,sym->name); /* invalid subscript */
1695 else if (level==sym->dim.array.level+1 && idxsym!=NULL)
1696 tag= idxsym->x.tags.index;
1700 lval->ident=iCONSTEXPR;
1701 lval->constval=tag | PUBLICTAG;
1702 ldconst(lval->constval,sPRI);
1703 while (paranthese--)
1709 /* check for postfix operators */
1710 if (matchtoken(';')) {
1711 /* Found a ';', do not look further for postfix operators */
1712 lexpush(); /* push ';' back after successful match */
1714 } else if (matchtoken(tTERM)) {
1715 /* Found a newline that ends a statement (this is the case when
1716 * semicolons are optional). Note that an explicit semicolon was
1717 * handled above. This case is similar, except that the token must
1718 * not be pushed back.
1724 case tINC: /* lval++ */
1726 return error(22); /* must be lvalue */
1727 assert(lval->sym!=NULL);
1728 if ((lval->sym->usage & uCONST)!=0)
1729 return error(22); /* assignment to const argument */
1730 /* on incrementing array cells, the address in PRI must be saved for
1731 * incremening the value, whereas the current value must be in PRI
1734 saveresult= (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR);
1736 pushreg(sPRI); /* save address in PRI */
1737 rvalue(lval); /* read current value into PRI */
1739 swap1(); /* save PRI on the stack, restore address in PRI */
1740 if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag))
1741 inc(lval); /* increase variable afterwards */
1743 popreg(sPRI); /* restore PRI (result of rvalue()) */
1745 return FALSE; /* result is no longer lvalue */
1746 case tDEC: /* lval-- */
1748 return error(22); /* must be lvalue */
1749 assert(lval->sym!=NULL);
1750 if ((lval->sym->usage & uCONST)!=0)
1751 return error(22); /* assignment to const argument */
1752 saveresult= (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR);
1754 pushreg(sPRI); /* save address in PRI */
1755 rvalue(lval); /* read current value into PRI */
1757 swap1(); /* save PRI on the stack, restore address in PRI */
1758 if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag))
1759 dec(lval); /* decrease variable afterwards */
1761 popreg(sPRI); /* restore PRI (result of rvalue()) */
1764 /* This is temporarily disabled because we detect it automatically.
1765 * Thus, it could be weird if both were used at once
1768 case tCHAR: /* char (compute required # of cells */
1769 if (lval->ident==iCONSTEXPR) {
1770 lval->constval *= sCHARBITS/8; /* from char to bytes */
1771 lval->constval = (lval->constval + sizeof(cell)-1) / sizeof(cell);
1774 rvalue(lval); /* fetch value if not already in PRI */
1775 char2addr(); /* from characters to bytes */
1776 addconst(sizeof(cell)-1); /* make sure the value is rounded up */
1777 addr2cell(); /* truncate to number of cells */
1791 * The highest hierarchy level: it looks for pointer and array indices
1792 * and function calls.
1793 * Generates code to fetch a pointer value if it is indexed and code to
1794 * add to the pointer value or the array address (the address is already
1795 * read at primary()). It also generates code to fetch a function address
1796 * if that hasn't already been done at primary() (check lval[4]) and calls
1797 * callfunction() to call the function.
1799 static int hier1(value *lval1)
1801 int lvalue,index,tok,symtok;
1808 symbol dummysymbol,*cursym; /* for changing the index tags in case of enumerated pseudo-arrays */
1810 lvalue=primary(lval1);
1811 symtok=tokeninfo(&val,&st); /* get token read by primary() */
1815 if (matchtoken('[') || matchtoken('{') || matchtoken('(')) {
1816 tok=tokeninfo(&val,&st); /* get token read by matchtoken() */
1817 magic_string = (sym && (sym->tag == pc_tag_string && sym->dim.array.level == 0));
1818 if (sym==NULL && symtok!=tSYMBOL) {
1819 /* we do not have a valid symbol and we appear not to have read a valid
1820 * symbol name (so it is unlikely that we would have read a name of an
1821 * undefined symbol) */
1822 error(29); /* expression error, assumed 0 */
1823 lexpush(); /* analyse '(', '{' or '[' again later */
1826 if (tok=='[' || tok=='{') { /* subscript */
1827 close = (char)((tok=='[') ? ']' : '}');
1828 if (sym==NULL) { /* sym==NULL if lval is a constant or a literal */
1829 error(28,"<no variable>"); /* cannot subscript */
1832 } else if (sym->ident!=iARRAY && sym->ident!=iREFARRAY){
1833 error(28,sym->name); /* cannot subscript, variable is not an array */
1836 } else if (sym->dim.array.level>0 && close!=']') {
1837 error(51); /* invalid subscript, must use [ ] */
1841 /* set the tag to match (enumeration fields as indices) */
1842 lval2.cmptag=sym->x.tags.index;
1843 stgget(&index,&cidx); /* mark position in code generator */
1844 pushreg(sPRI); /* save base address of the array */
1845 if (hier14(&lval2)) /* create expression for the array index */
1847 if (lval2.ident==iARRAY || lval2.ident==iREFARRAY)
1848 error(33,lval2.sym->name); /* array must be indexed */
1850 if ((sym->usage & uENUMROOT) && !matchtag(sym->x.tags.index,lval2.tag,TRUE))
1852 if (lval2.ident==iCONSTEXPR) { /* constant expression */
1853 stgdel(index,cidx); /* scratch generated code */
1854 if (lval1->arrayidx!=NULL) { /* keep constant index, for checking */
1855 assert(sym->dim.array.level>=0 && sym->dim.array.level<sDIMEN_MAX);
1856 lval1->arrayidx[sym->dim.array.level]=lval2.constval;
1858 if (close==']' && !(sym->tag == pc_tag_string && sym->dim.array.level == 0)) {
1859 /* normal array index */
1860 if (lval2.constval<0 || (sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval))
1861 error(32,sym->name); /* array index out of bounds */
1862 if (lval2.constval!=0) {
1863 /* don't add offsets for zero subscripts */
1864 #if PAWN_CELL_SIZE==16
1865 ldconst(lval2.constval<<1,sALT);
1866 #elif PAWN_CELL_SIZE==32
1867 ldconst(lval2.constval<<2,sALT);
1868 #elif PAWN_CELL_SIZE==64
1869 ldconst(lval2.constval<<3,sALT);
1871 #error Unsupported cell size
1876 /* character index */
1877 if (lval2.constval<0 || (sym->dim.array.length!=0
1878 && sym->dim.array.length*((8*sizeof(cell))/sCHARBITS)<=(ucell)lval2.constval))
1879 error(32,sym->name); /* array index out of bounds */
1880 if (lval2.constval!=0) {
1881 /* don't add offsets for zero subscripts */
1883 ldconst(lval2.constval<<1,sALT);/* 16-bit character */
1885 ldconst(lval2.constval,sALT); /* 8-bit character */
1889 charalign(); /* align character index into array */
1891 /* if the array index is a field from an enumeration, get the tag name
1892 * from the field and save the size of the field too.
1894 assert(lval2.sym==NULL || lval2.sym->dim.array.level==0);
1895 if (lval2.sym!=NULL && lval2.sym->dim.array.length>0 && sym->dim.array.level==0) {
1896 lval1->tag=lval2.sym->x.tags.index;
1897 lval1->constval=lval2.sym->dim.array.length;
1900 /* array index is not constant */
1901 lval1->arrayidx=NULL; /* reset, so won't be checked */
1902 if (close==']' && !magic_string) {
1903 if (sym->dim.array.length!=0)
1904 ffbounds(sym->dim.array.length-1); /* run time check for array bounds */
1905 cell2addr(); /* normal array index */
1907 if (sym->dim.array.length!=0)
1908 ffbounds(sym->dim.array.length*(32/sCHARBITS)-1);
1909 char2addr(); /* character array index */
1912 ob_add(); /* base address was popped into secondary register */
1913 if (close!=']' || magic_string)
1914 charalign(); /* align character index into array */
1916 /* the indexed item may be another array (multi-dimensional arrays) */
1917 assert(cursym==sym && sym!=NULL); /* should still be set */
1918 if (sym->dim.array.level>0) {
1919 assert(close==']'); /* checked earlier */
1920 assert(cursym==lval1->sym);
1921 /* read the offset to the subarray and add it to the current address */
1922 lval1->ident=iARRAYCELL;
1923 pushreg(sPRI); /* the optimizer makes this to a MOVE.alt */
1927 /* adjust the "value" structure and find the referenced array */
1928 lval1->ident=iREFARRAY;
1929 lval1->sym=finddepend(sym);
1930 assert(lval1->sym!=NULL);
1931 assert(lval1->sym->dim.array.level==sym->dim.array.level-1);
1933 /* try to parse subsequent array indices */
1934 lvalue=FALSE; /* for now, a iREFARRAY is no lvalue */
1937 assert(sym->dim.array.level==0);
1938 /* set type to fetch... INDIRECTLY */
1939 if (sym->tag == pc_tag_string) {
1940 lval1->ident = iARRAYCHAR;
1942 lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
1944 /* if the array index is a field from an enumeration, get the tag name
1945 * from the field and save the size of the field too. Otherwise, the
1946 * tag is the one from the array symbol.
1948 if (lval2.ident==iCONSTEXPR && lval2.sym!=NULL
1949 && lval2.sym->dim.array.length>0 && sym->dim.array.level==0)
1951 lval1->tag=lval2.sym->x.tags.index;
1952 lval1->constval=lval2.sym->dim.array.length;
1953 if (lval2.tag==sym->x.tags.index && lval1->constval>1 && matchtoken('[')) {
1954 /* an array indexed with an enumeration field may be considered a sub-array */
1956 lvalue=FALSE; /* for now, a iREFARRAY is no lvalue */
1957 lval1->ident=iREFARRAY;
1958 /* initialize a dummy symbol, which is a copy of the current symbol,
1959 * but with an adjusted index tag
1963 /* get the tag of the root of the enumeration */
1964 assert(lval2.sym!=NULL);
1965 dummysymbol.x.tags.index=lval2.sym->x.tags.field;
1966 dummysymbol.dim.array.length=lval2.sym->dim.array.length;
1967 cursym=&dummysymbol;
1973 if (cursym!=&dummysymbol)
1974 lval1->tag=sym->tag;
1977 /* a cell in an array is an lvalue, a character in an array is not
1978 * always a *valid* lvalue */
1980 } else { /* tok=='(' -> function(...) */
1983 || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
1985 if (sym==NULL && sc_status==statFIRST) {
1986 /* could be a "use before declaration"; in that case, create a stub
1987 * function so that the usage can be marked.
1989 sym=fetchfunc(lastsymbol,0);
1991 error(123); /* insufficient memory */
1992 markusage(sym,uREAD);
1994 return error(12); /* invalid function call */
1996 } else if ((sym->usage & uMISSING)!=0) {
1997 char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
1998 funcdisplayname(symname,sym->name);
1999 error(4,symname); /* function not defined */
2001 callfunction(sym,lval1,TRUE);
2002 return FALSE; /* result of function call is no lvalue */
2005 if (sym!=NULL && lval1->ident==iFUNCTN) {
2006 assert(sym->ident==iFUNCTN);
2007 if (sc_allowproccall) {
2008 callfunction(sym,lval1,FALSE);
2009 } else if ((sym->usage & uNATIVE) != uNATIVE) {
2012 int usage = ((sym->usage & uPUBLIC) == uPUBLIC) ? uPUBLIC : 0;
2014 for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
2015 if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage)))
2017 if (strcmp(sym->name, lval1->sym->name)==0) {
2019 code_addr = sym->codeaddr;
2026 char faketag[sNAMEMAX+1];
2028 lval1->ident=iCONSTEXPR;
2029 /* Generate a quick pseudo-tag! */
2030 if (usage == uPUBLIC) {
2031 lval1->constval=(n<<1)|1;
2032 snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n);
2034 lval1->constval=(code_addr<<1)|0;
2035 snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr);
2037 lval1->tag=pc_addfunctag(faketag);
2038 oldsym->usage |= uREAD;
2039 sym->usage |= uREAD;
2041 error(76); /* invalid function call, or syntax error */
2045 error(76); /* invalid function call, or syntax error */
2053 * Returns 1 if the operand is an lvalue (everything except arrays, functions
2054 * constants and -of course- errors).
2055 * Generates code to fetch the address of arrays. Code for constants is
2056 * already generated by constant().
2057 * This routine first clears the entire lval array (all fields are set to 0).
2059 * Global references: sc_intest (may be altered, but restored upon termination)
2061 static int primary(value *lval)
2068 if (matchtoken('(')){ /* sub-expression - (expression,...) */
2069 PUSHSTK_I(sc_intest);
2070 PUSHSTK_I(sc_allowtags);
2072 sc_intest=FALSE; /* no longer in "test" expression */
2073 sc_allowtags=TRUE; /* allow tagnames to be used in parenthesized expressions */
2074 sc_allowproccall=FALSE;
2076 lvalue=hier14(lval);
2077 while (matchtoken(','));
2079 lexclr(FALSE); /* clear lex() push-back, it should have been
2080 * cleared already by needtoken() */
2081 sc_allowtags=(short)POPSTK_I();
2082 sc_intest=(short)POPSTK_I();
2086 clear_value(lval); /* clear lval */
2089 /* lastsymbol is char[sNAMEMAX+1], lex() should have truncated any symbol
2090 * to sNAMEMAX significant characters */
2091 assert(strlen(st)<sizeof lastsymbol);
2092 strcpy(lastsymbol,st);
2094 if (tok==tSYMBOL && !findconst(st,NULL)) {
2095 /* first look for a local variable */
2096 if ((sym=findloc(st))!=0) {
2097 if (sym->ident==iLABEL) {
2098 error(29); /* expression error, assumed 0 */
2099 ldconst(0,sPRI); /* load 0 */
2100 return FALSE; /* return 0 for labels (expression error) */
2103 lval->ident=sym->ident;
2105 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
2106 address(sym,sPRI); /* get starting address in primary register */
2107 return FALSE; /* return 0 for array (not lvalue) */
2109 return TRUE; /* return 1 if lvalue (not label or array) */
2112 /* now try a global variable */
2113 if ((sym=findglb(st,sSTATEVAR))!=0) {
2114 if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) {
2115 /* if the function is only in the table because it was inserted as a
2116 * stub in the first pass (i.e. it was "used" but never declared or
2117 * implemented, issue an error
2119 if ((sym->usage & uPROTOTYPED)==0)
2122 if ((sym->usage & uDEFINE)==0)
2125 lval->ident=sym->ident;
2127 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
2128 address(sym,sPRI); /* get starting address in primary register */
2129 return FALSE; /* return 0 for array (not lvalue) */
2131 return TRUE; /* return 1 if lvalue (not function or array) */
2135 if (!sc_allowproccall)
2136 return error(17,st); /* undefined symbol */
2137 /* an unknown symbol, but used in a way compatible with the "procedure
2138 * call" syntax. So assume that the symbol refers to a function.
2140 assert(sc_status==statFIRST);
2141 sym=fetchfunc(st,0);
2143 error(123); /* insufficient memory */
2146 assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
2148 lval->ident=sym->ident;
2150 return FALSE; /* return 0 for function (not an lvalue) */
2152 lexpush(); /* push the token, it is analyzed by constant() */
2153 if (constant(lval)==0) {
2154 error(29); /* expression error, assumed 0 */
2155 ldconst(0,sPRI); /* load 0 */
2157 return FALSE; /* return 0 for constants (or errors) */
2160 static void clear_value(value *lval)
2166 lval->boolresult=FALSE;
2167 /* do not clear lval->arrayidx, it is preset in hier14() */
2168 /* do not clear lval->cmptag */
2171 static void setdefarray(cell *string,cell size,cell array_sz,cell *dataaddr,int fconst)
2173 /* The routine must copy the default array data onto the heap, as to avoid
2174 * that a function can change the default value. An optimization is that
2175 * the default array data is "dumped" into the data segment only once (on the
2178 /* check whether to dump the default array */
2179 assert(dataaddr!=NULL);
2180 if (sc_status==statWRITE && *dataaddr<0) {
2182 *dataaddr=(litidx+glb_declared)*sizeof(cell);
2183 for (i=0; i<size; i++)
2187 /* if the function is known not to modify the array (meaning that it also
2188 * does not modify the default value), directly pass the address of the
2189 * array in the data segment.
2191 if (fconst || !string) {
2192 ldconst(*dataaddr,sPRI);
2194 /* Generate the code:
2195 * CONST.pri dataaddr ;address of the default array data
2196 * HEAP array_sz*sizeof(cell) ;heap address in ALT
2197 * MOVS size*sizeof(cell) ;copy data from PRI to ALT
2198 * MOVE.PRI ;PRI = address on the heap
2200 ldconst(*dataaddr,sPRI);
2201 /* "array_sz" is the size of the argument (the value between the brackets
2202 * in the declaration), "size" is the size of the default array data.
2204 assert(array_sz>=size);
2205 modheap((int)array_sz*sizeof(cell));
2206 markheap(MEMUSE_STATIC, array_sz);
2207 /* ??? should perhaps fill with zeros first */
2208 memcopy(size*sizeof(cell));
2213 static int findnamedarg(arginfo *arg,char *name)
2217 for (i=0; arg[i].ident!=0 && arg[i].ident!=iVARARGS; i++)
2218 if (strcmp(arg[i].name,name)==0)
2223 int checktag(int tags[],int numtags,int exprtag)
2229 for (i=0; i<numtags; i++)
2230 if (matchtag(tags[i],exprtag,TRUE))
2231 return TRUE; /* matching tag */
2232 return FALSE; /* no tag matched */
2243 * Generates code to call a function. This routine handles default arguments
2244 * and positional as well as named parameters.
2246 static void callfunction(symbol *sym,value *lval_result,int matchparanthesis)
2248 static long nest_stkusage=0L;
2249 static int nesting=0;
2251 int argpos; /* index in the output stream (argpos==nargs if positional parameters) */
2252 int argidx=0; /* index in "arginfo" list */
2253 int nargs=0; /* number of arguments */
2255 int namedparams=FALSE;
2258 char arglist[sMAXARGS];
2259 constvalue arrayszlst = { NULL, "", 0, 0};/* array size list starts empty */
2260 constvalue taglst = { NULL, "", 0, 0}; /* tag list starts empty */
2266 lval_result->ident=iEXPRESSION; /* preset, may be changed later */
2267 lval_result->constval=0;
2268 lval_result->tag=sym->tag;
2269 /* check whether this is a function that returns an array */
2270 symret=finddepend(sym);
2271 assert(symret==NULL || symret->ident==iREFARRAY);
2274 /* allocate space on the heap for the array, and pass the pointer to the
2275 * reserved memory block as a hidden parameter
2277 retsize=(int)array_totalsize(symret);
2279 modheap(retsize*sizeof(cell));/* address is in ALT */
2280 pushreg(sALT); /* pass ALT as the last (hidden) parameter */
2281 markheap(MEMUSE_STATIC, retsize);
2282 /* also mark the ident of the result as "array" */
2283 lval_result->ident=iREFARRAY;
2284 lval_result->sym=symret;
2289 assert(nest_stkusage>=0);
2292 assert(nest_stkusage==0);
2294 sc_allowproccall=FALSE; /* parameters may not use procedure call syntax */
2296 if ((sym->flags & flgDEPRECATED)!=0) {
2297 char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
2298 error(234,sym->name,ptr); /* deprecated (probably a native function) */
2301 /* run through the arguments */
2302 arg=sym->dim.arglist;
2304 stgmark(sSTARTREORDER);
2305 memset(arglist,ARG_UNHANDLED,sizeof arglist);
2306 if (matchparanthesis) {
2307 /* Opening brace was already parsed, if closing brace follows, this
2308 * call passes no parameters.
2310 close=matchtoken(')');
2312 /* When we find an end of line here, it may be a function call passing
2313 * no parameters, or it may be that the first parameter is on a line
2314 * below. But as a parameter can be anything, this is difficult to check.
2315 * The only simple check that we have is the use of "named parameters".
2317 close=matchtoken(tTERM);
2319 close=!matchtoken('.');
2321 lexpush(); /* reset the '.' */
2326 if (matchtoken('.')) {
2328 if (needtoken(tSYMBOL))
2329 tokeninfo(&lexval,&lexstr);
2332 argpos=findnamedarg(arg,lexstr);
2334 error(17,lexstr); /* undefined symbol */
2335 break; /* exit loop, argpos is invalid */
2341 error(44); /* positional parameters must precede named parameters */
2344 /* the number of arguments this was already checked at the declaration
2345 * of the function; check it again for functions with a variable
2348 if (argpos>=sMAXARGS)
2349 error(45); /* too many function arguments */
2350 stgmark((char)(sEXPRSTART+argpos));/* mark beginning of new expression in stage */
2351 if (arglist[argpos]!=ARG_UNHANDLED)
2352 error(58); /* argument already set */
2353 if (matchtoken('_')) {
2354 arglist[argpos]=ARG_IGNORED; /* flag argument as "present, but ignored" */
2355 if (arg[argidx].ident==0 || arg[argidx].ident==iVARARGS) {
2356 error(92); /* argument count mismatch */
2357 } else if (!arg[argidx].hasdefault) {
2358 error(34,nargs+1); /* argument has no default value */
2360 if (arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS)
2362 /* The rest of the code to handle default values is at the bottom
2363 * of this routine where default values for unspecified parameters
2364 * are (also) handled. Note that above, the argument is flagged as
2368 arglist[argpos]=ARG_DONE; /* flag argument as "present" */
2369 if (arg[argidx].ident!=0 && arg[argidx].numtags==1) /* set the expected tag, if any */
2370 lval.cmptag=arg[argidx].tags[0];
2371 lvalue=hier14(&lval);
2372 assert(sc_status==statFIRST || arg[argidx].ident == 0 || arg[argidx].tags!=NULL);
2373 switch (arg[argidx].ident) {
2375 /* On the first pass, we donm't have all of the parameter info.
2376 * Hpwever, use information must be marked anyway, otherwise vars
2377 * declared previously will be omitted in the second psas. See
2378 * SourceMod bug 4643.
2380 error(92); /* argument count mismatch */
2382 markusage(lval.sym, uREAD);
2385 /* always pass by reference */
2386 if (lval.ident==iVARIABLE || lval.ident==iREFERENCE) {
2387 assert(lval.sym!=NULL);
2388 if ((lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0) {
2389 /* treat a "const" variable passed to a function with a non-const
2390 * "variable argument list" as a constant here */
2392 error(22); /* need lvalue */
2394 rvalue(&lval); /* get value in PRI */
2395 setheap_pri(); /* address of the value on the heap in PRI */
2396 heapalloc+=markheap(MEMUSE_STATIC, 1);
2399 } else if (lvalue) {
2400 address(lval.sym,sPRI);
2402 setheap_pri(); /* address of the value on the heap in PRI */
2403 heapalloc+=markheap(MEMUSE_STATIC, 1);
2406 } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION)
2408 /* allocate a cell on the heap and store the
2409 * value (already in PRI) there */
2410 setheap_pri(); /* address of the value on the heap in PRI */
2411 heapalloc+=markheap(MEMUSE_STATIC, 1);
2414 /* ??? handle const array passed by reference */
2415 /* otherwise, the address is already in PRI */
2417 markusage(lval.sym,uWRITTEN);
2418 if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
2419 && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2423 if (lval.ident==iLABEL || lval.ident==iFUNCTN || lval.ident==iREFFUNC
2424 || lval.ident==iARRAY || lval.ident==iREFARRAY)
2425 error(35,argidx+1); /* argument type mismatch */
2427 rvalue(&lval); /* get value (direct or indirect) */
2428 /* otherwise, the expression result is already in PRI */
2429 assert(arg[argidx].numtags>0);
2430 check_userop(NULL,lval.tag,arg[argidx].tags[0],2,NULL,&lval.tag);
2431 if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
2432 && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2434 if (arg[argidx].numtags == 1 && arg[argidx].tags[0] & FUNCTAG)
2435 error(100); /* error - function prototypes do not match */
2437 error(213); /* warning - tag mismatch */
2440 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2441 argidx++; /* argument done */
2445 error(35,argidx+1); /* argument type mismatch */
2446 if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
2447 error(35,argidx+1); /* argument type mismatch */
2448 if (lval.ident==iVARIABLE || lval.ident==iREFERENCE) {
2450 assert(lval.sym!=NULL);
2451 address(lval.sym,sPRI);
2453 setheap_pri(); /* address of the value on the heap in PRI */
2454 heapalloc+=markheap(MEMUSE_STATIC, 1);
2458 /* otherwise, the address is already in PRI */
2459 if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2462 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2463 argidx++; /* argument done */
2465 markusage(lval.sym,uWRITTEN);
2468 if (lval.ident!=iARRAY && lval.ident!=iREFARRAY
2469 && lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR)
2471 error(35,argidx+1); /* argument type mismatch */
2474 if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
2475 error(35,argidx+1); /* argument type mismatch */
2476 /* Verify that the dimensions match with those in arg[argidx].
2477 * A literal array always has a single dimension.
2478 * An iARRAYCELL parameter is also assumed to have a single dimension.
2480 if (lval.sym==NULL || lval.ident==iARRAYCELL || lval.ident==iARRAYCHAR) {
2481 if (arg[argidx].numdim!=1) {
2482 error(48); /* array dimensions must match */
2483 } else if (arg[argidx].dim[0]!=0) {
2484 assert(arg[argidx].dim[0]>0);
2485 if (lval.ident==iARRAYCELL) {
2486 error(47); /* array sizes must match */
2488 assert(lval.constval!=0); /* literal array must have a size */
2489 /* A literal array must have exactly the same size as the
2490 * function argument; a literal string may be smaller than
2491 * the function argument.
2493 if ((lval.constval>0 && arg[argidx].dim[0]!=lval.constval)
2494 || (lval.constval<0 && arg[argidx].dim[0] < -lval.constval))
2495 error(47); /* array sizes must match */
2498 if (lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR) {
2499 /* save array size, for default values with uSIZEOF flag */
2500 cell array_sz=lval.constval;
2501 assert(array_sz!=0);/* literal array must have a size */
2503 array_sz= -array_sz;
2504 append_constval(&arrayszlst,arg[argidx].name,array_sz,0);
2507 symbol *sym=lval.sym;
2510 if (sym->dim.array.level+1!=arg[argidx].numdim)
2511 error(48); /* array dimensions must match */
2512 /* the lengths for all dimensions must match, unless the dimension
2513 * length was defined at zero (which means "undefined")
2515 while (sym->dim.array.level>0) {
2516 assert(level<sDIMEN_MAX);
2517 if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level])
2518 error(47); /* array sizes must match */
2519 else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE))
2520 error(229,sym->name); /* index tag mismatch */
2521 append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level);
2522 sym=finddepend(sym);
2526 /* the last dimension is checked too, again, unless it is zero */
2527 assert(level<sDIMEN_MAX);
2529 if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level])
2530 error(47); /* array sizes must match */
2531 else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE))
2532 error(229,sym->name); /* index tag mismatch */
2533 append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level);
2535 /* address already in PRI */
2536 if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2539 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2540 // ??? set uWRITTEN?
2541 argidx++; /* argument done */
2544 pushreg(sPRI); /* store the function argument on the stack */
2545 markexpr(sPARM,NULL,0); /* mark the end of a sub-expression */
2548 assert(arglist[argpos]!=ARG_UNHANDLED);
2550 if (matchparanthesis) {
2551 close=matchtoken(')');
2552 if (!close) /* if not paranthese... */
2553 if (!needtoken(',')) /* ...should be comma... */
2554 break; /* ...but abort loop if neither */
2556 close=!matchtoken(',');
2557 if (close) { /* if not comma... */
2558 if (needtoken(tTERM)==1)/* ...must be end of statement */
2559 lexpush(); /* push again, because end of statement is analised later */
2562 } while (!close && freading && !matchtoken(tENDEXPR)); /* do */
2564 /* check remaining function arguments (they may have default values) */
2565 for (argidx=0; arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS; argidx++) {
2566 if (arglist[argidx]==ARG_DONE)
2567 continue; /* already seen and handled this argument */
2568 /* in this first stage, we also skip the arguments with uSIZEOF and uTAGOF;
2569 * these are handled last
2571 if ((arg[argidx].hasdefault & uSIZEOF)!=0 || (arg[argidx].hasdefault & uTAGOF)!=0) {
2572 assert(arg[argidx].ident==iVARIABLE);
2575 stgmark((char)(sEXPRSTART+argidx));/* mark beginning of new expression in stage */
2576 if (arg[argidx].hasdefault) {
2577 if (arg[argidx].ident==iREFARRAY) {
2579 setdefarray(arg[argidx].defvalue.array.data,
2580 arg[argidx].defvalue.array.size,
2581 arg[argidx].defvalue.array.arraysize,
2582 &arg[argidx].defvalue.array.addr,
2583 (arg[argidx].usage & uCONST)!=0);
2584 if (arg[argidx].defvalue.array.data != NULL) {
2585 if ((arg[argidx].usage & uCONST)==0) {
2586 heapalloc+=arg[argidx].defvalue.array.arraysize;
2587 nest_stkusage+=arg[argidx].defvalue.array.arraysize;
2589 /* keep the lengths of all dimensions of a multi-dimensional default array */
2590 assert(arg[argidx].numdim>0);
2591 if (arg[argidx].numdim==1) {
2592 append_constval(&arrayszlst,arg[argidx].name,arg[argidx].defvalue.array.arraysize,0);
2594 for (level=0; level<arg[argidx].numdim; level++) {
2595 assert(level<sDIMEN_MAX);
2596 append_constval(&arrayszlst,arg[argidx].name,arg[argidx].dim[level],level);
2600 } else if (arg[argidx].ident==iREFERENCE) {
2601 setheap(arg[argidx].defvalue.val);
2602 /* address of the value on the heap in PRI */
2603 heapalloc+=markheap(MEMUSE_STATIC, 1);
2606 int dummytag=arg[argidx].tags[0];
2607 ldconst(arg[argidx].defvalue.val,sPRI);
2608 assert(arg[argidx].numtags>0);
2609 check_userop(NULL,arg[argidx].defvalue_tag,arg[argidx].tags[0],2,NULL,&dummytag);
2610 assert(dummytag==arg[argidx].tags[0]);
2612 pushreg(sPRI); /* store the function argument on the stack */
2613 markexpr(sPARM,NULL,0); /* mark the end of a sub-expression */
2616 error(92,argidx); /* argument count mismatch */
2618 if (arglist[argidx]==ARG_UNHANDLED)
2620 arglist[argidx]=ARG_DONE;
2622 /* now a second loop to catch the arguments with default values that are
2623 * the "sizeof" or "tagof" of other arguments
2625 for (argidx=0; arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS; argidx++) {
2628 if (arglist[argidx]==ARG_DONE)
2629 continue; /* already seen and handled this argument */
2630 stgmark((char)(sEXPRSTART+argidx));/* mark beginning of new expression in stage */
2631 assert(arg[argidx].ident==iVARIABLE); /* if "sizeof", must be single cell */
2632 /* if unseen, must be "sizeof" or "tagof" */
2633 assert((arg[argidx].hasdefault & uSIZEOF)!=0 || (arg[argidx].hasdefault & uTAGOF)!=0);
2634 if ((arg[argidx].hasdefault & uSIZEOF)!=0) {
2635 /* find the argument; if it isn't found, the argument's default value
2636 * was a "sizeof" of a non-array (a warning for this was already given
2637 * when declaring the function)
2639 asz=find_constval(&arrayszlst,arg[argidx].defvalue.size.symname,
2640 arg[argidx].defvalue.size.level);
2642 array_sz=asz->value;
2644 error(224,arg[argidx].name); /* indeterminate array size in "sizeof" expression */
2649 asz=find_constval(&taglst,arg[argidx].defvalue.size.symname,
2650 arg[argidx].defvalue.size.level);
2652 exporttag(asz->value);
2653 array_sz=asz->value | PUBLICTAG; /* must be set, because it just was exported */
2658 ldconst(array_sz,sPRI);
2659 pushreg(sPRI); /* store the function argument on the stack */
2660 markexpr(sPARM,NULL,0);
2662 if (arglist[argidx]==ARG_UNHANDLED)
2664 arglist[argidx]=ARG_DONE;
2666 stgmark(sENDREORDER); /* mark end of reversed evaluation */
2667 pushval((cell)nargs /* *sizeof(cell)*/ );
2669 ffcall(sym,NULL,nargs);
2670 if (sc_status!=statSKIP)
2671 markusage(sym,uREAD); /* do not mark as "used" when this call itself is skipped */
2672 if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL)
2673 sym->x.lib->value += 1; /* increment "usage count" of the library */
2675 popreg(sPRI); /* pop hidden parameter as function result */
2676 sideeffect=TRUE; /* assume functions carry out a side-effect */
2677 delete_consttable(&arrayszlst); /* clear list of array sizes */
2678 delete_consttable(&taglst); /* clear list of parameter tags */
2680 /* maintain max. amount of memory used */
2683 totalsize=declared+heapalloc+1; /* local variables & return value size,
2684 * +1 for PROC opcode */
2685 if (lval_result->ident==iREFARRAY)
2686 totalsize++; /* add hidden parameter (on the stack) */
2687 if ((sym->usage & uNATIVE)==0)
2688 totalsize++; /* add "call" opcode */
2689 totalsize+=nest_stkusage;
2690 if (curfunc != NULL) {
2691 if (curfunc->x.stacksize<totalsize)
2692 curfunc->x.stacksize=totalsize;
2696 nest_stkusage-=nargs+heapalloc+1; /* stack/heap space, +1 for argcount param */
2697 /* if there is a syntax error in the script, the stack calculation is
2698 * probably incorrect; but we may not allow it to drop below zero
2700 if (nest_stkusage<0)
2704 /* scrap any arrays left on the heap, with the exception of the array that
2705 * this function has as a result (in other words, scrap all arrays on the
2706 * heap that caused by expressions in the function arguments)
2714 * Returns a non-zero value if lval1 an array and lval2 is not an array and
2715 * the operation is addition or subtraction.
2717 * Returns the "shift" count (1 for 16-bit, 2 for 32-bit) to align a cell
2718 * to an array offset.
2720 static int dbltest(void (*oper)(),value *lval1,value *lval2)
2722 if ((oper!=ob_add) && (oper!=ob_sub))
2724 if (lval1->ident!=iARRAY)
2726 if (lval2->ident==iARRAY)
2728 return sizeof(cell)/2; /* 1 for 16-bit, 2 for 32-bit */
2733 * Test whether an operator is commutative, i.e. x oper y == y oper x.
2734 * Commutative operators are: + (addition)
2735 * * (multiplication)
2742 * If in an expression, code for the left operand has been generated and
2743 * the right operand is a constant and the operator is commutative, the
2744 * precautionary "push" of the primary register is scrapped and the constant
2745 * is read into the secondary register immediately.
2747 static int commutative(void (*oper)())
2749 return oper==ob_add || oper==os_mult
2750 || oper==ob_eq || oper==ob_ne
2751 || oper==ob_and || oper==ob_xor || oper==ob_or;
2756 * Generates code to fetch a number, a literal character (which is returned
2757 * by lex() as a number as well) or a literal string (lex() stores the
2758 * strings in the literal queue). If the operand was a number, it is stored
2759 * in lval->constval.
2761 * The function returns 1 if the token was a constant or a string, 0
2764 static int constant(value *lval)
2766 int tok,index,ident;
2770 int cmptag=lval->cmptag;
2773 if (tok==tSYMBOL && (sym=findconst(st,&cmptag))!=0) {
2775 error(91,sym->name); /* ambiguity: multiple matching constants (different tags) */
2776 lval->constval=sym->addr;
2777 ldconst(lval->constval,sPRI);
2778 lval->ident=iCONSTEXPR;
2781 markusage(sym,uREAD);
2782 } else if (tok==tNUMBER) {
2784 ldconst(lval->constval,sPRI);
2785 lval->ident=iCONSTEXPR;
2786 } else if (tok==tRATIONAL) {
2788 ldconst(lval->constval,sPRI);
2789 lval->ident=iCONSTEXPR;
2790 lval->tag=sc_rationaltag;
2791 } else if (tok==tSTRING) {
2792 /* lex() stores starting index of string in the literal table in 'val' */
2793 ldconst((val+glb_declared)*sizeof(cell),sPRI);
2794 lval->ident=iARRAY; /* pretend this is a global array */
2795 lval->constval=val-litidx; /* constval == the negative value of the
2796 * size of the literal array; using a negative
2797 * value distinguishes between literal arrays
2798 * and literal strings (this was done for
2799 * array assignment). */
2800 lval->tag=pc_tag_string;
2801 } else if (tok=='{') {
2805 /* cannot call constexpr() here, because "staging" is already turned
2806 * on at this point */
2808 stgget(&index,&cidx); /* mark position in code generator */
2809 ident=expression(&item,&tag,NULL,FALSE,NULL);
2810 stgdel(index,cidx); /* scratch generated code */
2811 if (ident!=iCONSTEXPR)
2812 error(8); /* must be constant expression */
2815 else if (!matchtag(lasttag,tag,FALSE))
2816 error(213); /* tagname mismatch */
2817 litadd(item); /* store expression result in literal table */
2818 } while (matchtoken(','));
2819 if (!needtoken('}'))
2821 ldconst((val+glb_declared)*sizeof(cell),sPRI);
2822 lval->ident=iARRAY; /* pretend this is a global array */
2823 lval->constval=litidx-val; /* constval == the size of the literal array */
2825 return FALSE; /* no, it cannot be interpreted as a constant */
2827 return TRUE; /* yes, it was a constant value */