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.
21 * Version: $Id: sc3.c 3635 2006-08-13 12:19:41Z thiadmer $
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 & FUNCTAG)
332 if (actualtag == pc_functag || (formaltag == pc_functag && actualtag & FUNCTAG))
335 } else if (actualtag & FUNCTAG) {
336 constvalue *v = find_tag_byval(actualtag);
338 short usage = uPUBLIC;
339 symbol *sym, *found = NULL;
343 if (strncmp(v->name, "$Func", 5) != 0)
348 /* Now we have to go about looking up each function in this enum. WHICH IS IT. */
349 e = funcenums_find_byval(formaltag);
355 assert(v->name[5] == '@' || v->name[5] == '!');
357 /* Deduce which function type this is */
358 if (v->name[5] == '@')
361 } else if (v->name[5] = '!') {
365 index = atoi(&v->name[6]);
369 /* Find the function, either by public idx or code addr */
370 if (usage == uPUBLIC)
372 for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
373 if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->vclass == sGLOBAL))
382 } else if (usage == uSTOCK) {
383 for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
384 if (sym->ident==iFUNCTN && (sym->vclass == sGLOBAL))
386 if (sym->codeaddr == index)
402 * 1) The functional enum deduced from formaltag
403 * 2) The function trying to be shoved in deduced from actualtag
404 * Now we have to check if it matches any one of the functags inside the enum.
412 /* Check return type first. */
413 if (t->ret_tag != sym->tag)
419 if (t->type != usage)
424 /* Begin iterating arguments */
425 for (curarg=0; curarg<t->argcount; curarg++)
427 enum_arg = &t->args[curarg];
428 /* Check whether we've exhausted our arguments */
429 if (sym->dim.arglist[curarg].ident == 0)
431 /* Can we bail out early? */
432 if (!enum_arg->ommittable)
439 func_arg = &sym->dim.arglist[curarg];
440 /* First check the ident type */
441 if (enum_arg->ident != func_arg->ident)
446 /* Next check arrayness */
447 if (enum_arg->dimcount != func_arg->numdim)
452 if (enum_arg->dimcount > 0)
454 for (i=0; i<enum_arg->dimcount; i++)
456 if (enum_arg->dims[i] != func_arg->dim[i])
467 /* Lastly, check the tags */
468 if (enum_arg->tagcount != func_arg->numtags)
473 /* They should all be in the same order just for clarity... */
474 for (i=0; i<enum_arg->tagcount; i++)
476 if (enum_arg->tags[i] != func_arg->tags[i])
489 /* Make sure there are no trailing arguments */
490 if (sym->dim.arglist[curarg].ident == 0)
506 * The AMX pseudo-processor has no direct support for logical (boolean)
507 * operations. These have to be done via comparing and jumping. Since we are
508 * already jumping through the code, we might as well implement an "early
509 * drop-out" evaluation (also called "short-circuit"). This conforms to
512 * expr1 || expr2 expr2 will only be evaluated if expr1 is false.
513 * expr1 && expr2 expr2 will only be evaluated if expr1 is true.
515 * expr1 || expr2 && expr3 expr2 will only be evaluated if expr1 is false
516 * and expr3 will only be evaluated if expr1 is
517 * false and expr2 is true.
519 * Code generation for the last example proceeds thus:
523 * jump to "l1" if result of expr1 not equal to 0
525 * -> operator && found; skip to higher level in hierarchy diagram
526 * jump to "l2" if result of expr2 equal to 0
528 * jump to "l2" if result of expr3 equal to 0
529 * set expression result to 1 (true)
531 * l2: set expression result to 0 (false)
533 * <- drop back to previous hierarchy level
534 * jump to "l1" if result of expr2 && expr3 not equal to 0
535 * set expression result to 0 (false)
537 * l1: set expression result to 1 (true)
542 /* Skim over terms adjoining || and && operators
543 * dropval The value of the expression after "dropping out". An "or" drops
544 * out when the left hand is TRUE, so dropval must be 1 on "or"
546 * endval The value of the expression when no expression drops out. In an
547 * "or" expression, this happens when both the left hand and the
548 * right hand are FALSE, so endval must be 0 for "or" expressions.
550 static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
551 int (*hier)(value*),value *lval)
553 int lvalue,hits,droplab,endlab,opidx;
554 int allconst,foundop;
559 stgget(&index,&cidx); /* mark position in code generator */
560 hits=FALSE; /* no logical operators "hit" yet */
561 allconst=TRUE; /* assume all values "const" */
563 droplab=0; /* to avoid a compiler warning */
565 lvalue=plnge1(hier,lval); /* evaluate left expression */
567 allconst= allconst && (lval->ident==iCONSTEXPR);
570 /* one operator was already found */
571 if (testfunc==jmp_ne0)
572 lval->constval= lval->constval || constval;
574 lval->constval= lval->constval && constval;
576 constval=lval->constval; /* save result accumulated so far */
579 foundop=nextop(&opidx,opstr);
580 if ((foundop || hits) && (lval->ident==iARRAY || lval->ident==iREFARRAY))
581 error(33, lval->sym ? (lval->sym->name ? lval->sym->name : "-unknown") : "-unknown-"); /* array was not indexed in an expression */
584 /* this is the first operator in the list */
588 dropout(lvalue,testfunc,droplab,lval);
589 } else if (hits) { /* no (more) identical operators */
590 dropout(lvalue,testfunc,droplab,lval); /* found at least one operator! */
591 ldconst(endval,sPRI);
592 jumplabel(endlab=getlabel());
594 ldconst(dropval,sPRI);
597 lval->tag=pc_addtag("bool"); /* force tag to be "bool" */
599 lval->ident=iCONSTEXPR;
600 lval->constval=constval;
601 stgdel(index,cidx); /* scratch generated code and calculate */
603 lval->ident=iEXPRESSION;
608 return lvalue; /* none of the operators in "opstr" were found */
615 * Reads into the primary register the variable pointed to by lval if
616 * plunging through the hierarchy levels detected an lvalue. Otherwise
617 * if a constant was detected, it is loaded. If there is no constant and
618 * no lvalue, the primary register must already contain the expression
621 * After that, the compare routines "jmp_ne0" or "jmp_eq0" are called, which
622 * compare the primary register against 0, and jump to the "early drop-out"
623 * label "exit1" if the condition is true.
625 static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval)
629 else if (lval->ident==iCONSTEXPR)
630 ldconst(lval->constval,sPRI);
634 static void checkfunction(value *lval)
636 symbol *sym=lval->sym;
638 if (sym==NULL || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
639 return; /* no known symbol, or not a function result */
641 if ((sym->usage & uDEFINE)!=0) {
642 /* function is defined, can now check the return value (but make an
643 * exception for directly recursive functions)
645 if (sym!=curfunc && (sym->usage & uRETVALUE)==0) {
646 char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
647 funcdisplayname(symname,sym->name);
648 error(209,symname); /* function should return a value */
651 /* function not yet defined, set */
652 sym->usage|=uRETVALUE; /* make sure that a future implementation of
653 * the function uses "return <value>" */
658 * Plunge to a lower level
660 static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
661 char *forcetag,int chkbitwise)
667 lvalue=plnge1(hier,lval);
668 if (nextop(&opidx,opstr)==0)
669 return lvalue; /* no operator in "opstr" found */
674 if (chkbitwise && count++>0 && bitwise_opercount!=0)
676 opidx+=opoff; /* add offset to index returned by nextop() */
677 plnge2(op1[opidx],hier,lval,&lval2);
678 if (op1[opidx]==ob_and || op1[opidx]==ob_or)
681 lval->tag=pc_addtag(forcetag);
682 } while (nextop(&opidx,opstr)); /* do */
683 return FALSE; /* result of expression is not an lvalue */
688 * Binary plunge to lower level; this is very simular to plnge, but
689 * it has special code generation sequences for chained operations.
691 static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval)
697 /* this function should only be called for relational operators */
698 assert(op1[opoff]==os_le);
699 lvalue=plnge1(hier,lval);
700 if (nextop(&opidx,opstr)==0)
701 return lvalue; /* no operator in "opstr" found */
705 lval->boolresult=TRUE;
707 /* same check as in plnge(), but "chkbitwise" is always TRUE */
708 if (count>0 && bitwise_opercount!=0)
712 *lval=lval2; /* copy right hand expression of the previous iteration */
715 plnge2(op1[opidx],hier,lval,&lval2);
718 } while (nextop(&opidx,opstr)); /* enddo */
719 lval->constval=lval->boolresult;
720 lval->tag=pc_addtag("bool"); /* force tag to be "bool" */
721 return FALSE; /* result of expression is not an lvalue */
726 * Unary plunge to lower level
727 * Called by: skim(), plnge(), plnge2(), plnge_rel(), hier14() and hier13()
729 static int plnge1(int (*hier)(value *lval),value *lval)
734 stgget(&index,&cidx); /* mark position in code generator */
735 lvalue=(*hier)(lval);
736 if (lval->ident==iCONSTEXPR)
737 stgdel(index,cidx); /* load constant later */
743 * Binary plunge to lower level
744 * Called by: plnge(), plnge_rel(), hier14() and hier1()
746 static void plnge2(void (*oper)(void),
747 int (*hier)(value *lval),
748 value *lval1,value *lval2)
753 stgget(&index,&cidx); /* mark position in code generator */
754 if (lval1->ident==iCONSTEXPR) { /* constant on left side; it is not yet loaded */
755 if (plnge1(hier,lval2))
756 rvalue(lval2); /* load lvalue now */
757 else if (lval2->ident==iCONSTEXPR)
758 ldconst(lval2->constval<<dbltest(oper,lval2,lval1),sPRI);
759 ldconst(lval1->constval<<dbltest(oper,lval2,lval1),sALT);
760 /* ^ doubling of constants operating on integer addresses */
761 /* is restricted to "add" and "subtract" operators */
762 } else { /* non-constant on left side */
764 if (plnge1(hier,lval2))
766 if (lval2->ident==iCONSTEXPR) { /* constant on right side */
767 if (commutative(oper)) { /* test for commutative operators */
769 stgdel(index,cidx); /* scratch pushreg() and constant fetch (then
770 * fetch the constant again */
771 ldconst(lval2->constval<<dbltest(oper,lval1,lval2),sALT);
772 /* now, the primary register has the left operand and the secondary
773 * register the right operand; swap the "lval" variables so that lval1
774 * is associated with the secondary register and lval2 with the
775 * primary register, as is the "normal" case.
781 ldconst(lval2->constval<<dbltest(oper,lval1,lval2),sPRI);
782 popreg(sALT); /* pop result of left operand into secondary register */
784 } else { /* non-constants on both sides */
786 if (dbltest(oper,lval1,lval2))
787 cell2addr(); /* double primary register */
788 if (dbltest(oper,lval2,lval1))
789 cell2addr_alt(); /* double secondary register */
793 /* If used in an expression, a function should return a value.
794 * If the function has been defined, we can check this. If the
795 * function was not defined, we can set this requirement (so that
796 * a future function definition can check this bit.
798 checkfunction(lval1);
799 checkfunction(lval2);
800 if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
801 char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-";
802 error(33,ptr); /* array must be indexed */
803 } else if (lval2->ident==iARRAY || lval2->ident==iREFARRAY) {
804 char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-";
805 error(33,ptr); /* array must be indexed */
807 /* ??? ^^^ should do same kind of error checking with functions */
809 /* check whether an "operator" function is defined for the tag names
810 * (a constant expression cannot be optimized in that case)
812 if (check_userop(oper,lval1->tag,lval2->tag,2,NULL,&lval1->tag)) {
813 lval1->ident=iEXPRESSION;
815 } else if (lval1->ident==iCONSTEXPR && lval2->ident==iCONSTEXPR) {
816 /* only constant expression if both constant */
817 stgdel(index,cidx); /* scratch generated code and calculate */
818 if (!matchtag(lval1->tag,lval2->tag,FALSE))
819 error(213); /* tagname mismatch */
820 lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult);
822 if (!checktag_string(lval1, lval2) && !matchtag(lval1->tag,lval2->tag,FALSE))
823 error(213); /* tagname mismatch */
824 (*oper)(); /* do the (signed) operation */
825 lval1->ident=iEXPRESSION;
830 static cell flooreddiv(cell a,cell b,int return_remainder)
838 /* first implement truncated division in a portable way */
839 #define IABS(a) ((a)>=0 ? (a) : (-a))
842 q=-q; /* swap sign if either "a" or "b" is negative (but not both) */
843 r=a-q*b; /* calculate the matching remainder */
844 /* now "fiddle" with the values to get floored division */
845 if (r!=0 && (cell)(r ^ b)<0) {
849 return return_remainder ? r : q;
852 static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
855 return (left | right);
856 else if (oper==ob_xor)
857 return (left ^ right);
858 else if (oper==ob_and)
859 return (left & right);
860 else if (oper==ob_eq)
861 return (left == right);
862 else if (oper==ob_ne)
863 return (left != right);
864 else if (oper==os_le)
865 return *boolresult &= (char)(left <= right), right;
866 else if (oper==os_ge)
867 return *boolresult &= (char)(left >= right), right;
868 else if (oper==os_lt)
869 return *boolresult &= (char)(left < right), right;
870 else if (oper==os_gt)
871 return *boolresult &= (char)(left > right), right;
872 else if (oper==os_sar)
873 return (left >> (int)right);
874 else if (oper==ou_sar)
875 return ((ucell)left >> (ucell)right);
876 else if (oper==ob_sal)
877 return ((ucell)left << (int)right);
878 else if (oper==ob_add)
879 return (left + right);
880 else if (oper==ob_sub)
881 return (left - right);
882 else if (oper==os_mult)
883 return (left * right);
884 else if (oper==os_div)
885 return flooreddiv(left,right,0);
886 else if (oper==os_mod)
887 return flooreddiv(left,right,1);
889 error(29); /* invalid expression, assumed 0 (this should never occur) */
893 SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval)
900 /* scrap any arrays left on the heap */
903 if (lval.ident==iCONSTEXPR && val!=NULL) /* constant expression */
910 checkfunction(&lval);
916 SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
918 char name[sNAMEMAX+1];
923 assert(automaton!=NULL);
925 if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL))
928 tokeninfo(&val,&str);
929 assert(strlen(str)<sizeof name);
931 if (islabel || matchtoken(':')) {
932 /* token is an automaton name, add the name and get a new token */
933 *automaton=automaton_find(name);
934 /* read in the state name before checking the automaton, to keep the parser
935 * going (an "unknown automaton" error may occur when the "state" instruction
936 * precedes any state definition)
938 if (!needtoken(tSYMBOL))
940 tokeninfo(&val,&str); /* do not copy the name yet, must check automaton first */
941 if (*automaton==NULL) {
942 error(86,name); /* unknown automaton */
945 assert((*automaton)->index>0);
946 assert(strlen(str)<sizeof name);
949 *automaton=automaton_find("");
950 assert(*automaton!=NULL);
951 assert((*automaton)->index==0);
953 assert(*automaton!=NULL);
954 fsa=(*automaton)->index;
956 assert(*automaton!=NULL);
957 *state=state_find(name,fsa);
959 char *fsaname=(*automaton)->name;
962 error(87,name,fsaname); /* unknown state for automaton */
969 SC_FUNC cell array_totalsize(symbol *sym)
974 assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
975 length=sym->dim.array.length;
976 if (sym->dim.array.level > 0) {
977 cell sublength=array_totalsize(finddepend(sym));
979 length=length+length*sublength;
986 static cell array_levelsize(symbol *sym,int level)
989 assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
990 assert(level <= sym->dim.array.level);
991 while (level-- > 0) {
995 return (sym->dim.array.slength ? sym->dim.array.slength : sym->dim.array.length);
1000 * Lowest hierarchy level (except for the , operator).
1002 * Global references: sc_intest (reffered to only)
1003 * sc_allowproccall (modified)
1005 static int hier14(value *lval1)
1008 value lval2={0},lval3={0};
1013 int bwcount,leftarray;
1014 cell arrayidx1[sDIMEN_MAX],arrayidx2[sDIMEN_MAX]; /* last used array indices */
1017 bwcount=bitwise_opercount;
1018 bitwise_opercount=0;
1019 /* initialize the index arrays with unlikely constant indices; note that
1020 * these indices will only be changed when the array is indexed with a
1021 * constant, and that negative array indices are invalid (so actually, any
1022 * negative value would do).
1024 for (i=0; i<sDIMEN_MAX; i++)
1025 arrayidx1[i]=arrayidx2[i]=(cell)(-1L << (sizeof(cell)*8-1));
1026 org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */
1027 if (lval1->arrayidx==NULL)
1028 lval1->arrayidx=arrayidx1;
1029 lvalue=plnge1(hier13,lval1);
1030 if (lval1->ident!=iARRAYCELL && lval1->ident!=iARRAYCHAR)
1031 lval1->arrayidx=NULL;
1032 if (lval1->ident==iCONSTEXPR) /* load constant here */
1033 ldconst(lval1->constval,sPRI);
1069 case '=': /* simple assignment */
1072 error(211); /* possibly unintended assignment */
1076 bitwise_opercount=bwcount;
1077 lval1->arrayidx=org_arrayidx; /* restore array index pointer */
1081 /* if we get here, it was an assignment; first check a few special cases
1082 * and then the general */
1083 if (lval1->ident==iARRAYCHAR) {
1084 /* special case, assignment to packed character in a cell is permitted */
1086 } else if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
1087 /* array assignment is permitted too (with restrictions) */
1089 return error(23); /* array assignment must be simple assigment */
1090 assert(lval1->sym!=NULL);
1091 if (array_totalsize(lval1->sym)==0)
1092 return error(46,lval1->sym->name); /* unknown array size */
1096 /* operand on left side of assignment must be lvalue */
1098 return error(22); /* must be lvalue */
1099 /* may not change "constant" parameters */
1100 assert(lval1->sym!=NULL);
1101 if ((lval1->sym->usage & uCONST)!=0)
1102 return error(22); /* assignment to const argument */
1103 sc_allowproccall=FALSE; /* may no longer use "procedure call" syntax */
1105 lval3=*lval1; /* save symbol to enable storage of expresion result */
1106 lval1->arrayidx=org_arrayidx; /* restore array index pointer */
1107 if (lval1->ident==iARRAYCELL || lval1->ident==iARRAYCHAR
1108 || lval1->ident==iARRAY || lval1->ident==iREFARRAY)
1110 /* if indirect fetch: save PRI (cell address) */
1115 lval2.arrayidx=arrayidx2;
1116 plnge2(oper,hier14,lval1,&lval2);
1117 if (lval2.ident!=iARRAYCELL && lval2.ident!=iARRAYCHAR)
1118 lval2.arrayidx=NULL;
1121 if (!oper && lval3.arrayidx!=NULL && lval2.arrayidx!=NULL
1122 && lval3.ident==lval2.ident && lval3.sym==lval2.sym)
1125 assert(lval2.arrayidx==arrayidx2);
1126 for (i=0; i<sDIMEN_MAX; i++)
1127 same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
1129 error(226,lval3.sym->name); /* self-assignment */
1134 plnge2(oper,hier14,lval1,&lval2);
1136 /* if direct fetch and simple assignment: no "push"
1137 * and "pop" needed -> call hier14() directly, */
1139 rvalue(&lval2); /* instead of plnge2(). */
1140 else if (lval2.ident==iVARIABLE)
1141 lval2.ident=iEXPRESSION;/* mark as "rvalue" if it is not an "lvalue" */
1142 checkfunction(&lval2);
1143 /* check whether lval2 and lval3 (old lval1) refer to the same variable */
1144 if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) {
1145 assert(lval3.sym!=NULL);
1146 error(226,lval3.sym->name); /* self-assignment */
1150 /* Array elements are sometimes considered as sub-arrays --when the
1151 * array index is an enumeration field and the enumeration size is greater
1152 * than 1. If the expression on the right side of the assignment is a cell,
1153 * or if an operation is in effect, this does not apply.
1155 leftarray= lval3.ident==iARRAY || lval3.ident==iREFARRAY
1156 || ((lval3.ident==iARRAYCELL || lval3.ident==iARRAYCHAR)
1157 && lval3.constval>1 && lval3.sym->dim.array.level==0
1158 && !oper && (lval2.ident==iARRAY || lval2.ident==iREFARRAY));
1160 /* Left operand is an array, right operand should be an array variable
1161 * of the same size and the same dimension, an array literal (of the
1162 * same size) or a literal string. For single-dimensional arrays without
1163 * tag for the index, it is permitted to assign a smaller array into a
1164 * larger one (without warning). This is to make it easier to work with
1167 int exactmatch=TRUE;
1169 int ltlength=(int)lval3.sym->dim.array.length;
1170 if ((lval3.ident==iARRAYCELL || lval3.ident==iARRAYCHAR)
1171 && lval3.constval>0 && lval3.sym->dim.array.level==0)
1173 ltlength=(int)lval3.constval;
1175 if (lval2.ident!=iARRAY && lval2.ident!=iREFARRAY
1176 && (lval2.sym==NULL || lval2.constval<=0))
1177 error(33,lval3.sym->name); /* array must be indexed */
1178 if (lval2.sym!=NULL) {
1179 if (lval2.constval==0) {
1180 val=lval2.sym->dim.array.length;/* array variable */
1183 if (lval2.sym->dim.array.level!=0)
1184 error(28,lval2.sym->name);
1186 level=lval2.sym->dim.array.level;
1187 idxtag=lval2.sym->x.tags.index;
1188 if (level==0 && idxtag==0 && lval3.sym->x.tags.index==0)
1191 val=lval2.constval; /* literal array */
1193 /* If val is negative, it means that lval2 is a literal string.
1194 * The string array size may be smaller than the destination
1195 * array, provided that the destination array does not have an
1200 if (lval3.sym->x.tags.index==0)
1204 if (lval3.sym->dim.array.level!=level)
1205 return error(48); /* array dimensions must match */
1206 else if (ltlength<val || exactmatch && ltlength>val || val==0)
1207 return error(47); /* array sizes must match */
1208 else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE))
1209 error(229,(lval2.sym!=NULL) ? lval2.sym->name : lval3.sym->name); /* index tag mismatch */
1211 /* check the sizes of all sublevels too */
1212 symbol *sym1 = lval3.sym;
1213 symbol *sym2 = lval2.sym;
1215 assert(sym1!=NULL && sym2!=NULL);
1216 /* ^^^ sym2 must be valid, because only variables can be
1217 * multi-dimensional (there are no multi-dimensional literals),
1218 * sym1 must be valid because it must be an lvalue
1221 for (i=0; i<level; i++) {
1222 sym1=finddepend(sym1);
1223 sym2=finddepend(sym2);
1224 assert(sym1!=NULL && sym2!=NULL);
1225 /* ^^^ both arrays have the same dimensions (this was checked
1226 * earlier) so the dependend should always be found
1228 if (sym1->dim.array.length!=sym2->dim.array.length)
1229 error(47); /* array sizes must match */
1230 else if (!matchtag(sym1->x.tags.index,sym2->x.tags.index,TRUE))
1231 error(229,sym2->name); /* index tag mismatch */
1233 /* get the total size in cells of the multi-dimensional array */
1234 val=array_totalsize(lval3.sym);
1235 assert(val>0); /* already checked */
1238 /* left operand is not an array, right operand should then not be either */
1239 if (lval2.ident==iARRAY || lval2.ident==iREFARRAY)
1240 error(6); /* must be assigned to an array */
1243 memcopy(val*sizeof(cell));
1245 check_userop(NULL,lval2.tag,lval3.tag,2,&lval3,&lval2.tag);
1246 store(&lval3); /* now, store the expression result */
1248 if (!oper && !checktag_string(&lval3, &lval2) && !matchtag(lval3.tag,lval2.tag,TRUE))
1249 error(213); /* tagname mismatch (if "oper", warning already given in plunge2()) */
1251 markusage(lval3.sym,uWRITTEN);
1253 bitwise_opercount=bwcount;
1254 lval1->ident=iEXPRESSION;
1255 return FALSE; /* expression result is never an lvalue */
1259 * Sums up array usage in the current heap tracer and convert it into a dynamic array.
1260 * This is used for the ternary operator, which needs to convert its array usage into
1261 * something dynamically managed.
1263 * This might break if expressions can ever return dynamic arrays.
1264 * Thus, we assert() if something is non-static here.
1265 * Right now, this poses no problem because this type of expression is impossible:
1266 * (a() ? return_array() : return_array()) ? return_array() : return_array()
1269 void dynarray_from_heaplist(memuse_list_t *heap)
1271 memuse_t *use=heap->head;
1275 assert(use->type==MEMUSE_STATIC);
1283 setheap_save(-total*sizeof(cell));
1286 static int hier13(value *lval)
1288 int lvalue=plnge1(hier12,lval);
1289 if (matchtoken('?')) {
1290 int flab1=getlabel();
1291 int flab2=getlabel();
1294 memuse_list_t *heap;
1299 } else if (lval->ident==iCONSTEXPR) {
1300 ldconst(lval->constval,sPRI);
1301 error(lval->constval ? 206 : 205); /* redundant test */
1303 jmp_eq0(flab1); /* go to second expression if primary register==0 */
1304 PUSHSTK_I(sc_allowtags);
1305 sc_allowtags=FALSE; /* do not allow tagnames here (colon is a special token) */
1308 if (lval->ident==iCONSTEXPR) /* load constant here */
1309 ldconst(lval->constval,sPRI);
1310 sc_allowtags=(short)POPSTK_I(); /* restore */
1311 heap=popsaveheaplist();
1312 dynarray_from_heaplist(heap);
1319 if (lval2.ident==iCONSTEXPR) /* load constant here */
1320 ldconst(lval2.constval,sPRI);
1321 array1= (lval->ident==iARRAY || lval->ident==iREFARRAY);
1322 array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY);
1323 if (array1 && !array2) {
1324 char *ptr=(lval->sym->name!=NULL) ? lval->sym->name : "-unknown-";
1325 error(33,ptr); /* array must be indexed */
1326 } else if (!array1 && array2) {
1327 char *ptr=(lval2.sym->name!=NULL) ? lval2.sym->name : "-unknown-";
1328 error(33,ptr); /* array must be indexed */
1330 /* ??? if both are arrays, should check dimensions */
1331 if (!matchtag(lval->tag,lval2.tag,FALSE))
1332 error(213); /* tagname mismatch ('true' and 'false' expressions) */
1333 heap=popsaveheaplist();
1334 dynarray_from_heaplist(heap);
1336 if (array1 && array2) {
1337 markheap(MEMUSE_DYNAMIC, 0);
1339 if (lval->ident==iARRAY)
1340 lval->ident=iREFARRAY; /* iARRAY becomes iREFARRAY */
1341 else if (lval->ident!=iREFARRAY)
1342 lval->ident=iEXPRESSION; /* iREFARRAY stays iREFARRAY, rest becomes iEXPRESSION */
1343 return FALSE; /* conditional expression is no lvalue */
1349 /* the order of the operators in these lists is important and must be
1350 * the same as the order of the operators in the array "op1"
1352 static int list3[] = {'*','/','%',0};
1353 static int list4[] = {'+','-',0};
1354 static int list5[] = {tSHL,tSHR,tSHRU,0};
1355 static int list6[] = {'&',0};
1356 static int list7[] = {'^',0};
1357 static int list8[] = {'|',0};
1358 static int list9[] = {tlLE,tlGE,'<','>',0};
1359 static int list10[] = {tlEQ,tlNE,0};
1360 static int list11[] = {tlAND,0};
1361 static int list12[] = {tlOR,0};
1363 static int hier12(value *lval)
1365 return skim(list12,jmp_ne0,1,0,hier11,lval);
1368 static int hier11(value *lval)
1370 return skim(list11,jmp_eq0,0,1,hier10,lval);
1373 static int hier10(value *lval)
1375 return plnge(list10,15,hier9,lval,"bool",TRUE);
1376 } /* ^ this variable is the starting index in the op1[]
1377 * array of the operators of this hierarchy level */
1379 static int hier9(value *lval)
1380 { /* <=, >=, <, > */
1381 return plnge_rel(list9,11,hier8,lval);
1384 static int hier8(value *lval)
1386 return plnge(list8,10,hier7,lval,NULL,FALSE);
1389 static int hier7(value *lval)
1391 return plnge(list7,9,hier6,lval,NULL,FALSE);
1394 static int hier6(value *lval)
1396 return plnge(list6,8,hier5,lval,NULL,FALSE);
1399 static int hier5(value *lval)
1401 return plnge(list5,5,hier4,lval,NULL,FALSE);
1404 static int hier4(value *lval)
1406 return plnge(list4,3,hier3,lval,NULL,FALSE);
1409 static int hier3(value *lval)
1411 return plnge(list3,0,hier2,lval,NULL,FALSE);
1414 static int hier2(value *lval)
1425 case tINC: /* ++lval */
1427 return error(22); /* must be lvalue */
1428 assert(lval->sym!=NULL);
1429 if ((lval->sym->usage & uCONST)!=0)
1430 return error(22); /* assignment to const argument */
1431 if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag))
1432 inc(lval); /* increase variable first */
1433 rvalue(lval); /* and read the result into PRI */
1435 return FALSE; /* result is no longer lvalue */
1436 case tDEC: /* --lval */
1438 return error(22); /* must be lvalue */
1439 assert(lval->sym!=NULL);
1440 if ((lval->sym->usage & uCONST)!=0)
1441 return error(22); /* assignment to const argument */
1442 if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag))
1443 dec(lval); /* decrease variable first */
1444 rvalue(lval); /* and read the result into PRI */
1446 return FALSE; /* result is no longer lvalue */
1447 case '~': /* ~ (one's complement) */
1450 invert(); /* bitwise NOT */
1451 lval->constval=~lval->constval;
1453 case '!': /* ! (logical negate) */
1456 if (check_userop(lneg,lval->tag,0,1,NULL,&lval->tag)) {
1457 lval->ident=iEXPRESSION;
1460 lneg(); /* 0 -> 1, !0 -> 0 */
1461 lval->constval=!lval->constval;
1462 lval->tag=pc_addtag("bool");
1465 case '-': /* unary - (two's complement) */
1468 /* make a special check for a constant expression with the tag of a
1469 * rational number, so that we can simple swap the sign of that constant.
1471 if (lval->ident==iCONSTEXPR && lval->tag==sc_rationaltag && sc_rationaltag!=0) {
1472 if (rational_digits==0) {
1473 #if PAWN_CELL_SIZE==32
1474 float *f = (float *)&lval->constval;
1475 #elif PAWN_CELL_SIZE==64
1476 double *f = (double *)&lval->constval;
1478 #error Unsupported cell size
1480 *f= - *f; /* this modifies lval->constval */
1482 /* the negation of a fixed point number is just an integer negation */
1483 lval->constval=-lval->constval;
1485 } else if (check_userop(neg,lval->tag,0,1,NULL,&lval->tag)) {
1486 lval->ident=iEXPRESSION;
1489 neg(); /* arithmic negation */
1490 lval->constval=-lval->constval;
1493 case tLABEL: /* tagname override */
1501 while (matchtoken('('))
1505 return error(20,st); /* illegal symbol name */
1508 sym=findglb(st,sSTATEVAR);
1509 if (sym!=NULL && sym->ident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0)
1510 sym=NULL; /* symbol is not a function, it is in the table, but not "defined" */
1512 if (!val && find_subst(st,strlen(st))!=NULL)
1515 lval->ident=iCONSTEXPR;
1516 lval->constval= val;
1517 lval->tag=pc_addtag("bool");
1518 ldconst(lval->constval,sPRI);
1519 while (paranthese--)
1524 while (matchtoken('('))
1528 return error(20,st); /* illegal symbol name */
1531 sym=findglb(st,sSTATEVAR);
1533 return error(17,st); /* undefined symbol */
1534 if (sym->ident==iCONSTEXPR)
1535 error(39); /* constant symbol has no size */
1536 else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC)
1537 error(72); /* "function" symbol has no size */
1538 else if ((sym->usage & uDEFINE)==0)
1539 return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
1541 lval->ident=iCONSTEXPR;
1542 lval->constval=1; /* preset */
1543 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
1545 symbol *idxsym=NULL;
1547 for (level=0; matchtoken('['); level++) {
1549 if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
1551 int cmptag=subsym->x.tags.index;
1552 tokeninfo(&val,&idxname);
1553 if ((idxsym=findconst(idxname,&cmptag))==NULL)
1554 error(80,idxname); /* unknown symbol, or non-constant */
1556 error(91,idxname); /* ambiguous constant */
1560 subsym=finddepend(subsym);
1562 if (level>sym->dim.array.level+1) {
1563 error(28,sym->name); /* invalid subscript */
1564 } else if (level==sym->dim.array.level+1) {
1565 lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
1567 lval->constval=array_levelsize(sym,level);
1569 if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL)
1570 error(224,st); /* indeterminate array size in "sizeof" expression */
1572 ldconst(lval->constval,sPRI);
1573 while (paranthese--)
1578 while (matchtoken('('))
1582 return error(20,st); /* illegal symbol name */
1585 sym=findglb(st,sSTATEVAR);
1587 return error(17,st); /* undefined symbol */
1588 if (sym->ident==iCONSTEXPR)
1589 error(39); /* constant symbol has no size */
1590 else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC)
1591 error(72); /* "function" symbol has no size */
1592 else if ((sym->usage & uDEFINE)==0)
1593 return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
1595 lval->ident=iCONSTEXPR;
1596 lval->constval=1; /* preset */
1597 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
1599 symbol *idxsym=NULL;
1601 for (level=0; matchtoken('['); level++) {
1603 if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
1605 int cmptag=subsym->x.tags.index;
1606 tokeninfo(&val,&idxname);
1607 if ((idxsym=findconst(idxname,&cmptag))==NULL)
1608 error(80,idxname); /* unknown symbol, or non-constant */
1610 error(91,idxname); /* ambiguous constant */
1614 subsym=finddepend(subsym);
1616 if (level>sym->dim.array.level+1) {
1617 error(28,sym->name); /* invalid subscript */
1618 } else if (level==sym->dim.array.level+1) {
1619 lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
1621 lval->constval=array_levelsize(sym,level);
1623 if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL)
1624 error(224,st); /* indeterminate array size in "sizeof" expression */
1626 ldconst(lval->constval,sPRI);
1627 while (paranthese--)
1632 while (matchtoken('('))
1635 if (tok!=tSYMBOL && tok!=tLABEL)
1636 return error(20,st); /* illegal symbol name */
1638 constvalue *tagsym=find_constval(&tagname_tab,st,0);
1639 tag=(int)((tagsym!=NULL) ? tagsym->value : 0);
1643 sym=findglb(st,sSTATEVAR);
1645 return error(17,st); /* undefined symbol */
1646 if ((sym->usage & uDEFINE)==0)
1647 return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
1650 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
1652 symbol *idxsym=NULL;
1654 for (level=0; matchtoken('['); level++) {
1656 if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
1658 int cmptag=subsym->x.tags.index;
1659 tokeninfo(&val,&idxname);
1660 if ((idxsym=findconst(idxname,&cmptag))==NULL)
1661 error(80,idxname); /* unknown symbol, or non-constant */
1663 error(91,idxname); /* ambiguous constant */
1667 subsym=finddepend(subsym);
1669 if (level>sym->dim.array.level+1)
1670 error(28,sym->name); /* invalid subscript */
1671 else if (level==sym->dim.array.level+1 && idxsym!=NULL)
1672 tag= idxsym->x.tags.index;
1676 lval->ident=iCONSTEXPR;
1677 lval->constval=tag | PUBLICTAG;
1678 ldconst(lval->constval,sPRI);
1679 while (paranthese--)
1683 constvalue *automaton;
1685 if (sc_getstateid(&automaton,&state)) {
1686 assert(automaton!=NULL);
1687 assert(automaton->index==0 && automaton->name[0]=='\0' || automaton->index>0);
1688 loadreg(automaton->value,sALT);
1689 assert(state!=NULL);
1690 ldconst(state->value,sPRI);
1693 lval->ident=iEXPRESSION;
1694 lval->tag=pc_addtag("bool");
1701 /* check for postfix operators */
1702 if (matchtoken(';')) {
1703 /* Found a ';', do not look further for postfix operators */
1704 lexpush(); /* push ';' back after successful match */
1706 } else if (matchtoken(tTERM)) {
1707 /* Found a newline that ends a statement (this is the case when
1708 * semicolons are optional). Note that an explicit semicolon was
1709 * handled above. This case is similar, except that the token must
1710 * not be pushed back.
1716 case tINC: /* lval++ */
1718 return error(22); /* must be lvalue */
1719 assert(lval->sym!=NULL);
1720 if ((lval->sym->usage & uCONST)!=0)
1721 return error(22); /* assignment to const argument */
1722 /* on incrementing array cells, the address in PRI must be saved for
1723 * incremening the value, whereas the current value must be in PRI
1726 saveresult= (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR);
1728 pushreg(sPRI); /* save address in PRI */
1729 rvalue(lval); /* read current value into PRI */
1731 swap1(); /* save PRI on the stack, restore address in PRI */
1732 if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag))
1733 inc(lval); /* increase variable afterwards */
1735 popreg(sPRI); /* restore PRI (result of rvalue()) */
1737 return FALSE; /* result is no longer lvalue */
1738 case tDEC: /* lval-- */
1740 return error(22); /* must be lvalue */
1741 assert(lval->sym!=NULL);
1742 if ((lval->sym->usage & uCONST)!=0)
1743 return error(22); /* assignment to const argument */
1744 saveresult= (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR);
1746 pushreg(sPRI); /* save address in PRI */
1747 rvalue(lval); /* read current value into PRI */
1749 swap1(); /* save PRI on the stack, restore address in PRI */
1750 if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag))
1751 dec(lval); /* decrease variable afterwards */
1753 popreg(sPRI); /* restore PRI (result of rvalue()) */
1756 /* This is temporarily disabled because we detect it automatically.
1757 * Thus, it could be weird if both were used at once
1760 case tCHAR: /* char (compute required # of cells */
1761 if (lval->ident==iCONSTEXPR) {
1762 lval->constval *= sCHARBITS/8; /* from char to bytes */
1763 lval->constval = (lval->constval + sizeof(cell)-1) / sizeof(cell);
1766 rvalue(lval); /* fetch value if not already in PRI */
1767 char2addr(); /* from characters to bytes */
1768 addconst(sizeof(cell)-1); /* make sure the value is rounded up */
1769 addr2cell(); /* truncate to number of cells */
1783 * The highest hierarchy level: it looks for pointer and array indices
1784 * and function calls.
1785 * Generates code to fetch a pointer value if it is indexed and code to
1786 * add to the pointer value or the array address (the address is already
1787 * read at primary()). It also generates code to fetch a function address
1788 * if that hasn't already been done at primary() (check lval[4]) and calls
1789 * callfunction() to call the function.
1791 static int hier1(value *lval1)
1793 int lvalue,index,tok,symtok;
1800 symbol dummysymbol,*cursym; /* for changing the index tags in case of enumerated pseudo-arrays */
1802 lvalue=primary(lval1);
1803 symtok=tokeninfo(&val,&st); /* get token read by primary() */
1807 if (matchtoken('[') || matchtoken('{') || matchtoken('(')) {
1808 tok=tokeninfo(&val,&st); /* get token read by matchtoken() */
1809 magic_string = (sym && (sym->tag == pc_tag_string && sym->dim.array.level == 0));
1810 if (sym==NULL && symtok!=tSYMBOL) {
1811 /* we do not have a valid symbol and we appear not to have read a valid
1812 * symbol name (so it is unlikely that we would have read a name of an
1813 * undefined symbol) */
1814 error(29); /* expression error, assumed 0 */
1815 lexpush(); /* analyse '(', '{' or '[' again later */
1818 if (tok=='[' || tok=='{') { /* subscript */
1819 close = (char)((tok=='[') ? ']' : '}');
1820 if (sym==NULL) { /* sym==NULL if lval is a constant or a literal */
1821 error(28,"<no variable>"); /* cannot subscript */
1824 } else if (sym->ident!=iARRAY && sym->ident!=iREFARRAY){
1825 error(28,sym->name); /* cannot subscript, variable is not an array */
1828 } else if (sym->dim.array.level>0 && close!=']') {
1829 error(51); /* invalid subscript, must use [ ] */
1833 /* set the tag to match (enumeration fields as indices) */
1834 lval2.cmptag=sym->x.tags.index;
1835 stgget(&index,&cidx); /* mark position in code generator */
1836 pushreg(sPRI); /* save base address of the array */
1837 if (hier14(&lval2)) /* create expression for the array index */
1839 if (lval2.ident==iARRAY || lval2.ident==iREFARRAY)
1840 error(33,lval2.sym->name); /* array must be indexed */
1842 if ((sym->usage & uENUMROOT) && !matchtag(sym->x.tags.index,lval2.tag,TRUE))
1844 if (lval2.ident==iCONSTEXPR) { /* constant expression */
1845 stgdel(index,cidx); /* scratch generated code */
1846 if (lval1->arrayidx!=NULL) { /* keep constant index, for checking */
1847 assert(sym->dim.array.level>=0 && sym->dim.array.level<sDIMEN_MAX);
1848 lval1->arrayidx[sym->dim.array.level]=lval2.constval;
1850 if (close==']' && !(sym->tag == pc_tag_string && sym->dim.array.level == 0)) {
1851 /* normal array index */
1852 if (lval2.constval<0 || sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval)
1853 error(32,sym->name); /* array index out of bounds */
1854 if (lval2.constval!=0) {
1855 /* don't add offsets for zero subscripts */
1856 #if PAWN_CELL_SIZE==16
1857 ldconst(lval2.constval<<1,sALT);
1858 #elif PAWN_CELL_SIZE==32
1859 ldconst(lval2.constval<<2,sALT);
1860 #elif PAWN_CELL_SIZE==64
1861 ldconst(lval2.constval<<3,sALT);
1863 #error Unsupported cell size
1868 /* character index */
1869 if (lval2.constval<0 || sym->dim.array.length!=0
1870 && sym->dim.array.length*((8*sizeof(cell))/sCHARBITS)<=(ucell)lval2.constval)
1871 error(32,sym->name); /* array index out of bounds */
1872 if (lval2.constval!=0) {
1873 /* don't add offsets for zero subscripts */
1875 ldconst(lval2.constval<<1,sALT);/* 16-bit character */
1877 ldconst(lval2.constval,sALT); /* 8-bit character */
1881 charalign(); /* align character index into array */
1883 /* if the array index is a field from an enumeration, get the tag name
1884 * from the field and save the size of the field too.
1886 assert(lval2.sym==NULL || lval2.sym->dim.array.level==0);
1887 if (lval2.sym!=NULL && lval2.sym->dim.array.length>0 && sym->dim.array.level==0) {
1888 lval1->tag=lval2.sym->x.tags.index;
1889 lval1->constval=lval2.sym->dim.array.length;
1892 /* array index is not constant */
1893 lval1->arrayidx=NULL; /* reset, so won't be checked */
1894 if (close==']' && !magic_string) {
1895 if (sym->dim.array.length!=0)
1896 ffbounds(sym->dim.array.length-1); /* run time check for array bounds */
1897 cell2addr(); /* normal array index */
1899 if (sym->dim.array.length!=0)
1900 ffbounds(sym->dim.array.length*(32/sCHARBITS)-1);
1901 char2addr(); /* character array index */
1904 ob_add(); /* base address was popped into secondary register */
1905 if (close!=']' || magic_string)
1906 charalign(); /* align character index into array */
1908 /* the indexed item may be another array (multi-dimensional arrays) */
1909 assert(cursym==sym && sym!=NULL); /* should still be set */
1910 if (sym->dim.array.level>0) {
1911 assert(close==']'); /* checked earlier */
1912 assert(cursym==lval1->sym);
1913 /* read the offset to the subarray and add it to the current address */
1914 lval1->ident=iARRAYCELL;
1915 pushreg(sPRI); /* the optimizer makes this to a MOVE.alt */
1919 /* adjust the "value" structure and find the referenced array */
1920 lval1->ident=iREFARRAY;
1921 lval1->sym=finddepend(sym);
1922 assert(lval1->sym!=NULL);
1923 assert(lval1->sym->dim.array.level==sym->dim.array.level-1);
1925 /* try to parse subsequent array indices */
1926 lvalue=FALSE; /* for now, a iREFARRAY is no lvalue */
1929 assert(sym->dim.array.level==0);
1930 /* set type to fetch... INDIRECTLY */
1931 if (sym->tag == pc_tag_string) {
1932 lval1->ident = iARRAYCHAR;
1934 lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
1936 /* if the array index is a field from an enumeration, get the tag name
1937 * from the field and save the size of the field too. Otherwise, the
1938 * tag is the one from the array symbol.
1940 if (lval2.ident==iCONSTEXPR && lval2.sym!=NULL
1941 && lval2.sym->dim.array.length>0 && sym->dim.array.level==0)
1943 lval1->tag=lval2.sym->x.tags.index;
1944 lval1->constval=lval2.sym->dim.array.length;
1945 if (lval2.tag==sym->x.tags.index && lval1->constval>1 && matchtoken('[')) {
1946 /* an array indexed with an enumeration field may be considered a sub-array */
1948 lvalue=FALSE; /* for now, a iREFARRAY is no lvalue */
1949 lval1->ident=iREFARRAY;
1950 /* initialize a dummy symbol, which is a copy of the current symbol,
1951 * but with an adjusted index tag
1955 /* get the tag of the root of the enumeration */
1956 assert(lval2.sym!=NULL);
1957 dummysymbol.x.tags.index=lval2.sym->x.tags.field;
1958 dummysymbol.dim.array.length=lval2.sym->dim.array.length;
1959 cursym=&dummysymbol;
1965 if (cursym!=&dummysymbol)
1966 lval1->tag=sym->tag;
1969 /* a cell in an array is an lvalue, a character in an array is not
1970 * always a *valid* lvalue */
1972 } else { /* tok=='(' -> function(...) */
1975 || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
1977 if (sym==NULL && sc_status==statFIRST) {
1978 /* could be a "use before declaration"; in that case, create a stub
1979 * function so that the usage can be marked.
1981 sym=fetchfunc(lastsymbol,0);
1983 error(103); /* insufficient memory */
1984 markusage(sym,uREAD);
1986 return error(12); /* invalid function call */
1988 } else if ((sym->usage & uMISSING)!=0) {
1989 char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
1990 funcdisplayname(symname,sym->name);
1991 error(4,symname); /* function not defined */
1993 callfunction(sym,lval1,TRUE);
1994 return FALSE; /* result of function call is no lvalue */
1997 if (sym!=NULL && lval1->ident==iFUNCTN) {
1998 assert(sym->ident==iFUNCTN);
1999 if (sc_allowproccall) {
2000 callfunction(sym,lval1,FALSE);
2004 int usage = ((sym->usage & uPUBLIC) == uPUBLIC) ? uPUBLIC : 0;
2006 for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
2007 if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage)))
2009 if (strcmp(sym->name, lval1->sym->name)==0) {
2011 code_addr = sym->codeaddr;
2018 char faketag[sNAMEMAX+1];
2020 lval1->ident=iCONSTEXPR;
2021 /* Generate a quick pseudo-tag! */
2022 if (usage == uPUBLIC) {
2023 lval1->constval=(n<<1)|1;
2024 snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n);
2026 lval1->constval=(code_addr<<1)|0;
2027 snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr);
2029 lval1->tag=pc_addfunctag(faketag);
2030 oldsym->usage |= uREAD;
2031 sym->usage |= uREAD;
2033 error(76); /* invalid function call, or syntax error */
2043 * Returns 1 if the operand is an lvalue (everything except arrays, functions
2044 * constants and -of course- errors).
2045 * Generates code to fetch the address of arrays. Code for constants is
2046 * already generated by constant().
2047 * This routine first clears the entire lval array (all fields are set to 0).
2049 * Global references: sc_intest (may be altered, but restored upon termination)
2051 static int primary(value *lval)
2058 if (matchtoken('(')){ /* sub-expression - (expression,...) */
2059 PUSHSTK_I(sc_intest);
2060 PUSHSTK_I(sc_allowtags);
2062 sc_intest=FALSE; /* no longer in "test" expression */
2063 sc_allowtags=TRUE; /* allow tagnames to be used in parenthesized expressions */
2064 sc_allowproccall=FALSE;
2066 lvalue=hier14(lval);
2067 while (matchtoken(','));
2069 lexclr(FALSE); /* clear lex() push-back, it should have been
2070 * cleared already by needtoken() */
2071 sc_allowtags=(short)POPSTK_I();
2072 sc_intest=(short)POPSTK_I();
2076 clear_value(lval); /* clear lval */
2079 /* lastsymbol is char[sNAMEMAX+1], lex() should have truncated any symbol
2080 * to sNAMEMAX significant characters */
2081 assert(strlen(st)<sizeof lastsymbol);
2082 strcpy(lastsymbol,st);
2084 if (tok==tSYMBOL && !findconst(st,NULL)) {
2085 /* first look for a local variable */
2086 if ((sym=findloc(st))!=0) {
2087 if (sym->ident==iLABEL) {
2088 error(29); /* expression error, assumed 0 */
2089 ldconst(0,sPRI); /* load 0 */
2090 return FALSE; /* return 0 for labels (expression error) */
2093 lval->ident=sym->ident;
2095 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
2096 address(sym,sPRI); /* get starting address in primary register */
2097 return FALSE; /* return 0 for array (not lvalue) */
2099 return TRUE; /* return 1 if lvalue (not label or array) */
2102 /* now try a global variable */
2103 if ((sym=findglb(st,sSTATEVAR))!=0) {
2104 if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) {
2105 /* if the function is only in the table because it was inserted as a
2106 * stub in the first pass (i.e. it was "used" but never declared or
2107 * implemented, issue an error
2109 if ((sym->usage & uPROTOTYPED)==0)
2112 if ((sym->usage & uDEFINE)==0)
2115 lval->ident=sym->ident;
2117 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
2118 address(sym,sPRI); /* get starting address in primary register */
2119 return FALSE; /* return 0 for array (not lvalue) */
2121 return TRUE; /* return 1 if lvalue (not function or array) */
2125 if (!sc_allowproccall)
2126 return error(17,st); /* undefined symbol */
2127 /* an unknown symbol, but used in a way compatible with the "procedure
2128 * call" syntax. So assume that the symbol refers to a function.
2130 assert(sc_status==statFIRST);
2131 sym=fetchfunc(st,0);
2133 error(103); /* insufficient memory */
2136 assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
2138 lval->ident=sym->ident;
2140 return FALSE; /* return 0 for function (not an lvalue) */
2142 lexpush(); /* push the token, it is analyzed by constant() */
2143 if (constant(lval)==0) {
2144 error(29); /* expression error, assumed 0 */
2145 ldconst(0,sPRI); /* load 0 */
2147 return FALSE; /* return 0 for constants (or errors) */
2150 static void clear_value(value *lval)
2156 lval->boolresult=FALSE;
2157 /* do not clear lval->arrayidx, it is preset in hier14() */
2158 /* do not clear lval->cmptag */
2161 static void setdefarray(cell *string,cell size,cell array_sz,cell *dataaddr,int fconst)
2163 /* The routine must copy the default array data onto the heap, as to avoid
2164 * that a function can change the default value. An optimization is that
2165 * the default array data is "dumped" into the data segment only once (on the
2168 assert(string!=NULL);
2170 /* check whether to dump the default array */
2171 assert(dataaddr!=NULL);
2172 if (sc_status==statWRITE && *dataaddr<0) {
2174 *dataaddr=(litidx+glb_declared)*sizeof(cell);
2175 for (i=0; i<size; i++)
2179 /* if the function is known not to modify the array (meaning that it also
2180 * does not modify the default value), directly pass the address of the
2181 * array in the data segment.
2184 ldconst(*dataaddr,sPRI);
2186 /* Generate the code:
2187 * CONST.pri dataaddr ;address of the default array data
2188 * HEAP array_sz*sizeof(cell) ;heap address in ALT
2189 * MOVS size*sizeof(cell) ;copy data from PRI to ALT
2190 * MOVE.PRI ;PRI = address on the heap
2192 ldconst(*dataaddr,sPRI);
2193 /* "array_sz" is the size of the argument (the value between the brackets
2194 * in the declaration), "size" is the size of the default array data.
2196 assert(array_sz>=size);
2197 modheap((int)array_sz*sizeof(cell));
2198 markheap(MEMUSE_STATIC, array_sz);
2199 /* ??? should perhaps fill with zeros first */
2200 memcopy(size*sizeof(cell));
2205 static int findnamedarg(arginfo *arg,char *name)
2209 for (i=0; arg[i].ident!=0 && arg[i].ident!=iVARARGS; i++)
2210 if (strcmp(arg[i].name,name)==0)
2215 int checktag(int tags[],int numtags,int exprtag)
2221 for (i=0; i<numtags; i++)
2222 if (matchtag(tags[i],exprtag,TRUE))
2223 return TRUE; /* matching tag */
2224 return FALSE; /* no tag matched */
2235 * Generates code to call a function. This routine handles default arguments
2236 * and positional as well as named parameters.
2238 static void callfunction(symbol *sym,value *lval_result,int matchparanthesis)
2240 static long nest_stkusage=0L;
2241 static int nesting=0;
2243 int argpos; /* index in the output stream (argpos==nargs if positional parameters) */
2244 int argidx=0; /* index in "arginfo" list */
2245 int nargs=0; /* number of arguments */
2247 int namedparams=FALSE;
2250 char arglist[sMAXARGS];
2251 constvalue arrayszlst = { NULL, "", 0, 0};/* array size list starts empty */
2252 constvalue taglst = { NULL, "", 0, 0}; /* tag list starts empty */
2258 lval_result->ident=iEXPRESSION; /* preset, may be changed later */
2259 lval_result->constval=0;
2260 lval_result->tag=sym->tag;
2261 /* check whether this is a function that returns an array */
2262 symret=finddepend(sym);
2263 assert(symret==NULL || symret->ident==iREFARRAY);
2266 /* allocate space on the heap for the array, and pass the pointer to the
2267 * reserved memory block as a hidden parameter
2269 retsize=(int)array_totalsize(symret);
2271 modheap(retsize*sizeof(cell));/* address is in ALT */
2272 pushreg(sALT); /* pass ALT as the last (hidden) parameter */
2273 markheap(MEMUSE_STATIC, retsize);
2274 /* also mark the ident of the result as "array" */
2275 lval_result->ident=iREFARRAY;
2276 lval_result->sym=symret;
2281 assert(nest_stkusage>=0);
2284 assert(nest_stkusage==0);
2286 sc_allowproccall=FALSE; /* parameters may not use procedure call syntax */
2288 if ((sym->flags & flgDEPRECATED)!=0) {
2289 char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
2290 error(234,sym->name,ptr); /* deprecated (probably a native function) */
2293 /* run through the arguments */
2294 arg=sym->dim.arglist;
2296 stgmark(sSTARTREORDER);
2297 memset(arglist,ARG_UNHANDLED,sizeof arglist);
2298 if (matchparanthesis) {
2299 /* Opening brace was already parsed, if closing brace follows, this
2300 * call passes no parameters.
2302 close=matchtoken(')');
2304 /* When we find an end of line here, it may be a function call passing
2305 * no parameters, or it may be that the first parameter is on a line
2306 * below. But as a parameter can be anything, this is difficult to check.
2307 * The only simple check that we have is the use of "named parameters".
2309 close=matchtoken(tTERM);
2311 close=!matchtoken('.');
2313 lexpush(); /* reset the '.' */
2318 if (matchtoken('.')) {
2320 if (needtoken(tSYMBOL))
2321 tokeninfo(&lexval,&lexstr);
2324 argpos=findnamedarg(arg,lexstr);
2326 error(17,lexstr); /* undefined symbol */
2327 break; /* exit loop, argpos is invalid */
2333 error(44); /* positional parameters must precede named parameters */
2336 /* the number of arguments this was already checked at the declaration
2337 * of the function; check it again for functions with a variable
2340 if (argpos>=sMAXARGS)
2341 error(45); /* too many function arguments */
2342 stgmark((char)(sEXPRSTART+argpos));/* mark beginning of new expression in stage */
2343 if (arglist[argpos]!=ARG_UNHANDLED)
2344 error(58); /* argument already set */
2345 if (matchtoken('_')) {
2346 arglist[argpos]=ARG_IGNORED; /* flag argument as "present, but ignored" */
2347 if (arg[argidx].ident==0 || arg[argidx].ident==iVARARGS) {
2348 error(92); /* argument count mismatch */
2349 } else if (!arg[argidx].hasdefault) {
2350 error(34,nargs+1); /* argument has no default value */
2352 if (arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS)
2354 /* The rest of the code to handle default values is at the bottom
2355 * of this routine where default values for unspecified parameters
2356 * are (also) handled. Note that above, the argument is flagged as
2360 arglist[argpos]=ARG_DONE; /* flag argument as "present" */
2361 if (arg[argidx].numtags==1) /* set the expected tag, if any */
2362 lval.cmptag=arg[argidx].tags[0];
2363 lvalue=hier14(&lval);
2364 assert(sc_status==statFIRST || arg[argidx].tags!=NULL);
2365 switch (arg[argidx].ident) {
2367 error(92); /* argument count mismatch */
2370 /* always pass by reference */
2371 if (lval.ident==iVARIABLE || lval.ident==iREFERENCE) {
2372 assert(lval.sym!=NULL);
2373 if ((lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0) {
2374 /* treat a "const" variable passed to a function with a non-const
2375 * "variable argument list" as a constant here */
2377 error(22); /* need lvalue */
2379 rvalue(&lval); /* get value in PRI */
2380 setheap_pri(); /* address of the value on the heap in PRI */
2381 heapalloc+=markheap(MEMUSE_STATIC, 1);
2384 } else if (lvalue) {
2385 address(lval.sym,sPRI);
2387 setheap_pri(); /* address of the value on the heap in PRI */
2388 heapalloc+=markheap(MEMUSE_STATIC, 1);
2391 } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION)
2393 /* allocate a cell on the heap and store the
2394 * value (already in PRI) there */
2395 setheap_pri(); /* address of the value on the heap in PRI */
2396 heapalloc+=markheap(MEMUSE_STATIC, 1);
2399 /* ??? handle const array passed by reference */
2400 /* otherwise, the address is already in PRI */
2402 markusage(lval.sym,uWRITTEN);
2403 if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
2404 && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2407 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2410 if (lval.ident==iLABEL || lval.ident==iFUNCTN || lval.ident==iREFFUNC
2411 || lval.ident==iARRAY || lval.ident==iREFARRAY)
2412 error(35,argidx+1); /* argument type mismatch */
2414 rvalue(&lval); /* get value (direct or indirect) */
2415 /* otherwise, the expression result is already in PRI */
2416 assert(arg[argidx].numtags>0);
2417 check_userop(NULL,lval.tag,arg[argidx].tags[0],2,NULL,&lval.tag);
2418 if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
2419 && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2422 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2423 argidx++; /* argument done */
2427 error(35,argidx+1); /* argument type mismatch */
2428 if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
2429 error(35,argidx+1); /* argument type mismatch */
2430 if (lval.ident==iVARIABLE || lval.ident==iREFERENCE) {
2432 assert(lval.sym!=NULL);
2433 address(lval.sym,sPRI);
2435 setheap_pri(); /* address of the value on the heap in PRI */
2436 heapalloc+=markheap(MEMUSE_STATIC, 1);
2440 /* otherwise, the address is already in PRI */
2441 if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2444 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2445 argidx++; /* argument done */
2447 markusage(lval.sym,uWRITTEN);
2450 if (lval.ident!=iARRAY && lval.ident!=iREFARRAY
2451 && lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR)
2453 error(35,argidx+1); /* argument type mismatch */
2456 if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
2457 error(35,argidx+1); /* argument type mismatch */
2458 /* Verify that the dimensions match with those in arg[argidx].
2459 * A literal array always has a single dimension.
2460 * An iARRAYCELL parameter is also assumed to have a single dimension.
2462 if (lval.sym==NULL || lval.ident==iARRAYCELL || lval.ident==iARRAYCHAR) {
2463 if (arg[argidx].numdim!=1) {
2464 error(48); /* array dimensions must match */
2465 } else if (arg[argidx].dim[0]!=0) {
2466 assert(arg[argidx].dim[0]>0);
2467 if (lval.ident==iARRAYCELL) {
2468 error(47); /* array sizes must match */
2470 assert(lval.constval!=0); /* literal array must have a size */
2471 /* A literal array must have exactly the same size as the
2472 * function argument; a literal string may be smaller than
2473 * the function argument.
2475 if (lval.constval>0 && arg[argidx].dim[0]!=lval.constval
2476 || lval.constval<0 && arg[argidx].dim[0] < -lval.constval)
2477 error(47); /* array sizes must match */
2480 if (lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR) {
2481 /* save array size, for default values with uSIZEOF flag */
2482 cell array_sz=lval.constval;
2483 assert(array_sz!=0);/* literal array must have a size */
2485 array_sz= -array_sz;
2486 append_constval(&arrayszlst,arg[argidx].name,array_sz,0);
2489 symbol *sym=lval.sym;
2492 if (sym->dim.array.level+1!=arg[argidx].numdim)
2493 error(48); /* array dimensions must match */
2494 /* the lengths for all dimensions must match, unless the dimension
2495 * length was defined at zero (which means "undefined")
2497 while (sym->dim.array.level>0) {
2498 assert(level<sDIMEN_MAX);
2499 if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level])
2500 error(47); /* array sizes must match */
2501 else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE))
2502 error(229,sym->name); /* index tag mismatch */
2503 append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level);
2504 sym=finddepend(sym);
2508 /* the last dimension is checked too, again, unless it is zero */
2509 assert(level<sDIMEN_MAX);
2511 if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level])
2512 error(47); /* array sizes must match */
2513 else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE))
2514 error(229,sym->name); /* index tag mismatch */
2515 append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level);
2517 /* address already in PRI */
2518 if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2521 append_constval(&taglst,arg[argidx].name,lval.tag,0);
2522 // ??? set uWRITTEN?
2523 argidx++; /* argument done */
2526 pushreg(sPRI); /* store the function argument on the stack */
2527 markexpr(sPARM,NULL,0); /* mark the end of a sub-expression */
2530 assert(arglist[argpos]!=ARG_UNHANDLED);
2532 if (matchparanthesis) {
2533 close=matchtoken(')');
2534 if (!close) /* if not paranthese... */
2535 if (!needtoken(',')) /* ...should be comma... */
2536 break; /* ...but abort loop if neither */
2538 close=!matchtoken(',');
2539 if (close) { /* if not comma... */
2540 if (needtoken(tTERM)==1)/* ...must be end of statement */
2541 lexpush(); /* push again, because end of statement is analised later */
2544 } while (!close && freading && !matchtoken(tENDEXPR)); /* do */
2546 /* check remaining function arguments (they may have default values) */
2547 for (argidx=0; arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS; argidx++) {
2548 if (arglist[argidx]==ARG_DONE)
2549 continue; /* already seen and handled this argument */
2550 /* in this first stage, we also skip the arguments with uSIZEOF and uTAGOF;
2551 * these are handled last
2553 if ((arg[argidx].hasdefault & uSIZEOF)!=0 || (arg[argidx].hasdefault & uTAGOF)!=0) {
2554 assert(arg[argidx].ident==iVARIABLE);
2557 stgmark((char)(sEXPRSTART+argidx));/* mark beginning of new expression in stage */
2558 if (arg[argidx].hasdefault) {
2559 if (arg[argidx].ident==iREFARRAY) {
2561 setdefarray(arg[argidx].defvalue.array.data,
2562 arg[argidx].defvalue.array.size,
2563 arg[argidx].defvalue.array.arraysize,
2564 &arg[argidx].defvalue.array.addr,
2565 (arg[argidx].usage & uCONST)!=0);
2566 if ((arg[argidx].usage & uCONST)==0) {
2567 heapalloc+=arg[argidx].defvalue.array.arraysize;
2568 nest_stkusage+=arg[argidx].defvalue.array.arraysize;
2570 /* keep the lengths of all dimensions of a multi-dimensional default array */
2571 assert(arg[argidx].numdim>0);
2572 if (arg[argidx].numdim==1) {
2573 append_constval(&arrayszlst,arg[argidx].name,arg[argidx].defvalue.array.arraysize,0);
2575 for (level=0; level<arg[argidx].numdim; level++) {
2576 assert(level<sDIMEN_MAX);
2577 append_constval(&arrayszlst,arg[argidx].name,arg[argidx].dim[level],level);
2580 } else if (arg[argidx].ident==iREFERENCE) {
2581 setheap(arg[argidx].defvalue.val);
2582 /* address of the value on the heap in PRI */
2583 heapalloc+=markheap(MEMUSE_STATIC, 1);
2586 int dummytag=arg[argidx].tags[0];
2587 ldconst(arg[argidx].defvalue.val,sPRI);
2588 assert(arg[argidx].numtags>0);
2589 check_userop(NULL,arg[argidx].defvalue_tag,arg[argidx].tags[0],2,NULL,&dummytag);
2590 assert(dummytag==arg[argidx].tags[0]);
2592 pushreg(sPRI); /* store the function argument on the stack */
2593 markexpr(sPARM,NULL,0); /* mark the end of a sub-expression */
2596 error(92,argidx); /* argument count mismatch */
2598 if (arglist[argidx]==ARG_UNHANDLED)
2600 arglist[argidx]=ARG_DONE;
2602 /* now a second loop to catch the arguments with default values that are
2603 * the "sizeof" or "tagof" of other arguments
2605 for (argidx=0; arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS; argidx++) {
2608 if (arglist[argidx]==ARG_DONE)
2609 continue; /* already seen and handled this argument */
2610 stgmark((char)(sEXPRSTART+argidx));/* mark beginning of new expression in stage */
2611 assert(arg[argidx].ident==iVARIABLE); /* if "sizeof", must be single cell */
2612 /* if unseen, must be "sizeof" or "tagof" */
2613 assert((arg[argidx].hasdefault & uSIZEOF)!=0 || (arg[argidx].hasdefault & uTAGOF)!=0);
2614 if ((arg[argidx].hasdefault & uSIZEOF)!=0) {
2615 /* find the argument; if it isn't found, the argument's default value
2616 * was a "sizeof" of a non-array (a warning for this was already given
2617 * when declaring the function)
2619 asz=find_constval(&arrayszlst,arg[argidx].defvalue.size.symname,
2620 arg[argidx].defvalue.size.level);
2622 array_sz=asz->value;
2624 error(224,arg[argidx].name); /* indeterminate array size in "sizeof" expression */
2629 asz=find_constval(&taglst,arg[argidx].defvalue.size.symname,
2630 arg[argidx].defvalue.size.level);
2632 exporttag(asz->value);
2633 array_sz=asz->value | PUBLICTAG; /* must be set, because it just was exported */
2638 ldconst(array_sz,sPRI);
2639 pushreg(sPRI); /* store the function argument on the stack */
2640 markexpr(sPARM,NULL,0);
2642 if (arglist[argidx]==ARG_UNHANDLED)
2644 arglist[argidx]=ARG_DONE;
2646 stgmark(sENDREORDER); /* mark end of reversed evaluation */
2647 pushval((cell)nargs /* *sizeof(cell)*/ );
2649 ffcall(sym,NULL,nargs);
2650 if (sc_status!=statSKIP)
2651 markusage(sym,uREAD); /* do not mark as "used" when this call itself is skipped */
2652 if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL)
2653 sym->x.lib->value += 1; /* increment "usage count" of the library */
2655 popreg(sPRI); /* pop hidden parameter as function result */
2656 sideeffect=TRUE; /* assume functions carry out a side-effect */
2657 delete_consttable(&arrayszlst); /* clear list of array sizes */
2658 delete_consttable(&taglst); /* clear list of parameter tags */
2660 /* maintain max. amount of memory used */
2663 totalsize=declared+heapalloc+1; /* local variables & return value size,
2664 * +1 for PROC opcode */
2665 if (lval_result->ident==iREFARRAY)
2666 totalsize++; /* add hidden parameter (on the stack) */
2667 if ((sym->usage & uNATIVE)==0)
2668 totalsize++; /* add "call" opcode */
2669 totalsize+=nest_stkusage;
2670 assert(curfunc!=NULL);
2671 if (curfunc->x.stacksize<totalsize)
2672 curfunc->x.stacksize=totalsize;
2673 nest_stkusage-=nargs+heapalloc+1; /* stack/heap space, +1 for argcount param */
2674 /* if there is a syntax error in the script, the stack calculation is
2675 * probably incorrect; but we may not allow it to drop below zero
2677 if (nest_stkusage<0)
2681 /* scrap any arrays left on the heap, with the exception of the array that
2682 * this function has as a result (in other words, scrap all arrays on the
2683 * heap that caused by expressions in the function arguments)
2691 * Returns a non-zero value if lval1 an array and lval2 is not an array and
2692 * the operation is addition or subtraction.
2694 * Returns the "shift" count (1 for 16-bit, 2 for 32-bit) to align a cell
2695 * to an array offset.
2697 static int dbltest(void (*oper)(),value *lval1,value *lval2)
2699 if ((oper!=ob_add) && (oper!=ob_sub))
2701 if (lval1->ident!=iARRAY)
2703 if (lval2->ident==iARRAY)
2705 return sizeof(cell)/2; /* 1 for 16-bit, 2 for 32-bit */
2710 * Test whether an operator is commutative, i.e. x oper y == y oper x.
2711 * Commutative operators are: + (addition)
2712 * * (multiplication)
2719 * If in an expression, code for the left operand has been generated and
2720 * the right operand is a constant and the operator is commutative, the
2721 * precautionary "push" of the primary register is scrapped and the constant
2722 * is read into the secondary register immediately.
2724 static int commutative(void (*oper)())
2726 return oper==ob_add || oper==os_mult
2727 || oper==ob_eq || oper==ob_ne
2728 || oper==ob_and || oper==ob_xor || oper==ob_or;
2733 * Generates code to fetch a number, a literal character (which is returned
2734 * by lex() as a number as well) or a literal string (lex() stores the
2735 * strings in the literal queue). If the operand was a number, it is stored
2736 * in lval->constval.
2738 * The function returns 1 if the token was a constant or a string, 0
2741 static int constant(value *lval)
2743 int tok,index,ident;
2747 int cmptag=lval->cmptag;
2750 if (tok==tSYMBOL && (sym=findconst(st,&cmptag))!=0) {
2752 error(91,sym->name); /* ambiguity: multiple matching constants (different tags) */
2753 lval->constval=sym->addr;
2754 ldconst(lval->constval,sPRI);
2755 lval->ident=iCONSTEXPR;
2758 markusage(sym,uREAD);
2759 } else if (tok==tNUMBER) {
2761 ldconst(lval->constval,sPRI);
2762 lval->ident=iCONSTEXPR;
2763 } else if (tok==tRATIONAL) {
2765 ldconst(lval->constval,sPRI);
2766 lval->ident=iCONSTEXPR;
2767 lval->tag=sc_rationaltag;
2768 } else if (tok==tSTRING) {
2769 /* lex() stores starting index of string in the literal table in 'val' */
2770 ldconst((val+glb_declared)*sizeof(cell),sPRI);
2771 lval->ident=iARRAY; /* pretend this is a global array */
2772 lval->constval=val-litidx; /* constval == the negative value of the
2773 * size of the literal array; using a negative
2774 * value distinguishes between literal arrays
2775 * and literal strings (this was done for
2776 * array assignment). */
2777 lval->tag=pc_tag_string;
2778 } else if (tok=='{') {
2782 /* cannot call constexpr() here, because "staging" is already turned
2783 * on at this point */
2785 stgget(&index,&cidx); /* mark position in code generator */
2786 ident=expression(&item,&tag,NULL,FALSE,NULL);
2787 stgdel(index,cidx); /* scratch generated code */
2788 if (ident!=iCONSTEXPR)
2789 error(8); /* must be constant expression */
2792 else if (!matchtag(lasttag,tag,FALSE))
2793 error(213); /* tagname mismatch */
2794 litadd(item); /* store expression result in literal table */
2795 } while (matchtoken(','));
2796 if (!needtoken('}'))
2798 ldconst((val+glb_declared)*sizeof(cell),sPRI);
2799 lval->ident=iARRAY; /* pretend this is a global array */
2800 lval->constval=litidx-val; /* constval == the size of the literal array */
2802 return FALSE; /* no, it cannot be interpreted as a constant */
2804 return TRUE; /* yes, it was a constant value */