1 /*  Small compiler - Recursive descend expresion parser
2  *
3  *  Copyright (c) ITB CompuPhase, 1997-2003
4  *
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.
8  *
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:
12  *
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 required.
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.
20  *
21  *  Version: $Id$
22  */
23 
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <assert.h>
30 #include <stdio.h>
31 #include <limits.h>		/* for PATH_MAX */
32 #include <string.h>
33 
34 #include "embryo_cc_sc.h"
35 
36 static int          skim(int *opstr, void (*testfunc) (int), int dropval,
37 			 int endval, int (*hier) (value *), value * lval);
38 static void         dropout(int lvalue, void (*testfunc) (int val), int exit1,
39 			    value * lval);
40 static int          plnge(int *opstr, int opoff, int (*hier) (value * lval),
41 			  value * lval, char *forcetag, int chkbitwise);
42 static int          plnge1(int (*hier) (value * lval), value * lval);
43 static void         plnge2(void (*oper) (void),
44 			   int (*hier) (value * lval),
45 			   value * lval1, value * lval2);
46 static cell         calc(cell left, void (*oper) (), cell right,
47 			 char *boolresult);
48 static int          hier13(value * lval);
49 static int          hier12(value * lval);
50 static int          hier11(value * lval);
51 static int          hier10(value * lval);
52 static int          hier9(value * lval);
53 static int          hier8(value * lval);
54 static int          hier7(value * lval);
55 static int          hier6(value * lval);
56 static int          hier5(value * lval);
57 static int          hier4(value * lval);
58 static int          hier3(value * lval);
59 static int          hier2(value * lval);
60 static int          hier1(value * lval1);
61 static int          primary(value * lval);
62 static void         clear_value(value * lval);
63 static void         callfunction(symbol * sym);
64 static int          dbltest(void (*oper) (), value * lval1, value * lval2);
65 static int          commutative(void (*oper) ());
66 static int          constant(value * lval);
67 
68 static char         lastsymbol[sNAMEMAX + 1];	/* name of last function/variable */
69 static int          bitwise_opercount;	/* count of bitwise operators in an expression */
70 
71 /* Function addresses of binary operators for signed operations */
72 static void         (*op1[17]) (void) =
73 {
74    os_mult, os_div, os_mod,	/* hier3, index 0 */
75       ob_add, ob_sub,		/* hier4, index 3 */
76       ob_sal, os_sar, ou_sar,	/* hier5, index 5 */
77       ob_and,			/* hier6, index 8 */
78       ob_xor,			/* hier7, index 9 */
79       ob_or,			/* hier8, index 10 */
80       os_le, os_ge, os_lt, os_gt,	/* hier9, index 11 */
81       ob_eq, ob_ne,		/* hier10, index 15 */
82 };
83 /* These two functions are defined because the functions inc() and dec() in
84  * SC4.C have a different prototype than the other code generation functions.
85  * The arrays for user-defined functions use the function pointers for
86  * identifying what kind of operation is requested; these functions must all
87  * have the same prototype. As inc() and dec() are special cases already, it
88  * is simplest to add two "do-nothing" functions.
89  */
90 static void
user_inc(void)91 user_inc(void)
92 {
93 }
94 static void
user_dec(void)95 user_dec(void)
96 {
97 }
98 
99 /*
100  *  Searches for a binary operator a list of operators. The list is stored in
101  *  the array "list". The last entry in the list should be set to 0.
102  *
103  *  The index of an operator in "list" (if found) is returned in "opidx". If
104  *  no operator is found, nextop() returns 0.
105  */
106 static int
nextop(int * opidx,int * list)107 nextop(int *opidx, int *list)
108 {
109    *opidx = 0;
110    while (*list)
111      {
112 	if (matchtoken(*list))
113 	  {
114 	     return TRUE;	/* found! */
115 	  }
116 	else
117 	  {
118 	     list += 1;
119 	     *opidx += 1;
120 	  }			/* if */
121      }				/* while */
122    return FALSE;		/* entire list scanned, nothing found */
123 }
124 
125 int
check_userop(void (* oper)(void),int tag1,int tag2,int numparam,value * lval,int * resulttag)126 check_userop(void   (*oper) (void), int tag1, int tag2, int numparam,
127 	     value * lval, int *resulttag)
128 {
129    static char        *binoperstr[] = { "*", "/", "%", "+", "-", "", "", "",
130       "", "", "", "<=", ">=", "<", ">", "==", "!="
131    };
132    static int          binoper_savepri[] =
133       { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
134       FALSE, FALSE, FALSE, FALSE, FALSE,
135       TRUE, TRUE, TRUE, TRUE, FALSE, FALSE
136    };
137    static char        *unoperstr[] = { "!", "-", "++", "--" };
138    static void         (*unopers[]) (void) =
139    {
140    lneg, neg, user_inc, user_dec};
141    char                opername[4] = "", symbolname[sNAMEMAX + 1];
142    int                 i, swapparams, savepri, savealt;
143    int                 paramspassed;
144    symbol             *sym;
145 
146    /* since user-defined operators on untagged operands are forbidden, we have
147     * a quick exit.
148     */
149    assert(numparam == 1 || numparam == 2);
150    if (tag1 == 0 && (numparam == 1 || tag2 == 0))
151       return FALSE;
152 
153    savepri = savealt = FALSE;
154    /* find the name with the operator */
155    if (numparam == 2)
156      {
157 	if (!oper)
158 	  {
159 	     /* assignment operator: a special case */
160 	     strcpy(opername, "=");
161 	     if (lval
162 		 && (lval->ident == iARRAYCELL || lval->ident == iARRAYCHAR))
163 		savealt = TRUE;
164 	  }
165 	else
166 	  {
167 	     assert((sizeof binoperstr / sizeof binoperstr[0]) ==
168 		    (sizeof op1 / sizeof op1[0]));
169 	     for (i = 0; i < (int)(sizeof op1 / sizeof op1[0]); i++)
170 	       {
171 		  if (oper == op1[i])
172 		    {
173 		       strncpy(opername, binoperstr[i], sizeof(opername) - 1);
174                        opername[sizeof(opername) - 1] = 0;
175 		       savepri = binoper_savepri[i];
176 		       break;
177 		    }		/* if */
178 	       }		/* for */
179 	  }			/* if */
180      }
181    else
182      {
183 	assert(oper != NULL);
184 	assert(numparam == 1);
185 	/* try a select group of unary operators */
186 	assert((sizeof unoperstr / sizeof unoperstr[0]) ==
187 	       (sizeof unopers / sizeof unopers[0]));
188 	if (opername[0] == '\0')
189 	  {
190 	     for (i = 0; i < (int)(sizeof unopers / sizeof unopers[0]); i++)
191 	       {
192 		  if (oper == unopers[i])
193 		    {
194 		       strncpy(opername, unoperstr[i], sizeof(opername) - 1);
195                        opername[sizeof(opername) - 1] = 0;
196 		       break;
197 		    }		/* if */
198 	       }		/* for */
199 	  }			/* if */
200      }				/* if */
201    /* if not found, quit */
202    if (opername[0] == '\0')
203       return FALSE;
204 
205    /* create a symbol name from the tags and the operator name */
206    assert(numparam == 1 || numparam == 2);
207    operator_symname(symbolname, opername, tag1, tag2, numparam, tag2);
208    swapparams = FALSE;
209    sym = findglb(symbolname);
210    if (!sym /*|| (sym->usage & uDEFINE)==0 */ )
211      {				/* ??? should not check uDEFINE; first pass clears these bits */
212 	/* check for commutative operators */
213 	if (tag1 == tag2 || !oper || !commutative(oper))
214 	   return FALSE;	/* not commutative, cannot swap operands */
215 	/* if arrived here, the operator is commutative and the tags are different,
216 	 * swap tags and try again
217 	 */
218 	assert(numparam == 2);	/* commutative operator must be a binary operator */
219 	operator_symname(symbolname, opername, tag2, tag1, numparam, tag1);
220 	swapparams = TRUE;
221 	sym = findglb(symbolname);
222 	if (!sym /*|| (sym->usage & uDEFINE)==0 */ )
223 	   return FALSE;
224      }				/* if */
225 
226    /* check existence and the proper declaration of this function */
227    if ((sym->usage & uMISSING) != 0 || (sym->usage & uPROTOTYPED) == 0)
228      {
229 	char                symname[2 * sNAMEMAX + 16];	/* allow space for user defined operators */
230 
231 	funcdisplayname(symname, sym->name);
232 	if ((sym->usage & uMISSING) != 0)
233 	   error(4, symname);	/* function not defined */
234 	if ((sym->usage & uPROTOTYPED) == 0)
235 	   error(71, symname);	/* operator must be declared before use */
236      }				/* if */
237 
238    /* we don't want to use the redefined operator in the function that
239     * redefines the operator itself, otherwise the snippet below gives
240     * an unexpected recursion:
241     *    fixed:operator+(fixed:a, fixed:b)
242     *        return a + b
243     */
244    if (sym == curfunc)
245       return FALSE;
246 
247    /* for increment and decrement operators, the symbol must first be loaded
248     * (and stored back afterwards)
249     */
250    if (oper == user_inc || oper == user_dec)
251      {
252 	assert(!savepri);
253 	assert(lval != NULL);
254 	if (lval->ident == iARRAYCELL || lval->ident == iARRAYCHAR)
255 	   push1();		/* save current address in PRI */
256 	rvalue(lval);		/* get the symbol's value in PRI */
257      }				/* if */
258 
259    assert(!savepri || !savealt);	/* either one MAY be set, but not both */
260    if (savepri)
261      {
262 	/* the chained comparison operators require that the ALT register is
263 	 * unmodified, so we save it here; actually, we save PRI because the normal
264 	 * instruction sequence (without user operator) swaps PRI and ALT
265 	 */
266 	push1();		/* right-hand operand is in PRI */
267      }
268    else if (savealt)
269      {
270 	/* for the assignment operator, ALT may contain an address at which the
271 	 * result must be stored; this address must be preserved across the
272 	 * call
273 	 */
274 	assert(lval != NULL);	/* this was checked earlier */
275 	assert(lval->ident == iARRAYCELL || lval->ident == iARRAYCHAR);	/* checked earlier */
276 	push2();
277      }				/* if */
278 
279    /* push parameters, call the function */
280    paramspassed = (!oper) ? 1 : numparam;
281    switch (paramspassed)
282      {
283      case 1:
284 	push1();
285 	break;
286      case 2:
287 	/* note that 1) a function expects that the parameters are pushed
288 	 * in reversed order, and 2) the left operand is in the secondary register
289 	 * and the right operand is in the primary register */
290 	if (swapparams)
291 	  {
292 	     push2();
293 	     push1();
294 	  }
295 	else
296 	  {
297 	     push1();
298 	     push2();
299 	  }			/* if */
300 	break;
301      default:
302 	assert(0);
303      }				/* switch */
304    endexpr(FALSE);		/* mark the end of a sub-expression */
305    pushval((cell) paramspassed * sizeof(cell));
306    assert(sym->ident == iFUNCTN);
307    ffcall(sym, paramspassed);
308    if (sc_status != statSKIP)
309       markusage(sym, uREAD);	/* do not mark as "used" when this call itself is skipped */
310    if (sym->x.lib)
311       sym->x.lib->value += 1;	/* increment "usage count" of the library */
312    sideeffect = TRUE;		/* assume functions carry out a side-effect */
313    assert(resulttag != NULL);
314    *resulttag = sym->tag;	/* save tag of the called function */
315 
316    if (savepri || savealt)
317       pop2();			/* restore the saved PRI/ALT that into ALT */
318    if (oper == user_inc || oper == user_dec)
319      {
320 	assert(lval != NULL);
321 	if (lval->ident == iARRAYCELL || lval->ident == iARRAYCHAR)
322 	   pop2();		/* restore address (in ALT) */
323 	store(lval);		/* store PRI in the symbol */
324 	moveto1();		/* make sure PRI is restored on exit */
325      }				/* if */
326    return TRUE;
327 }
328 
329 int
matchtag(int formaltag,int actualtag,int allowcoerce)330 matchtag(int formaltag, int actualtag, int allowcoerce)
331 {
332    if (formaltag != actualtag)
333      {
334 	/* if the formal tag is zero and the actual tag is not "fixed", the actual
335 	 * tag is "coerced" to zero
336 	 */
337 	if (!allowcoerce || formaltag != 0 || (actualtag & FIXEDTAG) != 0)
338 	   return FALSE;
339      }				/* if */
340    return TRUE;
341 }
342 
343 /*
344  *  The AMX pseudo-processor has no direct support for logical (boolean)
345  *  operations. These have to be done via comparing and jumping. Since we are
346  *  already jumping through the code, we might as well implement an "early
347  *  drop-out" evaluation (also called "short-circuit"). This conforms to
348  *  standard C:
349  *
350  *  expr1 || expr2           expr2 will only be evaluated if expr1 is false.
351  *  expr1 && expr2           expr2 will only be evaluated if expr1 is true.
352  *
353  *  expr1 || expr2 && expr3  expr2 will only be evaluated if expr1 is false
354  *                           and expr3 will only be evaluated if expr1 is
355  *                           false and expr2 is true.
356  *
357  *  Code generation for the last example proceeds thus:
358  *
359  *      evaluate expr1
360  *      operator || found
361  *      jump to "l1" if result of expr1 not equal to 0
362  *      evaluate expr2
363  *      ->  operator && found; skip to higher level in hierarchy diagram
364  *          jump to "l2" if result of expr2 equal to 0
365  *          evaluate expr3
366  *          jump to "l2" if result of expr3 equal to 0
367  *          set expression result to 1 (true)
368  *          jump to "l3"
369  *      l2: set expression result to 0 (false)
370  *      l3:
371  *      <-  drop back to previous hierarchy level
372  *      jump to "l1" if result of expr2 && expr3 not equal to 0
373  *      set expression result to 0 (false)
374  *      jump to "l4"
375  *  l1: set expression result to 1 (true)
376  *  l4:
377  *
378  */
379 
380 /*  Skim over terms adjoining || and && operators
381  *  dropval   The value of the expression after "dropping out". An "or" drops
382  *            out when the left hand is TRUE, so dropval must be 1 on "or"
383  *            expressions.
384  *  endval    The value of the expression when no expression drops out. In an
385  *            "or" expression, this happens when both the left hand and the
386  *            right hand are FALSE, so endval must be 0 for "or" expressions.
387  */
388 static int
skim(int * opstr,void (* testfunc)(int),int dropval,int endval,int (* hier)(value *),value * lval)389 skim(int *opstr, void (*testfunc) (int), int dropval, int endval,
390      int (*hier) (value *), value * lval)
391 {
392    int                 lvalue, hits, droplab, endlab, opidx;
393    int                 allconst;
394    cell                constval;
395    int                 idx;
396    cell                cidx;
397 
398    stgget(&idx, &cidx);	/* mark position in code generator */
399    hits = FALSE;		/* no logical operators "hit" yet */
400    allconst = TRUE;		/* assume all values "const" */
401    constval = 0;
402    droplab = 0;			/* to avoid a compiler warning */
403    for (;;)
404      {
405 	lvalue = plnge1(hier, lval);	/* evaluate left expression */
406 
407 	allconst = allconst && (lval->ident == iCONSTEXPR);
408 	if (allconst)
409 	  {
410 	     if (hits)
411 	       {
412 		  /* one operator was already found */
413 		  if (testfunc == jmp_ne0)
414 		     lval->constval = lval->constval || constval;
415 		  else
416 		     lval->constval = lval->constval && constval;
417 	       }		/* if */
418 	     constval = lval->constval;	/* save result accumulated so far */
419 	  }			/* if */
420 
421 	if (nextop(&opidx, opstr))
422 	  {
423 	     if (!hits)
424 	       {
425 		  /* this is the first operator in the list */
426 		  hits = TRUE;
427 		  droplab = getlabel();
428 	       }		/* if */
429 	     dropout(lvalue, testfunc, droplab, lval);
430 	  }
431 	else if (hits)
432 	  {			/* no (more) identical operators */
433 	     dropout(lvalue, testfunc, droplab, lval);	/* found at least one operator! */
434 	     const1(endval);
435 	     jumplabel(endlab = getlabel());
436 	     setlabel(droplab);
437 	     const1(dropval);
438 	     setlabel(endlab);
439 	     lval->sym = NULL;
440 	     lval->tag = 0;
441 	     if (allconst)
442 	       {
443 		  lval->ident = iCONSTEXPR;
444 		  lval->constval = constval;
445 		  stgdel(idx, cidx);	/* scratch generated code and calculate */
446 	       }
447 	     else
448 	       {
449 		  lval->ident = iEXPRESSION;
450 		  lval->constval = 0;
451 	       }		/* if */
452 	     return FALSE;
453 	  }
454 	else
455 	  {
456 	     return lvalue;	/* none of the operators in "opstr" were found */
457 	  }			/* if */
458 
459      }				/* while */
460 }
461 
462 /*
463  *  Reads into the primary register the variable pointed to by lval if
464  *  plunging through the hierarchy levels detected an lvalue. Otherwise
465  *  if a constant was detected, it is loaded. If there is no constant and
466  *  no lvalue, the primary register must already contain the expression
467  *  result.
468  *
469  *  After that, the compare routines "jmp_ne0" or "jmp_eq0" are called, which
470  *  compare the primary register against 0, and jump to the "early drop-out"
471  *  label "exit1" if the condition is true.
472  */
473 static void
dropout(int lvalue,void (* testfunc)(int val),int exit1,value * lval)474 dropout(int lvalue, void (*testfunc) (int val), int exit1, value * lval)
475 {
476    if (lvalue)
477       rvalue(lval);
478    else if (lval->ident == iCONSTEXPR)
479       const1(lval->constval);
480    (*testfunc) (exit1);
481 }
482 
483 static void
checkfunction(value * lval)484 checkfunction(value * lval)
485 {
486    symbol             *sym = lval->sym;
487 
488    if (!sym || (sym->ident != iFUNCTN && sym->ident != iREFFUNC))
489       return;			/* no known symbol, or not a function result */
490 
491    if ((sym->usage & uDEFINE) != 0)
492      {
493 	/* function is defined, can now check the return value (but make an
494 	 * exception for directly recursive functions)
495 	 */
496 	if (sym != curfunc && (sym->usage & uRETVALUE) == 0)
497 	  {
498 	     char                symname[2 * sNAMEMAX + 16];	/* allow space for user defined operators */
499 
500 	     funcdisplayname(symname, sym->name);
501 	     error(209, symname);	/* function should return a value */
502 	  }			/* if */
503      }
504    else
505      {
506 	/* function not yet defined, set */
507 	sym->usage |= uRETVALUE;	/* make sure that a future implementation of
508 					 * the function uses "return <value>" */
509      }				/* if */
510 }
511 
512 /*
513  *  Plunge to a lower level
514  */
515 static int
plnge(int * opstr,int opoff,int (* hier)(value * lval),value * lval,char * forcetag,int chkbitwise)516 plnge(int *opstr, int opoff, int (*hier) (value * lval), value * lval,
517       char *forcetag, int chkbitwise)
518 {
519    int                 lvalue, opidx;
520    int                 count;
521    value               lval2 = { NULL, 0, 0, 0, 0, NULL };
522 
523    lvalue = plnge1(hier, lval);
524    if (nextop(&opidx, opstr) == 0)
525       return lvalue;		/* no operator in "opstr" found */
526    if (lvalue)
527       rvalue(lval);
528    count = 0;
529    do
530      {
531 	if (chkbitwise && count++ > 0 && bitwise_opercount != 0)
532 	   error(212);
533 	opidx += opoff;		/* add offset to index returned by nextop() */
534 	plnge2(op1[opidx], hier, lval, &lval2);
535 	if (op1[opidx] == ob_and || op1[opidx] == ob_or)
536 	   bitwise_opercount++;
537 	if (forcetag)
538 	   lval->tag = sc_addtag(forcetag);
539      }
540    while (nextop(&opidx, opstr));	/* do */
541    return FALSE;		/* result of expression is not an lvalue */
542 }
543 
544 /*  plnge_rel
545  *
546  *  Binary plunge to lower level; this is very simular to plnge, but
547  *  it has special code generation sequences for chained operations.
548  */
549 static int
plnge_rel(int * opstr,int opoff,int (* hier)(value * lval),value * lval)550 plnge_rel(int *opstr, int opoff, int (*hier) (value * lval), value * lval)
551 {
552    int                 lvalue, opidx;
553    value               lval2 = { NULL, 0, 0, 0, 0, NULL };
554    int                 count;
555 
556    /* this function should only be called for relational operators */
557    assert(op1[opoff] == os_le);
558    lvalue = plnge1(hier, lval);
559    if (nextop(&opidx, opstr) == 0)
560       return lvalue;		/* no operator in "opstr" found */
561    if (lvalue)
562       rvalue(lval);
563    count = 0;
564    lval->boolresult = TRUE;
565    do
566      {
567 	/* same check as in plnge(), but "chkbitwise" is always TRUE */
568 	if (count > 0 && bitwise_opercount != 0)
569 	   error(212);
570 	if (count > 0)
571 	  {
572 	     relop_prefix();
573 	     *lval = lval2;	/* copy right hand expression of the previous iteration */
574 	  }			/* if */
575 	opidx += opoff;
576 	plnge2(op1[opidx], hier, lval, &lval2);
577 	if (count++ > 0)
578 	   relop_suffix();
579      }
580    while (nextop(&opidx, opstr));	/* enddo */
581    lval->constval = lval->boolresult;
582    lval->tag = sc_addtag("bool");	/* force tag to be "bool" */
583    return FALSE;		/* result of expression is not an lvalue */
584 }
585 
586 /*  plnge1
587  *
588  *  Unary plunge to lower level
589  *  Called by: skim(), plnge(), plnge2(), plnge_rel(), hier14() and hier13()
590  */
591 static int
plnge1(int (* hier)(value * lval),value * lval)592 plnge1(int          (*hier) (value * lval), value * lval)
593 {
594    int                 lvalue, idx;
595    cell                cidx;
596 
597    stgget(&idx, &cidx);	/* mark position in code generator */
598    lvalue = (*hier) (lval);
599    if (lval->ident == iCONSTEXPR)
600       stgdel(idx, cidx);	/* load constant later */
601    return lvalue;
602 }
603 
604 /*  plnge2
605  *
606  *  Binary plunge to lower level
607  *  Called by: plnge(), plnge_rel(), hier14() and hier1()
608  */
609 static void
plnge2(void (* oper)(void),int (* hier)(value * lval),value * lval1,value * lval2)610 plnge2(void         (*oper) (void),
611        int (*hier) (value * lval), value * lval1, value * lval2)
612 {
613    int                 idx;
614    cell                cidx;
615 
616    stgget(&idx, &cidx);	/* mark position in code generator */
617    if (lval1->ident == iCONSTEXPR)
618      {				/* constant on left side; it is not yet loaded */
619 	if (plnge1(hier, lval2))
620 	   rvalue(lval2);	/* load lvalue now */
621 	else if (lval2->ident == iCONSTEXPR)
622 	   const1(lval2->constval << dbltest(oper, lval2, lval1));
623 	const2(lval1->constval << dbltest(oper, lval2, lval1));
624 	/* ^ doubling of constants operating on integer addresses */
625 	/*   is restricted to "add" and "subtract" operators */
626      }
627    else
628      {				/* non-constant on left side */
629 	push1();
630 	if (plnge1(hier, lval2))
631 	   rvalue(lval2);
632 	if (lval2->ident == iCONSTEXPR)
633 	  {			/* constant on right side */
634 	     if (commutative(oper))
635 	       {		/* test for commutative operators */
636 		  value               lvaltmp = { NULL, 0, 0, 0, 0, NULL };
637 		  stgdel(idx, cidx);	/* scratch push1() and constant fetch (then
638 					 * fetch the constant again */
639 		  const2(lval2->constval << dbltest(oper, lval1, lval2));
640 		  /* now, the primary register has the left operand and the secondary
641 		   * register the right operand; swap the "lval" variables so that lval1
642 		   * is associated with the secondary register and lval2 with the
643 		   * primary register, as is the "normal" case.
644 		   */
645 		  lvaltmp = *lval1;
646 		  *lval1 = *lval2;
647 		  *lval2 = lvaltmp;
648 	       }
649 	     else
650 	       {
651 		  const1(lval2->constval << dbltest(oper, lval1, lval2));
652 		  pop2();	/* pop result of left operand into secondary register */
653 	       }		/* if */
654 	  }
655 	else
656 	  {			/* non-constants on both sides */
657 	     pop2();
658 	     if (dbltest(oper, lval1, lval2))
659 		cell2addr();	/* double primary register */
660 	     if (dbltest(oper, lval2, lval1))
661 		cell2addr_alt();	/* double secondary register */
662 	  }			/* if */
663      }				/* if */
664    if (oper)
665      {
666 	/* If used in an expression, a function should return a value.
667 	 * If the function has been defined, we can check this. If the
668 	 * function was not defined, we can set this requirement (so that
669 	 * a future function definition can check this bit.
670 	 */
671 	checkfunction(lval1);
672 	checkfunction(lval2);
673 	if (lval1->ident == iARRAY || lval1->ident == iREFARRAY)
674 	  {
675 	     char               *ptr =
676 		(lval1->sym) ? lval1->sym->name : "-unknown-";
677 	     error(33, ptr);	/* array must be indexed */
678 	  }
679 	else if (lval2->ident == iARRAY || lval2->ident == iREFARRAY)
680 	  {
681 	     char               *ptr =
682 		(lval2->sym) ? lval2->sym->name : "-unknown-";
683 	     error(33, ptr);	/* array must be indexed */
684 	  }			/* if */
685 	/* ??? ^^^ should do same kind of error checking with functions */
686 
687 	/* check whether an "operator" function is defined for the tag names
688 	 * (a constant expression cannot be optimized in that case)
689 	 */
690 	if (check_userop(oper, lval1->tag, lval2->tag, 2, NULL, &lval1->tag))
691 	  {
692 	     lval1->ident = iEXPRESSION;
693 	     lval1->constval = 0;
694 	  }
695 	else if (lval1->ident == iCONSTEXPR && lval2->ident == iCONSTEXPR)
696 	  {
697 	     /* only constant expression if both constant */
698 	     stgdel(idx, cidx);	/* scratch generated code and calculate */
699 	     if (!matchtag(lval1->tag, lval2->tag, FALSE))
700 		error(213);	/* tagname mismatch */
701 	     lval1->constval =
702 		calc(lval1->constval, oper, lval2->constval,
703 		     &lval1->boolresult);
704 	  }
705 	else
706 	  {
707 	     if (!matchtag(lval1->tag, lval2->tag, FALSE))
708 		error(213);	/* tagname mismatch */
709 	     (*oper) ();	/* do the (signed) operation */
710 	     lval1->ident = iEXPRESSION;
711 	  }			/* if */
712      }				/* if */
713 }
714 
715 static cell
truemodulus(cell a,cell b)716 truemodulus(cell a, cell b)
717 {
718    return (a % b + b) % b;
719 }
720 
721 static cell
calc(cell left,void (* oper)(),cell right,char * boolresult)722 calc(cell left, void (*oper) (), cell right, char *boolresult)
723 {
724    if (oper == ob_or)
725       return (left | right);
726    else if (oper == ob_xor)
727       return (left ^ right);
728    else if (oper == ob_and)
729       return (left & right);
730    else if (oper == ob_eq)
731       return (left == right);
732    else if (oper == ob_ne)
733       return (left != right);
734    else if (oper == os_le)
735       return *boolresult &= (char)(left <= right), right;
736    else if (oper == os_ge)
737       return *boolresult &= (char)(left >= right), right;
738    else if (oper == os_lt)
739       return *boolresult &= (char)(left < right), right;
740    else if (oper == os_gt)
741       return *boolresult &= (char)(left > right), right;
742    else if (oper == os_sar)
743       return (left >> (int)right);
744    else if (oper == ou_sar)
745       return ((ucell) left >> (ucell) right);
746    else if (oper == ob_sal)
747       return ((ucell) left << (int)right);
748    else if (oper == ob_add)
749       return (left + right);
750    else if (oper == ob_sub)
751       return (left - right);
752    else if (oper == os_mult)
753       return (left * right);
754    else if (oper == os_div)
755       return (left - truemodulus(left, right)) / right;
756    else if (oper == os_mod)
757       return truemodulus(left, right);
758    else
759       error(29);		/* invalid expression, assumed 0 (this should never occur) */
760    return 0;
761 }
762 
763 int
expression(int * is_constant,cell * val,int * tag,int chkfuncresult)764 expression(int *is_constant, cell * val, int *tag, int chkfuncresult)
765 {
766    value               lval = { NULL, 0, 0, 0, 0, NULL };
767 
768    if (hier14(&lval))
769       rvalue(&lval);
770    if (lval.ident == iCONSTEXPR)
771      {				/* constant expression */
772 	*is_constant = TRUE;
773 	*val = lval.constval;
774      }
775    else
776      {
777 	*is_constant = FALSE;
778 	*val = 0;
779      }				/* if */
780    if (tag)
781       *tag = lval.tag;
782    if (chkfuncresult)
783       checkfunction(&lval);
784    return lval.ident;
785 }
786 
787 static cell
array_totalsize(symbol * sym)788 array_totalsize(symbol * sym)
789 {
790    cell                length;
791 
792    assert(sym != NULL);
793    assert(sym->ident == iARRAY || sym->ident == iREFARRAY);
794    length = sym->dim.array.length;
795    if (sym->dim.array.level > 0)
796      {
797 	cell                sublength = array_totalsize(finddepend(sym));
798 
799 	if (sublength > 0)
800 	   length = length + length * sublength;
801 	else
802 	   length = 0;
803      }				/* if */
804    return length;
805 }
806 
807 static cell
array_levelsize(symbol * sym,int level)808 array_levelsize(symbol * sym, int level)
809 {
810    assert(sym != NULL);
811    assert(sym->ident == iARRAY || sym->ident == iREFARRAY);
812    assert(level <= sym->dim.array.level);
813    while (level-- > 0)
814      {
815 	sym = finddepend(sym);
816 	assert(sym != NULL);
817      }				/* if */
818    return sym->dim.array.length;
819 }
820 
821 /*  hier14
822  *
823  *  Lowest hierarchy level (except for the , operator).
824  *
825  *  Global references: intest   (referred to only)
826  */
827 int
hier14(value * lval1)828 hier14(value * lval1)
829 {
830    int                 lvalue;
831    value               lval2 = { NULL, 0, 0, 0, 0, NULL };
832    value               lval3 = { NULL, 0, 0, 0, 0, NULL };
833    void                (*oper) (void);
834    int                 tok, level, i;
835    cell                val;
836    char               *st;
837    int                 bwcount;
838    cell                arrayidx1[sDIMEN_MAX], arrayidx2[sDIMEN_MAX];	/* last used array indices */
839    cell               *org_arrayidx;
840 
841    bwcount = bitwise_opercount;
842    bitwise_opercount = 0;
843    for (i = 0; i < sDIMEN_MAX; i++)
844       arrayidx1[i] = arrayidx2[i] = 0;
845    org_arrayidx = lval1->arrayidx;	/* save current pointer, to reset later */
846    if (!lval1->arrayidx)
847       lval1->arrayidx = arrayidx1;
848    lvalue = plnge1(hier13, lval1);
849    if (lval1->ident != iARRAYCELL && lval1->ident != iARRAYCHAR)
850       lval1->arrayidx = NULL;
851    if (lval1->ident == iCONSTEXPR)	/* load constant here */
852       const1(lval1->constval);
853    tok = lex(&val, &st);
854    switch (tok)
855      {
856      case taOR:
857 	oper = ob_or;
858 	break;
859      case taXOR:
860 	oper = ob_xor;
861 	break;
862      case taAND:
863 	oper = ob_and;
864 	break;
865      case taADD:
866 	oper = ob_add;
867 	break;
868      case taSUB:
869 	oper = ob_sub;
870 	break;
871      case taMULT:
872 	oper = os_mult;
873 	break;
874      case taDIV:
875 	oper = os_div;
876 	break;
877      case taMOD:
878 	oper = os_mod;
879 	break;
880      case taSHRU:
881 	oper = ou_sar;
882 	break;
883      case taSHR:
884 	oper = os_sar;
885 	break;
886      case taSHL:
887 	oper = ob_sal;
888 	break;
889      case '=':			/* simple assignment */
890 	oper = NULL;
891 	if (intest)
892 	   error(211);		/* possibly unintended assignment */
893 	break;
894      default:
895 	lexpush();
896 	bitwise_opercount = bwcount;
897 	lval1->arrayidx = org_arrayidx;	/* restore array index pointer */
898 	return lvalue;
899      }				/* switch */
900 
901    /* if we get here, it was an assignment; first check a few special cases
902     * and then the general */
903    if (lval1->ident == iARRAYCHAR)
904      {
905 	/* special case, assignment to packed character in a cell is permitted */
906 	lvalue = TRUE;
907      }
908    else if (lval1->ident == iARRAY || lval1->ident == iREFARRAY)
909      {
910 	/* array assignment is permitted too (with restrictions) */
911 	if (oper)
912 	   return error(23);	/* array assignment must be simple assigment */
913 	assert(lval1->sym != NULL);
914 	if (array_totalsize(lval1->sym) == 0)
915 	   return error(46, lval1->sym->name);	/* unknown array size */
916 	lvalue = TRUE;
917      }				/* if */
918 
919    /* operand on left side of assignment must be lvalue */
920    if (!lvalue)
921       return error(22);		/* must be lvalue */
922    /* may not change "constant" parameters */
923    assert(lval1->sym != NULL);
924    if ((lval1->sym->usage & uCONST) != 0)
925       return error(22);		/* assignment to const argument */
926    lval3 = *lval1;		/* save symbol to enable storage of expresion result */
927    lval1->arrayidx = org_arrayidx;	/* restore array index pointer */
928    if (lval1->ident == iARRAYCELL || lval1->ident == iARRAYCHAR
929        || lval1->ident == iARRAY || lval1->ident == iREFARRAY)
930      {
931 	/* if indirect fetch: save PRI (cell address) */
932 	if (oper)
933 	  {
934 	     push1();
935 	     rvalue(lval1);
936 	  }			/* if */
937 	lval2.arrayidx = arrayidx2;
938 	plnge2(oper, hier14, lval1, &lval2);
939 	if (lval2.ident != iARRAYCELL && lval2.ident != iARRAYCHAR)
940 	   lval2.arrayidx = NULL;
941 	if (oper)
942 	   pop2();
943 	if (!oper && lval3.arrayidx && lval2.arrayidx
944 	    && lval3.ident == lval2.ident && lval3.sym == lval2.sym)
945 	  {
946 	     int                 same = TRUE;
947 
948 	     assert(lval3.arrayidx == arrayidx1);
949 	     assert(lval2.arrayidx == arrayidx2);
950 	     for (i = 0; i < sDIMEN_MAX; i++)
951 		same = same && (lval3.arrayidx[i] == lval2.arrayidx[i]);
952 	     if (same)
953 		error(226, lval3.sym->name);	/* self-assignment */
954 	  }			/* if */
955      }
956    else
957      {
958 	if (oper)
959 	  {
960 	     rvalue(lval1);
961 	     plnge2(oper, hier14, lval1, &lval2);
962 	  }
963 	else
964 	  {
965 	     /* if direct fetch and simple assignment: no "push"
966 	      * and "pop" needed -> call hier14() directly, */
967 	     if (hier14(&lval2))
968 		rvalue(&lval2);	/* instead of plnge2(). */
969 	     checkfunction(&lval2);
970 	     /* check whether lval2 and lval3 (old lval1) refer to the same variable */
971 	     if (lval2.ident == iVARIABLE && lval3.ident == lval2.ident
972 		 && lval3.sym == lval2.sym)
973 	       {
974 		  assert(lval3.sym != NULL);
975 		  error(226, lval3.sym->name);	/* self-assignment */
976 	       }		/* if */
977 	  }			/* if */
978      }				/* if */
979    if (lval3.ident == iARRAY || lval3.ident == iREFARRAY)
980      {
981 	/* left operand is an array, right operand should be an array variable
982 	 * of the same size and the same dimension, an array literal (of the
983 	 * same size) or a literal string.
984 	 */
985 	int                 exactmatch = TRUE;
986 
987 	if (lval2.ident != iARRAY && lval2.ident != iREFARRAY)
988 	   error(33, lval3.sym->name);	/* array must be indexed */
989 	if (lval2.sym)
990 	  {
991 	     val = lval2.sym->dim.array.length;	/* array variable */
992 	     level = lval2.sym->dim.array.level;
993 	  }
994 	else
995 	  {
996 	     val = lval2.constval;	/* literal array */
997 	     level = 0;
998 	     /* If val is negative, it means that lval2 is a
999 	      * literal string. The string array size may be
1000 	      * smaller than the destination array.
1001 	      */
1002 	     if (val < 0)
1003 	       {
1004 		  val = -val;
1005 		  exactmatch = FALSE;
1006 	       }		/* if */
1007 	  }			/* if */
1008 	if (lval3.sym->dim.array.level != level)
1009 	   return error(48);	/* array dimensions must match */
1010 	else if (lval3.sym->dim.array.length < val
1011 		 || (exactmatch && lval3.sym->dim.array.length > val))
1012 	   return error(47);	/* array sizes must match */
1013 	if (level > 0)
1014 	  {
1015 	     /* check the sizes of all sublevels too */
1016 	     symbol             *sym1 = lval3.sym;
1017 	     symbol             *sym2 = lval2.sym;
1018 	     int                 clvl;
1019 
1020 	     assert(sym1 != NULL && sym2 != NULL);
1021 	     /* ^^^ sym2 must be valid, because only variables can be
1022 	      *     multi-dimensional (there are no multi-dimensional arrays),
1023 	      *     sym1 must be valid because it must be an lvalue
1024 	      */
1025 	     assert(exactmatch);
1026 	     for (clvl = 0; clvl < level; clvl++)
1027 	       {
1028 		  sym1 = finddepend(sym1);
1029 		  sym2 = finddepend(sym2);
1030 		  assert(sym1 != NULL && sym2 != NULL);
1031 		  /* ^^^ both arrays have the same dimensions (this was checked
1032 		   *     earlier) so the dependend should always be found
1033 		   */
1034 		  if (sym1->dim.array.length != sym2->dim.array.length)
1035 		     error(47);	/* array sizes must match */
1036 	       }		/* for */
1037 	     /* get the total size in cells of the multi-dimensional array */
1038 	     val = array_totalsize(lval3.sym);
1039 	     assert(val > 0);	/* already checked */
1040 	  }			/* if */
1041      }
1042    else
1043      {
1044 	/* left operand is not an array, right operand should then not be either */
1045 	if (lval2.ident == iARRAY || lval2.ident == iREFARRAY)
1046 	   error(6);		/* must be assigned to an array */
1047      }				/* if */
1048    if (lval3.ident == iARRAY || lval3.ident == iREFARRAY)
1049      {
1050 	memcopy(val * sizeof(cell));
1051      }
1052    else
1053      {
1054 	check_userop(NULL, lval2.tag, lval3.tag, 2, &lval3, &lval2.tag);
1055 	store(&lval3);		/* now, store the expression result */
1056      }				/* if */
1057    if (!oper && !matchtag(lval3.tag, lval2.tag, TRUE))
1058       error(213);		/* tagname mismatch (if "oper", warning already given in plunge2()) */
1059    if (lval3.sym)
1060       markusage(lval3.sym, uWRITTEN);
1061    sideeffect = TRUE;
1062    bitwise_opercount = bwcount;
1063    return FALSE;		/* expression result is never an lvalue */
1064 }
1065 
1066 static int
hier13(value * lval)1067 hier13(value * lval)
1068 {
1069    int                 lvalue, flab1, flab2;
1070    value               lval2 = { NULL, 0, 0, 0, 0, NULL };
1071    int                 array1, array2;
1072 
1073    lvalue = plnge1(hier12, lval);
1074    if (matchtoken('?'))
1075      {
1076 	flab1 = getlabel();
1077 	flab2 = getlabel();
1078 	if (lvalue)
1079 	  {
1080 	     rvalue(lval);
1081 	  }
1082 	else if (lval->ident == iCONSTEXPR)
1083 	  {
1084 	     const1(lval->constval);
1085 	     error(lval->constval ? 206 : 205);	/* redundant test */
1086 	  }			/* if */
1087 	jmp_eq0(flab1);		/* go to second expression if primary register==0 */
1088 	if (hier14(lval))
1089 	   rvalue(lval);
1090 	jumplabel(flab2);
1091 	setlabel(flab1);
1092 	needtoken(':');
1093 	if (hier14(&lval2))
1094 	   rvalue(&lval2);
1095 	array1 = (lval->ident == iARRAY || lval->ident == iREFARRAY);
1096 	array2 = (lval2.ident == iARRAY || lval2.ident == iREFARRAY);
1097 	if (array1 && !array2)
1098 	  {
1099 	     char               *ptr = lval->sym->name;
1100 	     error(33, ptr);	/* array must be indexed */
1101 	  }
1102 	else if (!array1 && array2)
1103 	  {
1104 	     char               *ptr = lval2.sym->name;
1105 	     error(33, ptr);	/* array must be indexed */
1106 	  }			/* if */
1107 	/* ??? if both are arrays, should check dimensions */
1108 	if (!matchtag(lval->tag, lval2.tag, FALSE))
1109 	   error(213);		/* tagname mismatch ('true' and 'false' expressions) */
1110 	setlabel(flab2);
1111 	if (lval->ident == iARRAY)
1112 	   lval->ident = iREFARRAY;	/* iARRAY becomes iREFARRAY */
1113 	else if (lval->ident != iREFARRAY)
1114 	   lval->ident = iEXPRESSION;	/* iREFARRAY stays iREFARRAY, rest becomes iEXPRESSION */
1115 	return FALSE;		/* conditional expression is no lvalue */
1116      }
1117    else
1118      {
1119 	return lvalue;
1120      }				/* endif */
1121 }
1122 
1123 /* the order of the operators in these lists is important and must cohere */
1124 /* with the order of the operators in the array "op1" */
1125 static int          list3[] = { '*', '/', '%', 0 };
1126 static int          list4[] = { '+', '-', 0 };
1127 static int          list5[] = { tSHL, tSHR, tSHRU, 0 };
1128 static int          list6[] = { '&', 0 };
1129 static int          list7[] = { '^', 0 };
1130 static int          list8[] = { '|', 0 };
1131 static int          list9[] = { tlLE, tlGE, '<', '>', 0 };
1132 static int          list10[] = { tlEQ, tlNE, 0 };
1133 static int          list11[] = { tlAND, 0 };
1134 static int          list12[] = { tlOR, 0 };
1135 
1136 static int
hier12(value * lval)1137 hier12(value * lval)
1138 {
1139    return skim(list12, jmp_ne0, 1, 0, hier11, lval);
1140 }
1141 
1142 static int
hier11(value * lval)1143 hier11(value * lval)
1144 {
1145    return skim(list11, jmp_eq0, 0, 1, hier10, lval);
1146 }
1147 
1148 static int
hier10(value * lval)1149 hier10(value * lval)
1150 {				/* ==, != */
1151    return plnge(list10, 15, hier9, lval, "bool", TRUE);
1152 }				/* ^ this variable is the starting index in the op1[]
1153 				 *   array of the operators of this hierarchy level */
1154 
1155 static int
hier9(value * lval)1156 hier9(value * lval)
1157 {				/* <=, >=, <, > */
1158    return plnge_rel(list9, 11, hier8, lval);
1159 }
1160 
1161 static int
hier8(value * lval)1162 hier8(value * lval)
1163 {				/* | */
1164    return plnge(list8, 10, hier7, lval, NULL, FALSE);
1165 }
1166 
1167 static int
hier7(value * lval)1168 hier7(value * lval)
1169 {				/* ^ */
1170    return plnge(list7, 9, hier6, lval, NULL, FALSE);
1171 }
1172 
1173 static int
hier6(value * lval)1174 hier6(value * lval)
1175 {				/* & */
1176    return plnge(list6, 8, hier5, lval, NULL, FALSE);
1177 }
1178 
1179 static int
hier5(value * lval)1180 hier5(value * lval)
1181 {				/* <<, >>, >>> */
1182    return plnge(list5, 5, hier4, lval, NULL, FALSE);
1183 }
1184 
1185 static int
hier4(value * lval)1186 hier4(value * lval)
1187 {				/* +, - */
1188    return plnge(list4, 3, hier3, lval, NULL, FALSE);
1189 }
1190 
1191 static int
hier3(value * lval)1192 hier3(value * lval)
1193 {				/* *, /, % */
1194    return plnge(list3, 0, hier2, lval, NULL, FALSE);
1195 }
1196 
1197 static int
hier2(value * lval)1198 hier2(value * lval)
1199 {
1200    int                 lvalue, tok;
1201    int                 tag, paranthese;
1202    cell                val;
1203    char               *st;
1204    symbol             *sym;
1205    int                 saveresult;
1206 
1207    tok = lex(&val, &st);
1208    switch (tok)
1209      {
1210      case tINC:		/* ++lval */
1211 	if (!hier2(lval))
1212 	   return error(22);	/* must be lvalue */
1213 	assert(lval->sym != NULL);
1214 	if ((lval->sym->usage & uCONST) != 0)
1215 	   return error(22);	/* assignment to const argument */
1216 	if (!check_userop(user_inc, lval->tag, 0, 1, lval, &lval->tag))
1217 	   inc(lval);		/* increase variable first */
1218 	rvalue(lval);		/* and read the result into PRI */
1219 	sideeffect = TRUE;
1220 	return FALSE;		/* result is no longer lvalue */
1221      case tDEC:		/* --lval */
1222 	if (!hier2(lval))
1223 	   return error(22);	/* must be lvalue */
1224 	assert(lval->sym != NULL);
1225 	if ((lval->sym->usage & uCONST) != 0)
1226 	   return error(22);	/* assignment to const argument */
1227 	if (!check_userop(user_dec, lval->tag, 0, 1, lval, &lval->tag))
1228 	   dec(lval);		/* decrease variable first */
1229 	rvalue(lval);		/* and read the result into PRI */
1230 	sideeffect = TRUE;
1231 	return FALSE;		/* result is no longer lvalue */
1232      case '~':			/* ~ (one's complement) */
1233 	if (hier2(lval))
1234 	   rvalue(lval);
1235 	invert();		/* bitwise NOT */
1236 	lval->constval = ~lval->constval;
1237 	return FALSE;
1238      case '!':			/* ! (logical negate) */
1239 	if (hier2(lval))
1240 	   rvalue(lval);
1241 	if (check_userop(lneg, lval->tag, 0, 1, NULL, &lval->tag))
1242 	  {
1243 	     lval->ident = iEXPRESSION;
1244 	     lval->constval = 0;
1245 	  }
1246 	else
1247 	  {
1248 	     lneg();		/* 0 -> 1,  !0 -> 0 */
1249 	     lval->constval = !lval->constval;
1250 	     lval->tag = sc_addtag("bool");
1251 	  }			/* if */
1252 	return FALSE;
1253      case '-':			/* unary - (two's complement) */
1254 	if (hier2(lval))
1255 	   rvalue(lval);
1256 	/* make a special check for a constant expression with the tag of a
1257 	 * rational number, so that we can simple swap the sign of that constant.
1258 	 */
1259 	if (lval->ident == iCONSTEXPR && lval->tag == sc_rationaltag
1260 	    && sc_rationaltag != 0)
1261 	  {
1262 	     if (rational_digits == 0)
1263 	       {
1264 		  float              *f = (float *)&lval->constval;
1265 
1266 		  *f = -*f;	/* this modifies lval->constval */
1267 	       }
1268 	     else
1269 	       {
1270 		  /* the negation of a fixed point number is just an integer negation */
1271 		  lval->constval = -lval->constval;
1272 	       }		/* if */
1273 	  }
1274 	else if (check_userop(neg, lval->tag, 0, 1, NULL, &lval->tag))
1275 	  {
1276 	     lval->ident = iEXPRESSION;
1277 	     lval->constval = 0;
1278 	  }
1279 	else
1280 	  {
1281 	     neg();		/* arithmic negation */
1282 	     lval->constval = -lval->constval;
1283 	  }			/* if */
1284 	return FALSE;
1285      case tLABEL:		/* tagname override */
1286 	tag = sc_addtag(st);
1287 	lvalue = hier2(lval);
1288 	lval->tag = tag;
1289 	return lvalue;
1290      case tDEFINED:
1291 	paranthese = 0;
1292 	while (matchtoken('('))
1293 	   paranthese++;
1294 	tok = lex(&val, &st);
1295 	if (tok != tSYMBOL)
1296 	   return error(20, st);	/* illegal symbol name */
1297 	sym = findloc(st);
1298 	if (!sym)
1299 	   sym = findglb(st);
1300 	if (sym && sym->ident != iFUNCTN && sym->ident != iREFFUNC
1301 	    && (sym->usage & uDEFINE) == 0)
1302 	   sym = NULL;		/* symbol is not a function, it is in the table, but not "defined" */
1303 	val = !!sym;
1304 	if (!val && find_subst(st, strlen(st)))
1305 	   val = 1;
1306 	clear_value(lval);
1307 	lval->ident = iCONSTEXPR;
1308 	lval->constval = val;
1309 	const1(lval->constval);
1310 	while (paranthese--)
1311 	   needtoken(')');
1312 	return FALSE;
1313      case tSIZEOF:
1314 	paranthese = 0;
1315 	while (matchtoken('('))
1316 	   paranthese++;
1317 	tok = lex(&val, &st);
1318 	if (tok != tSYMBOL)
1319 	   return error(20, st);	/* illegal symbol name */
1320 	sym = findloc(st);
1321 	if (!sym)
1322 	   sym = findglb(st);
1323 	if (!sym)
1324 	   return error(17, st);	/* undefined symbol */
1325 	if (sym->ident == iCONSTEXPR)
1326 	   error(39);		/* constant symbol has no size */
1327 	else if (sym->ident == iFUNCTN || sym->ident == iREFFUNC)
1328 	   error(72);		/* "function" symbol has no size */
1329 	else if ((sym->usage & uDEFINE) == 0)
1330 	   return error(17, st);	/* undefined symbol (symbol is in the table, but it is "used" only) */
1331 	clear_value(lval);
1332 	lval->ident = iCONSTEXPR;
1333 	lval->constval = 1;	/* preset */
1334 	if (sym->ident == iARRAY || sym->ident == iREFARRAY)
1335 	  {
1336 	     int                 level;
1337 
1338 	     for (level = 0; matchtoken('['); level++)
1339 		needtoken(']');
1340 	     if (level > sym->dim.array.level)
1341 		error(28);	/* invalid subscript */
1342 	     else
1343 		lval->constval = array_levelsize(sym, level);
1344 	     if (lval->constval == 0 && !strchr(lptr, PREPROC_TERM))
1345 		error(224, st);	/* indeterminate array size in "sizeof" expression */
1346 	  }			/* if */
1347 	const1(lval->constval);
1348 	while (paranthese--)
1349 	   needtoken(')');
1350 	return FALSE;
1351      case tTAGOF:
1352 	paranthese = 0;
1353 	while (matchtoken('('))
1354 	   paranthese++;
1355 	tok = lex(&val, &st);
1356 	if (tok != tSYMBOL && tok != tLABEL)
1357 	   return error(20, st);	/* illegal symbol name */
1358 	if (tok == tLABEL)
1359 	  {
1360 	     tag = sc_addtag(st);
1361 	  }
1362 	else
1363 	  {
1364 	     sym = findloc(st);
1365 	     if (!sym)
1366 		sym = findglb(st);
1367 	     if (!sym)
1368 		return error(17, st);	/* undefined symbol */
1369 	     if ((sym->usage & uDEFINE) == 0)
1370 		return error(17, st);	/* undefined symbol (symbol is in the table, but it is "used" only) */
1371 	     tag = sym->tag;
1372 	  }			/* if */
1373 	exporttag(tag);
1374 	clear_value(lval);
1375 	lval->ident = iCONSTEXPR;
1376 	lval->constval = tag;
1377 	const1(lval->constval);
1378 	while (paranthese--)
1379 	   needtoken(')');
1380 	return FALSE;
1381      default:
1382 	lexpush();
1383 	lvalue = hier1(lval);
1384 	/* check for postfix operators */
1385 	if (matchtoken(';'))
1386 	  {
1387 	     /* Found a ';', do not look further for postfix operators */
1388 	     lexpush();		/* push ';' back after successful match */
1389 	     return lvalue;
1390 	  }
1391 	else if (matchtoken(tTERM))
1392 	  {
1393 	     /* Found a newline that ends a statement (this is the case when
1394 	      * semicolons are optional). Note that an explicit semicolon was
1395 	      * handled above. This case is similar, except that the token must
1396 	      * not be pushed back.
1397 	      */
1398 	     return lvalue;
1399 	  }
1400 	else
1401 	  {
1402 	     tok = lex(&val, &st);
1403 	     switch (tok)
1404 	       {
1405 	       case tINC:	/* lval++ */
1406 		  if (!lvalue)
1407 		     return error(22);	/* must be lvalue */
1408 		  assert(lval->sym != NULL);
1409 		  if ((lval->sym->usage & uCONST) != 0)
1410 		     return error(22);	/* assignment to const argument */
1411 		  /* on incrementing array cells, the address in PRI must be saved for
1412 		   * incremening the value, whereas the current value must be in PRI
1413 		   * on exit.
1414 		   */
1415 		  saveresult = (lval->ident == iARRAYCELL
1416 				|| lval->ident == iARRAYCHAR);
1417 		  if (saveresult)
1418 		     push1();	/* save address in PRI */
1419 		  rvalue(lval);	/* read current value into PRI */
1420 		  if (saveresult)
1421 		     swap1();	/* save PRI on the stack, restore address in PRI */
1422 		  if (!check_userop
1423 		      (user_inc, lval->tag, 0, 1, lval, &lval->tag))
1424 		     inc(lval);	/* increase variable afterwards */
1425 		  if (saveresult)
1426 		     pop1();	/* restore PRI (result of rvalue()) */
1427 		  sideeffect = TRUE;
1428 		  return FALSE;	/* result is no longer lvalue */
1429 	       case tDEC:	/* lval-- */
1430 		  if (!lvalue)
1431 		     return error(22);	/* must be lvalue */
1432 		  assert(lval->sym != NULL);
1433 		  if ((lval->sym->usage & uCONST) != 0)
1434 		     return error(22);	/* assignment to const argument */
1435 		  saveresult = (lval->ident == iARRAYCELL
1436 				|| lval->ident == iARRAYCHAR);
1437 		  if (saveresult)
1438 		     push1();	/* save address in PRI */
1439 		  rvalue(lval);	/* read current value into PRI */
1440 		  if (saveresult)
1441 		     swap1();	/* save PRI on the stack, restore address in PRI */
1442 		  if (!check_userop
1443 		      (user_dec, lval->tag, 0, 1, lval, &lval->tag))
1444 		     dec(lval);	/* decrease variable afterwards */
1445 		  if (saveresult)
1446 		     pop1();	/* restore PRI (result of rvalue()) */
1447 		  sideeffect = TRUE;
1448 		  return FALSE;
1449 	       case tCHAR:	/* char (compute required # of cells */
1450 		  if (lval->ident == iCONSTEXPR)
1451 		    {
1452 		       lval->constval *= charbits / 8;	/* from char to bytes */
1453 		       lval->constval =
1454 			  (lval->constval + sizeof(cell) - 1) / sizeof(cell);
1455 		    }
1456 		  else
1457 		    {
1458 		       if (lvalue)
1459 			  rvalue(lval);	/* fetch value if not already in PRI */
1460 		       char2addr();	/* from characters to bytes */
1461 		       addconst(sizeof(cell) - 1);	/* make sure the value is rounded up */
1462 		       addr2cell();	/* truncate to number of cells */
1463 		    }		/* if */
1464 		  return FALSE;
1465 	       default:
1466 		  lexpush();
1467 		  return lvalue;
1468 	       }		/* switch */
1469 	  }			/* if */
1470      }				/* switch */
1471 }
1472 
1473 /*  hier1
1474  *
1475  *  The highest hierarchy level: it looks for pointer and array indices
1476  *  and function calls.
1477  *  Generates code to fetch a pointer value if it is indexed and code to
1478  *  add to the pointer value or the array address (the address is already
1479  *  read at primary()). It also generates code to fetch a function address
1480  *  if that hasn't already been done at primary() (check lval[4]) and calls
1481  *  callfunction() to call the function.
1482  */
1483 static int
hier1(value * lval1)1484 hier1(value * lval1)
1485 {
1486    int                 lvalue, idx, tok, symtok;
1487    cell                val, cidx;
1488    value               lval2 = { NULL, 0, 0, 0, 0, NULL };
1489    char               *st;
1490    char                close;
1491    symbol             *sym;
1492 
1493    lvalue = primary(lval1);
1494    symtok = tokeninfo(&val, &st);	/* get token read by primary() */
1495  restart:
1496    sym = lval1->sym;
1497    if (matchtoken('[') || matchtoken('{') || matchtoken('('))
1498      {
1499 	tok = tokeninfo(&val, &st);	/* get token read by matchtoken() */
1500 	if (!sym && symtok != tSYMBOL)
1501 	  {
1502 	     /* we do not have a valid symbol and we appear not to have read a valid
1503 	      * symbol name (so it is unlikely that we would have read a name of an
1504 	      * undefined symbol) */
1505 	     error(29);		/* expression error, assumed 0 */
1506 	     lexpush();		/* analyse '(', '{' or '[' again later */
1507 	     return FALSE;
1508 	  }			/* if */
1509 	if (tok == '[' || tok == '{')
1510 	  {			/* subscript */
1511 	     close = (char)((tok == '[') ? ']' : '}');
1512 	     if (!sym)
1513 	       {		/* sym==NULL if lval is a constant or a literal */
1514 		  error(28);	/* cannot subscript */
1515 		  needtoken(close);
1516 		  return FALSE;
1517 	       }
1518 	     else if (sym->ident != iARRAY && sym->ident != iREFARRAY)
1519 	       {
1520 		  error(28);	/* cannot subscript, variable is not an array */
1521 		  needtoken(close);
1522 		  return FALSE;
1523 	       }
1524 	     else if (sym->dim.array.level > 0 && close != ']')
1525 	       {
1526 		  error(51);	/* invalid subscript, must use [ ] */
1527 		  needtoken(close);
1528 		  return FALSE;
1529 	       }		/* if */
1530 	     stgget(&idx, &cidx);	/* mark position in code generator */
1531 	     push1();		/* save base address of the array */
1532 	     if (hier14(&lval2))	/* create expression for the array index */
1533 		rvalue(&lval2);
1534 	     if (lval2.ident == iARRAY || lval2.ident == iREFARRAY)
1535 		error(33, lval2.sym->name);	/* array must be indexed */
1536 	     needtoken(close);
1537 	     if (!matchtag(sym->x.idxtag, lval2.tag, TRUE))
1538 		error(213);
1539 	     if (lval2.ident == iCONSTEXPR)
1540 	       {		/* constant expression */
1541 		  stgdel(idx, cidx);	/* scratch generated code */
1542 		  if (lval1->arrayidx)
1543 		    {		/* keep constant index, for checking */
1544 		       assert(sym->dim.array.level >= 0
1545 			      && sym->dim.array.level < sDIMEN_MAX);
1546 		       lval1->arrayidx[sym->dim.array.level] = lval2.constval;
1547 		    }		/* if */
1548 		  if (close == ']')
1549 		    {
1550 		       /* normal array index */
1551 		       if (lval2.constval < 0 || (sym->dim.array.length != 0
1552 			   && sym->dim.array.length <= lval2.constval))
1553 			  error(32, sym->name);	/* array index out of bounds */
1554 		       if (lval2.constval != 0)
1555 			 {
1556 			    /* don't add offsets for zero subscripts */
1557 #if defined(BIT16)
1558 			    const2(lval2.constval << 1);
1559 #else
1560 			    const2(lval2.constval << 2);
1561 #endif
1562 			    ob_add();
1563 			 }	/* if */
1564 		    }
1565 		  else
1566 		    {
1567 		       /* character index */
1568 		       if (lval2.constval < 0 || (sym->dim.array.length != 0
1569 			   && sym->dim.array.length * ((8 * sizeof(cell)) /
1570 						       charbits) <=
1571 			   (ucell) lval2.constval))
1572 			  error(32, sym->name);	/* array index out of bounds */
1573 		       if (lval2.constval != 0)
1574 			 {
1575 			    /* don't add offsets for zero subscripts */
1576 			    if (charbits == 16)
1577 			       const2(lval2.constval << 1);	/* 16-bit character */
1578 			    else
1579 			       const2(lval2.constval);	/* 8-bit character */
1580 			    ob_add();
1581 			 }	/* if */
1582 		       charalign();	/* align character index into array */
1583 		    }		/* if */
1584 	       }
1585 	     else
1586 	       {
1587 		  /* array index is not constant */
1588 		  lval1->arrayidx = NULL;	/* reset, so won't be checked */
1589 		  if (close == ']')
1590 		    {
1591 		       if (sym->dim.array.length != 0)
1592 			  ffbounds(sym->dim.array.length - 1);	/* run time check for array bounds */
1593 		       cell2addr();	/* normal array index */
1594 		    }
1595 		  else
1596 		    {
1597 		       if (sym->dim.array.length != 0)
1598 			  ffbounds(sym->dim.array.length * (32 / charbits) - 1);
1599 		       char2addr();	/* character array index */
1600 		    }		/* if */
1601 		  pop2();
1602 		  ob_add();	/* base address was popped into secondary register */
1603 		  if (close != ']')
1604 		     charalign();	/* align character index into array */
1605 	       }		/* if */
1606 	     /* the indexed item may be another array (multi-dimensional arrays) */
1607 	     assert(lval1->sym == sym && sym != NULL);	/* should still be set */
1608 	     if (sym->dim.array.level > 0)
1609 	       {
1610 		  assert(close == ']');	/* checked earlier */
1611 		  /* read the offset to the subarray and add it to the current address */
1612 		  lval1->ident = iARRAYCELL;
1613 		  push1();	/* the optimizer makes this to a MOVE.alt */
1614 		  rvalue(lval1);
1615 		  pop2();
1616 		  ob_add();
1617 		  /* adjust the "value" structure and find the referenced array */
1618 		  lval1->ident = iREFARRAY;
1619 		  lval1->sym = finddepend(sym);
1620 		  assert(lval1->sym != NULL);
1621 		  assert(lval1->sym->dim.array.level ==
1622 			 sym->dim.array.level - 1);
1623 		  /* try to parse subsequent array indices */
1624 		  lvalue = FALSE;	/* for now, a iREFARRAY is no lvalue */
1625 		  goto restart;
1626 	       }		/* if */
1627 	     assert(sym->dim.array.level == 0);
1628 	     /* set type to fetch... INDIRECTLY */
1629 	     lval1->ident = (char)((close == ']') ? iARRAYCELL : iARRAYCHAR);
1630 	     lval1->tag = sym->tag;
1631 	     /* a cell in an array is an lvalue, a character in an array is not
1632 	      * always a *valid* lvalue */
1633 	     return TRUE;
1634 	  }
1635 	else
1636 	  {			/* tok=='(' -> function(...) */
1637 	     if (!sym
1638 		 || (sym->ident != iFUNCTN && sym->ident != iREFFUNC))
1639 	       {
1640 		  if (!sym && sc_status == statFIRST)
1641 		    {
1642 		       /* could be a "use before declaration"; in that case, create a stub
1643 		        * function so that the usage can be marked.
1644 		        */
1645 		       sym = fetchfunc(lastsymbol, 0);
1646 		       if (sym)
1647 			  markusage(sym, uREAD);
1648 		    }		/* if */
1649 		  return error(12);	/* invalid function call */
1650 	       }
1651 	     else if ((sym->usage & uMISSING) != 0)
1652 	       {
1653 		  char                symname[2 * sNAMEMAX + 16];	/* allow space for user defined operators */
1654 
1655 		  funcdisplayname(symname, sym->name);
1656 		  error(4, symname);	/* function not defined */
1657 	       }		/* if */
1658 	     callfunction(sym);
1659 	     lval1->ident = iEXPRESSION;
1660 	     lval1->constval = 0;
1661 	     lval1->tag = sym->tag;
1662 	     return FALSE;	/* result of function call is no lvalue */
1663 	  }			/* if */
1664      }				/* if */
1665    if (sym && lval1->ident == iFUNCTN)
1666      {
1667 	assert(sym->ident == iFUNCTN);
1668 	address(sym);
1669 	lval1->sym = NULL;
1670 	lval1->ident = iREFFUNC;
1671 	/* ??? however... function pointers (or function references are not (yet) allowed */
1672 	error(29);		/* expression error, assumed 0 */
1673 	return FALSE;
1674      }				/* if */
1675    return lvalue;
1676 }
1677 
1678 /*  primary
1679  *
1680  *  Returns 1 if the operand is an lvalue (everything except arrays, functions
1681  *  constants and -of course- errors).
1682  *  Generates code to fetch the address of arrays. Code for constants is
1683  *  already generated by constant().
1684  *  This routine first clears the entire lval array (all fields are set to 0).
1685  *
1686  *  Global references: intest  (may be altered, but restored upon termination)
1687  */
1688 static int
primary(value * lval)1689 primary(value * lval)
1690 {
1691    char               *st;
1692    int                 lvalue, tok;
1693    cell                val;
1694    symbol             *sym;
1695 
1696    if (matchtoken('('))
1697      {				/* sub-expression - (expression,...) */
1698 	pushstk((stkitem) intest);
1699 	pushstk((stkitem) sc_allowtags);
1700 
1701 	intest = 0;		/* no longer in "test" expression */
1702 	sc_allowtags = TRUE;	/* allow tagnames to be used in parenthised expressions */
1703 	do
1704 	   lvalue = hier14(lval);
1705 	while (matchtoken(','));
1706 	needtoken(')');
1707 	lexclr(FALSE);		/* clear lex() push-back, it should have been
1708 				 * cleared already by needtoken() */
1709 	sc_allowtags = (int)(long)popstk();
1710 	intest = (int)(long)popstk();
1711 	return lvalue;
1712      }				/* if */
1713 
1714    clear_value(lval);		/* clear lval */
1715    tok = lex(&val, &st);
1716    if (tok == tSYMBOL)
1717      {
1718 	/* lastsymbol is char[sNAMEMAX+1], lex() should have truncated any symbol
1719 	 * to sNAMEMAX significant characters */
1720 	assert(strlen(st) < sizeof lastsymbol);
1721 	strcpy(lastsymbol, st);
1722      }				/* if */
1723    if (tok == tSYMBOL && !findconst(st))
1724      {
1725 	/* first look for a local variable */
1726 	if ((sym = findloc(st)))
1727 	  {
1728 	     if (sym->ident == iLABEL)
1729 	       {
1730 		  error(29);	/* expression error, assumed 0 */
1731 		  const1(0);	/* load 0 */
1732 		  return FALSE;	/* return 0 for labels (expression error) */
1733 	       }		/* if */
1734 	     lval->sym = sym;
1735 	     lval->ident = sym->ident;
1736 	     lval->tag = sym->tag;
1737 	     if (sym->ident == iARRAY || sym->ident == iREFARRAY)
1738 	       {
1739 		  address(sym);	/* get starting address in primary register */
1740 		  return FALSE;	/* return 0 for array (not lvalue) */
1741 	       }
1742 	     else
1743 	       {
1744 		  return TRUE;	/* return 1 if lvalue (not label or array) */
1745 	       }		/* if */
1746 	  }			/* if */
1747 	/* now try a global variable */
1748 	if ((sym = findglb(st)))
1749 	  {
1750 	     if (sym->ident == iFUNCTN || sym->ident == iREFFUNC)
1751 	       {
1752 		  /* if the function is only in the table because it was inserted as a
1753 		   * stub in the first pass (i.e. it was "used" but never declared or
1754 		   * implemented, issue an error
1755 		   */
1756 		  if ((sym->usage & uPROTOTYPED) == 0)
1757 		     error(17, st);
1758 	       }
1759 	     else
1760 	       {
1761 		  if ((sym->usage & uDEFINE) == 0)
1762 		     error(17, st);
1763 		  lval->sym = sym;
1764 		  lval->ident = sym->ident;
1765 		  lval->tag = sym->tag;
1766 		  if (sym->ident == iARRAY || sym->ident == iREFARRAY)
1767 		    {
1768 		       address(sym);	/* get starting address in primary register */
1769 		       return FALSE;	/* return 0 for array (not lvalue) */
1770 		    }
1771 		  else
1772 		    {
1773 		       return TRUE;	/* return 1 if lvalue (not function or array) */
1774 		    }		/* if */
1775 	       }		/* if */
1776 	  }
1777 	else
1778 	  {
1779 	     return error(17, st);	/* undefined symbol */
1780 	  }			/* endif */
1781 	assert(sym != NULL);
1782 	assert(sym->ident == iFUNCTN || sym->ident != iREFFUNC);
1783 	lval->sym = sym;
1784 	lval->ident = sym->ident;
1785 	lval->tag = sym->tag;
1786 	return FALSE;		/* return 0 for function (not an lvalue) */
1787      }				/* if */
1788    lexpush();			/* push the token, it is analyzed by constant() */
1789    if (constant(lval) == 0)
1790      {
1791 	error(29);		/* expression error, assumed 0 */
1792 	const1(0);		/* load 0 */
1793      }				/* if */
1794    return FALSE;		/* return 0 for constants (or errors) */
1795 }
1796 
1797 static void
clear_value(value * lval)1798 clear_value(value * lval)
1799 {
1800    lval->sym = NULL;
1801    lval->constval = 0L;
1802    lval->tag = 0;
1803    lval->ident = 0;
1804    lval->boolresult = FALSE;
1805    /* do not clear lval->arrayidx, it is preset in hier14() */
1806 }
1807 
1808 static void
setdefarray(cell * string,cell size,cell array_sz,cell * dataaddr,int fconst)1809 setdefarray(cell * string, cell size, cell array_sz, cell * dataaddr,
1810 	    int fconst)
1811 {
1812    /* The routine must copy the default array data onto the heap, as to avoid
1813     * that a function can change the default value. An optimization is that
1814     * the default array data is "dumped" into the data segment only once (on the
1815     * first use).
1816     */
1817    assert(string != NULL);
1818    assert(size > 0);
1819    /* check whether to dump the default array */
1820    assert(dataaddr != NULL);
1821    if (sc_status == statWRITE && *dataaddr < 0)
1822      {
1823 	int                 i;
1824 
1825 	*dataaddr = (litidx + glb_declared) * sizeof(cell);
1826 	for (i = 0; i < size; i++)
1827 	   stowlit(*string++);
1828      }				/* if */
1829 
1830    /* if the function is known not to modify the array (meaning that it also
1831     * does not modify the default value), directly pass the address of the
1832     * array in the data segment.
1833     */
1834    if (fconst)
1835      {
1836 	const1(*dataaddr);
1837      }
1838    else
1839      {
1840 	/* Generate the code:
1841 	 *  CONST.pri dataaddr                ;address of the default array data
1842 	 *  HEAP      array_sz*sizeof(cell)   ;heap address in ALT
1843 	 *  MOVS      size*sizeof(cell)       ;copy data from PRI to ALT
1844 	 *  MOVE.PRI                          ;PRI = address on the heap
1845 	 */
1846 	const1(*dataaddr);
1847 	/* "array_sz" is the size of the argument (the value between the brackets
1848 	 * in the declaration), "size" is the size of the default array data.
1849 	 */
1850 	assert(array_sz >= size);
1851 	modheap((int)array_sz * sizeof(cell));
1852 	/* ??? should perhaps fill with zeros first */
1853 	memcopy(size * sizeof(cell));
1854 	moveto1();
1855      }				/* if */
1856 }
1857 
1858 static int
findnamedarg(arginfo * arg,char * name)1859 findnamedarg(arginfo * arg, char *name)
1860 {
1861    int                 i;
1862 
1863    for (i = 0; arg[i].ident != 0 && arg[i].ident != iVARARGS; i++)
1864       if (strcmp(arg[i].name, name) == 0)
1865 	 return i;
1866    return -1;
1867 }
1868 
1869 static int
checktag(int tags[],int numtags,int exprtag)1870 checktag(int tags[], int numtags, int exprtag)
1871 {
1872    int                 i;
1873 
1874    assert(tags != 0);
1875    assert(numtags > 0);
1876    for (i = 0; i < numtags; i++)
1877       if (matchtag(tags[i], exprtag, TRUE))
1878 	 return TRUE;		/* matching tag */
1879    return FALSE;		/* no tag matched */
1880 }
1881 
1882 enum
1883 {
1884    ARG_UNHANDLED,
1885    ARG_IGNORED,
1886    ARG_DONE,
1887 };
1888 
1889 /*  callfunction
1890  *
1891  *  Generates code to call a function. This routine handles default arguments
1892  *  and positional as well as named parameters.
1893  */
1894 static void
callfunction(symbol * sym)1895 callfunction(symbol * sym)
1896 {
1897    int                 close, lvalue;
1898    int                 argpos;	/* index in the output stream (argpos==nargs if positional parameters) */
1899    int                 argidx = 0;	/* index in "arginfo" list */
1900    int                 nargs = 0;	/* number of arguments */
1901    int                 heapalloc = 0;
1902    int                 namedparams = FALSE;
1903    value               lval = { NULL, 0, 0, 0, 0, NULL };
1904    arginfo            *arg;
1905    char                arglist[sMAXARGS];
1906    constvalue          arrayszlst = { NULL, "", 0, 0 };	/* array size list starts empty */
1907    cell                lexval;
1908    char               *lexstr;
1909 
1910    assert(sym != NULL);
1911    arg = sym->dim.arglist;
1912    assert(arg != NULL);
1913    stgmark(sSTARTREORDER);
1914    for (argpos = 0; argpos < sMAXARGS; argpos++)
1915       arglist[argpos] = ARG_UNHANDLED;
1916    if (!matchtoken(')'))
1917      {
1918 	do
1919 	  {
1920 	     if (matchtoken('.'))
1921 	       {
1922 		  namedparams = TRUE;
1923 		  if (needtoken(tSYMBOL))
1924 		     tokeninfo(&lexval, &lexstr);
1925 		  else
1926 		     lexstr = "";
1927 		  argpos = findnamedarg(arg, lexstr);
1928 		  if (argpos < 0)
1929 		    {
1930 		       error(17, lexstr);	/* undefined symbol */
1931 		       break;	/* exit loop, argpos is invalid */
1932 		    }		/* if */
1933 		  needtoken('=');
1934 		  argidx = argpos;
1935 	       }
1936 	     else
1937 	       {
1938 		  if (namedparams)
1939 		     error(44);	/* positional parameters must precede named parameters */
1940 		  argpos = nargs;
1941 	       }		/* if */
1942 	     stgmark((char)(sEXPRSTART + argpos));	/* mark beginning of new expression in stage */
1943 	     if (arglist[argpos] != ARG_UNHANDLED)
1944 		error(58);	/* argument already set */
1945 	     if (matchtoken('_'))
1946 	       {
1947 		  arglist[argpos] = ARG_IGNORED;	/* flag argument as "present, but ignored" */
1948 		  if (arg[argidx].ident == 0 || arg[argidx].ident == iVARARGS)
1949 		    {
1950 		       error(202);	/* argument count mismatch */
1951 		    }
1952 		  else if (!arg[argidx].hasdefault)
1953 		    {
1954 		       error(34, nargs + 1);	/* argument has no default value */
1955 		    }		/* if */
1956 		  if (arg[argidx].ident != 0 && arg[argidx].ident != iVARARGS)
1957 		     argidx++;
1958 		  /* The rest of the code to handle default values is at the bottom
1959 		   * of this routine where default values for unspecified parameters
1960 		   * are (also) handled. Note that above, the argument is flagged as
1961 		   * ARG_IGNORED.
1962 		   */
1963 	       }
1964 	     else
1965 	       {
1966 		  arglist[argpos] = ARG_DONE;	/* flag argument as "present" */
1967 		  lvalue = hier14(&lval);
1968 		  switch (arg[argidx].ident)
1969 		    {
1970 		    case 0:
1971 		       error(202);	/* argument count mismatch */
1972 		       break;
1973 		    case iVARARGS:
1974 		       /* always pass by reference */
1975 		       if (lval.ident == iVARIABLE || lval.ident == iREFERENCE)
1976 			 {
1977 			    assert(lval.sym != NULL);
1978 			    if ((lval.sym->usage & uCONST) != 0
1979 				&& (arg[argidx].usage & uCONST) == 0)
1980 			      {
1981 				 /* treat a "const" variable passed to a function with a non-const
1982 				  * "variable argument list" as a constant here */
1983 				 assert(lvalue);
1984 				 rvalue(&lval);	/* get value in PRI */
1985 				 setheap_pri();	/* address of the value on the heap in PRI */
1986 				 heapalloc++;
1987 			      }
1988 			    else if (lvalue)
1989 			      {
1990 				 address(lval.sym);
1991 			      }
1992 			    else
1993 			      {
1994 				 setheap_pri();	/* address of the value on the heap in PRI */
1995 				 heapalloc++;
1996 			      }	/* if */
1997 			 }
1998 		       else if (lval.ident == iCONSTEXPR
1999 				|| lval.ident == iEXPRESSION
2000 				|| lval.ident == iARRAYCHAR)
2001 			 {
2002 			    /* fetch value if needed */
2003 			    if (lval.ident == iARRAYCHAR)
2004 			       rvalue(&lval);
2005 			    /* allocate a cell on the heap and store the
2006 			     * value (already in PRI) there */
2007 			    setheap_pri();	/* address of the value on the heap in PRI */
2008 			    heapalloc++;
2009 			 }	/* if */
2010 		       /* ??? handle const array passed by reference */
2011 		       /* otherwise, the address is already in PRI */
2012 		       if (lval.sym)
2013 			  markusage(lval.sym, uWRITTEN);
2014 /*
2015  * Dont need this warning - its varargs. there is no way of knowing the
2016  * required tag/type...
2017  *
2018           if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
2019             error(213);
2020  */
2021 		       break;
2022 		    case iVARIABLE:
2023 		       if (lval.ident == iLABEL || lval.ident == iFUNCTN
2024 			   || lval.ident == iREFFUNC || lval.ident == iARRAY
2025 			   || lval.ident == iREFARRAY)
2026 			  error(35, argidx + 1);	/* argument type mismatch */
2027 		       if (lvalue)
2028 			  rvalue(&lval);	/* get value (direct or indirect) */
2029 		       /* otherwise, the expression result is already in PRI */
2030 		       assert(arg[argidx].numtags > 0);
2031 		       check_userop(NULL, lval.tag, arg[argidx].tags[0], 2,
2032 				    NULL, &lval.tag);
2033 		       if (!checktag
2034 			   (arg[argidx].tags, arg[argidx].numtags, lval.tag))
2035 			  error(213);
2036 		       argidx++;	/* argument done */
2037 		       break;
2038 		    case iREFERENCE:
2039 		       if (!lvalue || lval.ident == iARRAYCHAR)
2040 			  error(35, argidx + 1);	/* argument type mismatch */
2041 		       if (lval.sym && (lval.sym->usage & uCONST) != 0
2042 			   && (arg[argidx].usage & uCONST) == 0)
2043 			  error(35, argidx + 1);	/* argument type mismatch */
2044 		       if (lval.ident == iVARIABLE || lval.ident == iREFERENCE)
2045 			 {
2046 			    if (lvalue)
2047 			      {
2048 				 assert(lval.sym != NULL);
2049 				 address(lval.sym);
2050 			      }
2051 			    else
2052 			      {
2053 				 setheap_pri();	/* address of the value on the heap in PRI */
2054 				 heapalloc++;
2055 			      }	/* if */
2056 			 }	/* if */
2057 		       /* otherwise, the address is already in PRI */
2058 		       if (!checktag
2059 			   (arg[argidx].tags, arg[argidx].numtags, lval.tag))
2060 			  error(213);
2061 		       argidx++;	/* argument done */
2062 		       if (lval.sym)
2063 			  markusage(lval.sym, uWRITTEN);
2064 		       break;
2065 		    case iREFARRAY:
2066 		       if (lval.ident != iARRAY && lval.ident != iREFARRAY
2067 			   && lval.ident != iARRAYCELL)
2068 			 {
2069 			    error(35, argidx + 1);	/* argument type mismatch */
2070 			    break;
2071 			 }	/* if */
2072 		       if (lval.sym && (lval.sym->usage & uCONST) != 0
2073 			   && (arg[argidx].usage & uCONST) == 0)
2074 			  error(35, argidx + 1);	/* argument type mismatch */
2075 		       /* Verify that the dimensions match with those in arg[argidx].
2076 		        * A literal array always has a single dimension.
2077 		        * An iARRAYCELL parameter is also assumed to have a single dimension.
2078 		        */
2079 		       if (!lval.sym || lval.ident == iARRAYCELL)
2080 			 {
2081 			    if (arg[argidx].numdim != 1)
2082 			      {
2083 				 error(48);	/* array dimensions must match */
2084 			      }
2085 			    else if (arg[argidx].dim[0] != 0)
2086 			      {
2087 				 assert(arg[argidx].dim[0] > 0);
2088 				 if (lval.ident == iARRAYCELL)
2089 				   {
2090 				      error(47);	/* array sizes must match */
2091 				   }
2092 				 else
2093 				   {
2094 				      assert(lval.constval != 0);	/* literal array must have a size */
2095 				      /* A literal array must have exactly the same size as the
2096 				       * function argument; a literal string may be smaller than
2097 				       * the function argument.
2098 				       */
2099 				      if ((lval.constval > 0
2100 					  && arg[argidx].dim[0] != lval.constval)
2101 					  || (lval.constval < 0
2102 					  && arg[argidx].dim[0] <
2103 					  -lval.constval))
2104 					 error(47);	/* array sizes must match */
2105 				   }	/* if */
2106 			      }	/* if */
2107 			    if (lval.ident != iARRAYCELL)
2108 			      {
2109 				 /* save array size, for default values with uSIZEOF flag */
2110 				 cell                array_sz = lval.constval;
2111 
2112 				 assert(array_sz != 0);	/* literal array must have a size */
2113 				 if (array_sz < 0)
2114 				    array_sz = -array_sz;
2115 				 append_constval(&arrayszlst, arg[argidx].name,
2116 						 array_sz, 0);
2117 			      }	/* if */
2118 			 }
2119 		       else
2120 			 {
2121 			    symbol             *lsym = lval.sym;
2122 			    short               level = 0;
2123 
2124 			    assert(lsym != NULL);
2125 			    if (lsym->dim.array.level + 1 != arg[argidx].numdim)
2126 			       error(48);	/* array dimensions must match */
2127 			    /* the lengths for all dimensions must match, unless the dimension
2128 			     * length was defined at zero (which means "undefined")
2129 			     */
2130 			    while (lsym->dim.array.level > 0)
2131 			      {
2132 				 assert(level < sDIMEN_MAX);
2133 				 if (arg[argidx].dim[level] != 0
2134 				     && lsym->dim.array.length !=
2135 				     arg[argidx].dim[level])
2136 				    error(47);	/* array sizes must match */
2137 				 append_constval(&arrayszlst, arg[argidx].name,
2138 						 lsym->dim.array.length, level);
2139 				 lsym = finddepend(lsym);
2140 				 assert(lsym != NULL);
2141 				 level++;
2142 			      }	/* if */
2143 			    /* the last dimension is checked too, again, unless it is zero */
2144 			    assert(level < sDIMEN_MAX);
2145 			    assert(lsym != NULL);
2146 			    if (arg[argidx].dim[level] != 0
2147 				&& lsym->dim.array.length !=
2148 				arg[argidx].dim[level])
2149 			       error(47);	/* array sizes must match */
2150 			    append_constval(&arrayszlst, arg[argidx].name,
2151 					    lsym->dim.array.length, level);
2152 			 }	/* if */
2153 		       /* address already in PRI */
2154 		       if (!checktag
2155 			   (arg[argidx].tags, arg[argidx].numtags, lval.tag))
2156 			  error(213);
2157 		       // ??? set uWRITTEN?
2158 		       argidx++;	/* argument done */
2159 		       break;
2160 		    }		/* switch */
2161 		  push1();	/* store the function argument on the stack */
2162 		  endexpr(FALSE);	/* mark the end of a sub-expression */
2163 	       }		/* if */
2164 	     assert(arglist[argpos] != ARG_UNHANDLED);
2165 	     nargs++;
2166 	     close = matchtoken(')');
2167 	     if (!close)	/* if not paranthese... */
2168 		if (!needtoken(','))	/* ...should be comma... */
2169 		   break;	/* ...but abort loop if neither */
2170 	  }
2171 	while (!close && freading && !matchtoken(tENDEXPR));	/* do */
2172      }				/* if */
2173    /* check remaining function arguments (they may have default values) */
2174    for (argidx = 0; arg[argidx].ident != 0 && arg[argidx].ident != iVARARGS;
2175 	argidx++)
2176      {
2177 	if (arglist[argidx] == ARG_DONE)
2178 	   continue;		/* already seen and handled this argument */
2179 	/* in this first stage, we also skip the arguments with uSIZEOF and uTAGOF;
2180 	 * these are handled last
2181 	 */
2182 	if ((arg[argidx].hasdefault & uSIZEOF) != 0
2183 	    || (arg[argidx].hasdefault & uTAGOF) != 0)
2184 	  {
2185 	     assert(arg[argidx].ident == iVARIABLE);
2186 	     continue;
2187 	  }			/* if */
2188 	stgmark((char)(sEXPRSTART + argidx));	/* mark beginning of new expression in stage */
2189 	if (arg[argidx].hasdefault)
2190 	  {
2191 	     if (arg[argidx].ident == iREFARRAY)
2192 	       {
2193 		  short               level;
2194 
2195 		  setdefarray(arg[argidx].defvalue.array.data,
2196 			      arg[argidx].defvalue.array.size,
2197 			      arg[argidx].defvalue.array.arraysize,
2198 			      &arg[argidx].defvalue.array.addr,
2199 			      (arg[argidx].usage & uCONST) != 0);
2200 		  if ((arg[argidx].usage & uCONST) == 0)
2201 		     heapalloc += arg[argidx].defvalue.array.arraysize;
2202 		  /* keep the lengths of all dimensions of a multi-dimensional default array */
2203 		  assert(arg[argidx].numdim > 0);
2204 		  if (arg[argidx].numdim == 1)
2205 		    {
2206 		       append_constval(&arrayszlst, arg[argidx].name,
2207 				       arg[argidx].defvalue.array.arraysize, 0);
2208 		    }
2209 		  else
2210 		    {
2211 		       for (level = 0; level < arg[argidx].numdim; level++)
2212 			 {
2213 			    assert(level < sDIMEN_MAX);
2214 			    append_constval(&arrayszlst, arg[argidx].name,
2215 					    arg[argidx].dim[level], level);
2216 			 }	/* for */
2217 		    }		/* if */
2218 	       }
2219 	     else if (arg[argidx].ident == iREFERENCE)
2220 	       {
2221 		  setheap(arg[argidx].defvalue.val);
2222 		  /* address of the value on the heap in PRI */
2223 		  heapalloc++;
2224 	       }
2225 	     else
2226 	       {
2227 		  int                 dummytag = arg[argidx].tags[0];
2228 
2229 		  const1(arg[argidx].defvalue.val);
2230 		  assert(arg[argidx].numtags > 0);
2231 		  check_userop(NULL, arg[argidx].defvalue_tag,
2232 			       arg[argidx].tags[0], 2, NULL, &dummytag);
2233 		  assert(dummytag == arg[argidx].tags[0]);
2234 	       }		/* if */
2235 	     push1();		/* store the function argument on the stack */
2236 	     endexpr(FALSE);	/* mark the end of a sub-expression */
2237 	  }
2238 	else
2239 	  {
2240 	     error(202, argidx);	/* argument count mismatch */
2241 	  }			/* if */
2242 	if (arglist[argidx] == ARG_UNHANDLED)
2243 	   nargs++;
2244 	arglist[argidx] = ARG_DONE;
2245      }				/* for */
2246    /* now a second loop to catch the arguments with default values that are
2247     * the "sizeof" or "tagof" of other arguments
2248     */
2249    for (argidx = 0; arg[argidx].ident != 0 && arg[argidx].ident != iVARARGS;
2250 	argidx++)
2251      {
2252 	constvalue         *asz;
2253 	cell                array_sz;
2254 
2255 	if (arglist[argidx] == ARG_DONE)
2256 	   continue;		/* already seen and handled this argument */
2257 	stgmark((char)(sEXPRSTART + argidx));	/* mark beginning of new expression in stage */
2258 	assert(arg[argidx].ident == iVARIABLE);	/* if "sizeof", must be single cell */
2259 	/* if unseen, must be "sizeof" or "tagof" */
2260 	assert((arg[argidx].hasdefault & uSIZEOF) != 0
2261 	       || (arg[argidx].hasdefault & uTAGOF) != 0);
2262 	if ((arg[argidx].hasdefault & uSIZEOF) != 0)
2263 	  {
2264 	     /* find the argument; if it isn't found, the argument's default value
2265 	      * was a "sizeof" of a non-array (a warning for this was already given
2266 	      * when declaring the function)
2267 	      */
2268 	     asz = find_constval(&arrayszlst, arg[argidx].defvalue.size.symname,
2269 				 arg[argidx].defvalue.size.level);
2270 	     if (asz)
2271 	       {
2272 		  array_sz = asz->value;
2273 		  if (array_sz == 0)
2274 		     error(224, arg[argidx].name);	/* indeterminate array size in "sizeof" expression */
2275 	       }
2276 	     else
2277 	       {
2278 		  array_sz = 1;
2279 	       }		/* if */
2280 	  }
2281 	else
2282 	  {
2283 	     symbol             *lsym;
2284 
2285 	     assert((arg[argidx].hasdefault & uTAGOF) != 0);
2286 	     lsym = findloc(arg[argidx].defvalue.size.symname);
2287 	     if (!lsym)
2288 		lsym = findglb(arg[argidx].defvalue.size.symname);
2289 	     array_sz = (lsym) ? lsym->tag : 0;
2290 	     exporttag(array_sz);
2291 	  }			/* if */
2292 	const1(array_sz);
2293 	push1();		/* store the function argument on the stack */
2294 	endexpr(FALSE);
2295 	if (arglist[argidx] == ARG_UNHANDLED)
2296 	   nargs++;
2297 	arglist[argidx] = ARG_DONE;
2298      }				/* for */
2299    stgmark(sENDREORDER);	/* mark end of reversed evaluation */
2300    pushval((cell) nargs * sizeof(cell));
2301    ffcall(sym, nargs);
2302    if (sc_status != statSKIP)
2303       markusage(sym, uREAD);	/* do not mark as "used" when this call itself is skipped */
2304    if (sym->x.lib)
2305       sym->x.lib->value += 1;	/* increment "usage count" of the library */
2306    modheap(-heapalloc * sizeof(cell));
2307    sideeffect = TRUE;		/* assume functions carry out a side-effect */
2308    delete_consttable(&arrayszlst);	/* clear list of array sizes */
2309 }
2310 
2311 /*  dbltest
2312  *
2313  *  Returns a non-zero value if lval1 an array and lval2 is not an array and
2314  *  the operation is addition or subtraction.
2315  *
2316  *  Returns the "shift" count (1 for 16-bit, 2 for 32-bit) to align a cell
2317  *  to an array offset.
2318  */
2319 static int
dbltest(void (* oper)(),value * lval1,value * lval2)2320 dbltest(void        (*oper) (), value * lval1, value * lval2)
2321 {
2322    if ((oper != ob_add) && (oper != ob_sub))
2323       return 0;
2324    if (lval1->ident != iARRAY)
2325       return 0;
2326    if (lval2->ident == iARRAY)
2327       return 0;
2328    return sizeof(cell) / 2;	/* 1 for 16-bit, 2 for 32-bit */
2329 }
2330 
2331 /*  commutative
2332  *
2333  *  Test whether an operator is commutative, i.e. x oper y == y oper x.
2334  *  Commutative operators are: +  (addition)
2335  *                             *  (multiplication)
2336  *                             == (equality)
2337  *                             != (inequality)
2338  *                             &  (bitwise and)
2339  *                             ^  (bitwise xor)
2340  *                             |  (bitwise or)
2341  *
2342  *  If in an expression, code for the left operand has been generated and
2343  *  the right operand is a constant and the operator is commutative, the
2344  *  precautionary "push" of the primary register is scrapped and the constant
2345  *  is read into the secondary register immediately.
2346  */
2347 static int
commutative(void (* oper)())2348 commutative(void    (*oper) ())
2349 {
2350    return oper == ob_add || oper == os_mult
2351       || oper == ob_eq || oper == ob_ne
2352       || oper == ob_and || oper == ob_xor || oper == ob_or;
2353 }
2354 
2355 /*  constant
2356  *
2357  *  Generates code to fetch a number, a literal character (which is returned
2358  *  by lex() as a number as well) or a literal string (lex() stores the
2359  *  strings in the literal queue). If the operand was a number, it is stored
2360  *  in lval->constval.
2361  *
2362  *  The function returns 1 if the token was a constant or a string, 0
2363  *  otherwise.
2364  */
2365 static int
constant(value * lval)2366 constant(value * lval)
2367 {
2368    int                 tok, idx, is_constant;
2369    cell                val, item, cidx;
2370    char               *st;
2371    symbol             *sym;
2372 
2373    tok = lex(&val, &st);
2374    if (tok == tSYMBOL && (sym = findconst(st)))
2375      {
2376 	lval->constval = sym->addr;
2377 	const1(lval->constval);
2378 	lval->ident = iCONSTEXPR;
2379 	lval->tag = sym->tag;
2380 	markusage(sym, uREAD);
2381      }
2382    else if (tok == tNUMBER)
2383      {
2384 	lval->constval = val;
2385 	const1(lval->constval);
2386 	lval->ident = iCONSTEXPR;
2387      }
2388    else if (tok == tRATIONAL)
2389      {
2390 	lval->constval = val;
2391 	const1(lval->constval);
2392 	lval->ident = iCONSTEXPR;
2393 	lval->tag = sc_rationaltag;
2394      }
2395    else if (tok == tSTRING)
2396      {
2397 	/* lex() stores starting index of string in the literal table in 'val' */
2398 	const1((val + glb_declared) * sizeof(cell));
2399 	lval->ident = iARRAY;	/* pretend this is a global array */
2400 	lval->constval = val - litidx;	/* constval == the negative value of the
2401 					 * size of the literal array; using a negative
2402 					 * value distinguishes between literal arrays
2403 					 * and literal strings (this was done for
2404 					 * array assignment). */
2405      }
2406    else if (tok == '{')
2407      {
2408 	int                 tag, lasttag = -1;
2409 
2410 	val = litidx;
2411 	do
2412 	  {
2413 	     /* cannot call constexpr() here, because "staging" is already turned
2414 	      * on at this point */
2415 	     assert(staging);
2416 	     stgget(&idx, &cidx);	/* mark position in code generator */
2417 	     expression(&is_constant, &item, &tag, FALSE);
2418 	     stgdel(idx, cidx);	/* scratch generated code */
2419 	     if (is_constant == 0)
2420 		error(8);	/* must be constant expression */
2421 	     if (lasttag < 0)
2422 		lasttag = tag;
2423 	     else if (!matchtag(lasttag, tag, FALSE))
2424 		error(213);	/* tagname mismatch */
2425 	     stowlit(item);	/* store expression result in literal table */
2426 	  }
2427 	while (matchtoken(','));
2428 	needtoken('}');
2429 	const1((val + glb_declared) * sizeof(cell));
2430 	lval->ident = iARRAY;	/* pretend this is a global array */
2431 	lval->constval = litidx - val;	/* constval == the size of the literal array */
2432      }
2433    else
2434      {
2435 	return FALSE;		/* no, it cannot be interpreted as a constant */
2436      }				/* if */
2437    return TRUE;			/* yes, it was a constant value */
2438 }
2439