]> git.sur5r.net Git - cc65/blob - src/cc65/expr.c
2d04142bc8b42f9fa95ce179260325a5ffbb2e0f
[cc65] / src / cc65 / expr.c
1 /*
2  * expr.c
3  *
4  * Ullrich von Bassewitz, 21.06.1998
5  */
6
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 /* common */
14 #include "check.h"
15 #include "xmalloc.h"
16
17 /* cc65 */
18 #include "asmcode.h"
19 #include "asmlabel.h"
20 #include "codegen.h"
21 #include "datatype.h"
22 #include "declare.h"
23 #include "error.h"
24 #include "funcdesc.h"
25 #include "function.h"
26 #include "global.h"
27 #include "litpool.h"
28 #include "macrotab.h"
29 #include "preproc.h"
30 #include "scanner.h"
31 #include "stdfunc.h"
32 #include "symtab.h"
33 #include "typecmp.h"
34 #include "expr.h"
35
36
37
38 /*****************************************************************************/
39 /*                                   Data                                    */
40 /*****************************************************************************/
41
42
43
44 /* Generator attributes */
45 #define GEN_NOPUSH      0x01            /* Don't push lhs */
46
47 /* Map a generator function and its attributes to a token */
48 typedef struct {
49     unsigned char Tok;                  /* Token to map to */
50     unsigned char Flags;                /* Flags for generator function */
51     void          (*Func) (unsigned, unsigned long);    /* Generator func */
52 } GenDesc;
53
54 /* Descriptors for the operations */
55 static GenDesc GenMUL    = { TOK_STAR,          GEN_NOPUSH,     g_mul };
56 static GenDesc GenDIV    = { TOK_DIV,           GEN_NOPUSH,     g_div };
57 static GenDesc GenMOD    = { TOK_MOD,           GEN_NOPUSH,     g_mod };
58 static GenDesc GenASL    = { TOK_SHL,           GEN_NOPUSH,     g_asl };
59 static GenDesc GenASR    = { TOK_SHR,           GEN_NOPUSH,     g_asr };
60 static GenDesc GenLT     = { TOK_LT,            GEN_NOPUSH,     g_lt  };
61 static GenDesc GenLE     = { TOK_LE,            GEN_NOPUSH,     g_le  };
62 static GenDesc GenGE     = { TOK_GE,            GEN_NOPUSH,     g_ge  };
63 static GenDesc GenGT     = { TOK_GT,            GEN_NOPUSH,     g_gt  };
64 static GenDesc GenEQ     = { TOK_EQ,            GEN_NOPUSH,     g_eq  };
65 static GenDesc GenNE     = { TOK_NE,            GEN_NOPUSH,     g_ne  };
66 static GenDesc GenAND    = { TOK_AND,           GEN_NOPUSH,     g_and };
67 static GenDesc GenXOR    = { TOK_XOR,           GEN_NOPUSH,     g_xor };
68 static GenDesc GenOR     = { TOK_OR,            GEN_NOPUSH,     g_or  };
69 static GenDesc GenPASGN  = { TOK_PLUS_ASSIGN,   GEN_NOPUSH,     g_add };
70 static GenDesc GenSASGN  = { TOK_MINUS_ASSIGN,  GEN_NOPUSH,     g_sub };
71 static GenDesc GenMASGN  = { TOK_MUL_ASSIGN,    GEN_NOPUSH,     g_mul };
72 static GenDesc GenDASGN  = { TOK_DIV_ASSIGN,    GEN_NOPUSH,     g_div };
73 static GenDesc GenMOASGN = { TOK_MOD_ASSIGN,    GEN_NOPUSH,     g_mod };
74 static GenDesc GenSLASGN = { TOK_SHL_ASSIGN,    GEN_NOPUSH,     g_asl };
75 static GenDesc GenSRASGN = { TOK_SHR_ASSIGN,    GEN_NOPUSH,     g_asr };
76 static GenDesc GenAASGN  = { TOK_AND_ASSIGN,    GEN_NOPUSH,     g_and };
77 static GenDesc GenXOASGN = { TOK_XOR_ASSIGN,    GEN_NOPUSH,     g_xor };
78 static GenDesc GenOASGN  = { TOK_OR_ASSIGN,     GEN_NOPUSH,     g_or  };
79
80
81
82 /*****************************************************************************/
83 /*                             Function forwards                             */
84 /*****************************************************************************/
85
86
87
88 static int hie10 (struct expent* lval);
89 /* Handle ++, --, !, unary - etc. */
90
91
92
93 /*****************************************************************************/
94 /*                             Helper functions                              */
95 /*****************************************************************************/
96
97
98
99 static unsigned GlobalModeFlags (unsigned flags)
100 /* Return the addressing mode flags for the variable with the given flags */
101 {
102     flags &= E_MCTYPE;
103     if (flags == E_TGLAB) {
104         /* External linkage */
105         return CF_EXTERNAL;
106     } else if (flags == E_TREGISTER) {
107         /* Register variable */
108         return CF_REGVAR;
109     } else {
110         /* Static */
111         return CF_STATIC;
112     }
113 }
114
115
116
117 static int IsNullPtr (struct expent* lval)
118 /* Return true if this is the NULL pointer constant */
119 {
120     return (IsClassInt (lval->e_tptr) &&        /* Is it an int? */
121             lval->e_flags == E_MCONST &&        /* Is it constant? */
122             lval->e_const == 0);                /* And is it's value zero? */
123 }
124
125
126
127 static type* promoteint (type* lhst, type* rhst)
128 /* In an expression with two ints, return the type of the result */
129 {
130     /* Rules for integer types:
131      *   - If one of the values is a long, the result is long.
132      *   - If one of the values is unsigned, the result is also unsigned.
133      *   - Otherwise the result is an int.
134      */
135     if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
136         if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
137             return type_ulong;
138         } else {
139             return type_long;
140         }
141     } else {
142         if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
143             return type_uint;
144         } else {
145             return type_int;
146         }
147     }
148 }
149
150
151
152 static unsigned typeadjust (struct expent* lhs, struct expent* rhs, int NoPush)
153 /* Adjust the two values for a binary operation. lhs is expected on stack or
154  * to be constant, rhs is expected to be in the primary register or constant.
155  * The function will put the type of the result into lhs and return the
156  * code generator flags for the operation.
157  * If NoPush is given, it is assumed that the operation does not expect the lhs
158  * to be on stack, and that lhs is in a register instead.
159  * Beware: The function does only accept int types.
160  */
161 {
162     unsigned ltype, rtype;
163     unsigned flags;
164
165     /* Get the type strings */
166     type* lhst = lhs->e_tptr;
167     type* rhst = rhs->e_tptr;
168
169     /* Generate type adjustment code if needed */
170     ltype = TypeOf (lhst);
171     if (lhs->e_flags == E_MCONST) {
172         ltype |= CF_CONST;
173     }
174     if (NoPush) {
175         /* Value is in primary register*/
176         ltype |= CF_REG;
177     }
178     rtype = TypeOf (rhst);
179     if (rhs->e_flags == E_MCONST) {
180         rtype |= CF_CONST;
181     }
182     flags = g_typeadjust (ltype, rtype);
183
184     /* Set the type of the result */
185     lhs->e_tptr = promoteint (lhst, rhst);
186
187     /* Return the code generator flags */
188     return flags;
189 }
190
191
192
193 unsigned assignadjust (type* lhst, struct expent* rhs)
194 /* Adjust the type of the right hand expression so that it can be assigned to
195  * the type on the left hand side. This function is used for assignment and
196  * for converting parameters in a function call. It returns the code generator
197  * flags for the operation. The type string of the right hand side will be
198  * set to the type of the left hand side.
199  */
200 {
201     /* Get the type of the right hand side. Treat function types as
202      * pointer-to-function
203      */
204     type* rhst = rhs->e_tptr;
205     if (IsTypeFunc (rhst)) {
206         rhst = PointerTo (rhst);
207     }
208
209     /* After calling this function, rhs will have the type of the lhs */
210     rhs->e_tptr = lhst;
211
212     /* First, do some type checking */
213     if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) {
214         /* If one of the sides are of type void, output a more apropriate
215          * error message.
216          */
217         Error ("Illegal type");
218     } else if (IsClassInt (lhst)) {
219         if (IsClassPtr (rhst)) {
220             /* Pointer -> int conversion */
221             Warning ("Converting pointer to integer without a cast");
222         } else if (!IsClassInt (rhst)) {
223             Error ("Incompatible types");
224         } else {
225             /* Adjust the int types. To avoid manipulation of TOS mark lhs
226              * as const.
227              */
228             unsigned flags = TypeOf (rhst);
229             if (rhs->e_flags & E_MCONST) {
230                 flags |= CF_CONST;
231             }
232             return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
233         }
234     } else if (IsClassPtr (lhst)) {
235         if (IsClassPtr (rhst)) {
236             /* Pointer to pointer assignment is valid, if:
237              *   - both point to the same types, or
238              *   - the rhs pointer is a void pointer, or
239              *   - the lhs pointer is a void pointer.
240              */
241             if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
242                 /* Compare the types */
243                 switch (TypeCmp (lhst, rhst)) {
244
245                     case TC_INCOMPATIBLE:
246                         Error ("Incompatible pointer types");
247                         break;
248
249                     case TC_QUAL_DIFF:
250                         Error ("Pointer types differ in type qualifiers");
251                         break;
252
253                     default:
254                         /* Ok */
255                         break;
256                 }
257             }
258         } else if (IsClassInt (rhst)) {
259             /* Int to pointer assignment is valid only for constant zero */
260             if ((rhs->e_flags & E_MCONST) == 0 || rhs->e_const != 0) {
261                 Warning ("Converting integer to pointer without a cast");
262             }
263         } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
264             /* Assignment of function to function pointer is allowed, provided
265              * that both functions have the same parameter list.
266              */
267             if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
268                 Error ("Incompatible types");
269             }
270         } else {
271             Error ("Incompatible types");
272         }
273     } else {
274         Error ("Incompatible types");
275     }
276
277     /* Return an int value in all cases where the operands are not both ints */
278     return CF_INT;
279 }
280
281
282
283 void DefineData (struct expent* lval)
284 /* Output a data definition for the given expression */
285 {
286     unsigned flags = lval->e_flags;
287
288     switch (flags & E_MCTYPE) {
289
290         case E_TCONST:
291             /* Number */
292             g_defdata (TypeOf (lval->e_tptr) | CF_CONST, lval->e_const, 0);
293             break;
294
295         case E_TREGISTER:
296             /* Register variable. Taking the address is usually not
297              * allowed.
298              */
299             if (!AllowRegVarAddr) {
300                 Error ("Cannot take the address of a register variable");
301             }
302             /* FALLTHROUGH */
303
304         case E_TGLAB:
305         case E_TLLAB:
306             /* Local or global symbol */
307             g_defdata (GlobalModeFlags (flags), lval->e_name, lval->e_const);
308             break;
309
310         case E_TLIT:
311             /* a literal of some kind */
312             g_defdata (CF_STATIC, LiteralPoolLabel, lval->e_const);
313             break;
314
315         default:
316             Internal ("Unknown constant type: %04X", flags);
317     }
318 }
319
320
321
322 static void lconst (unsigned flags, struct expent* lval)
323 /* Load primary reg with some constant value. */
324 {
325     switch (lval->e_flags & E_MCTYPE) {
326
327         case E_TLOFFS:
328             g_leasp (lval->e_const);
329             break;
330
331         case E_TCONST:
332             /* Number constant */
333             g_getimmed (flags | TypeOf (lval->e_tptr) | CF_CONST, lval->e_const, 0);
334             break;
335
336         case E_TREGISTER:
337             /* Register variable. Taking the address is usually not
338              * allowed.
339              */
340             if (!AllowRegVarAddr) {
341                 Error ("Cannot take the address of a register variable");
342             }
343             /* FALLTHROUGH */
344
345         case E_TGLAB:
346         case E_TLLAB:
347             /* Local or global symbol, load address */
348             flags |= GlobalModeFlags (lval->e_flags);
349             flags &= ~CF_CONST;
350             g_getimmed (flags, lval->e_name, lval->e_const);
351             break;
352
353         case E_TLIT:
354             /* Literal string */
355             g_getimmed (CF_STATIC, LiteralPoolLabel, lval->e_const);
356             break;
357
358         default:
359             Internal ("Unknown constant type: %04X", lval->e_flags);
360     }
361 }
362
363
364
365 static int kcalc (int tok, long val1, long val2)
366 /* Calculate an operation with left and right operand constant. */
367 {
368     switch (tok) {
369         case TOK_EQ:
370             return (val1 == val2);
371         case TOK_NE:
372             return (val1 != val2);
373         case TOK_LT:
374             return (val1 < val2);
375         case TOK_LE:
376             return (val1 <= val2);
377         case TOK_GE:
378             return (val1 >= val2);
379         case TOK_GT:
380             return (val1 > val2);
381         case TOK_OR:
382             return (val1 | val2);
383         case TOK_XOR:
384             return (val1 ^ val2);
385         case TOK_AND:
386             return (val1 & val2);
387         case TOK_SHR:
388             return (val1 >> val2);
389         case TOK_SHL:
390             return (val1 << val2);
391         case TOK_STAR:
392             return (val1 * val2);
393         case TOK_DIV:
394             if (val2 == 0) {
395                 Error ("Division by zero");
396                 return 0x7FFFFFFF;
397             }
398             return (val1 / val2);
399         case TOK_MOD:
400             if (val2 == 0) {
401                 Error ("Modulo operation with zero");
402                 return 0;
403             }
404             return (val1 % val2);
405         default:
406             Internal ("kcalc: got token 0x%X\n", tok);
407             return 0;
408     }
409 }
410
411
412
413 static GenDesc* FindGen (int Tok, GenDesc** Table)
414 {
415     GenDesc* G;
416     while ((G = *Table) != 0) {
417         if (G->Tok == Tok) {
418             return G;
419         }
420         ++Table;
421     }
422     return 0;
423 }
424
425
426
427 static int istypeexpr (void)
428 /* Return true if some sort of variable or type is waiting (helper for cast
429  * and sizeof() in hie10).
430  */
431 {
432     SymEntry* Entry;
433
434     return curtok == TOK_LPAREN && (
435             (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
436             (nxttok == TOK_CONST)                               ||
437             (nxttok  == TOK_IDENT                               &&
438             (Entry = FindSym (NextTok.Ident)) != 0              &&
439             IsTypeDef (Entry))
440            );
441 }
442
443
444
445 static void PushAddr (struct expent* lval)
446 /* If the expression contains an address that was somehow evaluated,
447  * push this address on the stack. This is a helper function for all
448  * sorts of implicit or explicit assignment functions where the lvalue
449  * must be saved if it's not constant, before evaluating the rhs.
450  */
451 {
452     /* Get the address on stack if needed */
453     if (lval->e_flags != E_MREG && (lval->e_flags & E_MEXPR)) {
454         /* Push the address (always a pointer) */
455         g_push (CF_PTR, 0);
456     }
457 }
458
459
460
461 /*****************************************************************************/
462 /*                                   code                                    */
463 /*****************************************************************************/
464
465
466
467 void exprhs (unsigned flags, int k, struct expent *lval)
468 /* Put the result of an expression into the primary register */
469 {
470     int f;
471
472     f = lval->e_flags;
473     if (k) {
474         /* Dereferenced lvalue */
475         flags |= TypeOf (lval->e_tptr);
476         if (lval->e_test & E_FORCETEST) {
477             flags |= CF_TEST;
478             lval->e_test &= ~E_FORCETEST;
479         }
480         if (f & E_MGLOBAL) {    /* ref to globalvar */
481             /* Generate code */
482             flags |= GlobalModeFlags (f);
483             g_getstatic (flags, lval->e_name, lval->e_const);
484         } else if (f & E_MLOCAL) {
485             /* ref to localvar */
486             g_getlocal (flags, lval->e_const);
487         } else if (f & E_MCONST) {
488             /* ref to absolute address */
489             g_getstatic (flags | CF_ABSOLUTE, lval->e_const, 0);
490         } else if (f == E_MEOFFS) {
491             g_getind (flags, lval->e_const);
492         } else if (f != E_MREG) {
493             g_getind (flags, 0);
494         }
495     } else if (f == E_MEOFFS) {
496         /* reference not storable */
497         flags |= TypeOf (lval->e_tptr);
498         g_inc (flags | CF_CONST, lval->e_const);
499     } else if ((f & E_MEXPR) == 0) {
500         /* Constant of some sort, load it into the primary */
501         lconst (flags, lval);
502     }
503     if (lval->e_test & E_FORCETEST) {   /* we testing this value? */
504         /* debug... */
505         AddCodeHint ("forcetest");
506         flags |= TypeOf (lval->e_tptr);
507         g_test (flags);                 /* yes, force a test */
508         lval->e_test &= ~E_FORCETEST;
509     }
510 }
511
512
513
514 static unsigned FunctionParamList (FuncDesc* Func)
515 /* Parse a function parameter list and pass the parameters to the called
516  * function. Depending on several criteria this may be done by just pushing
517  * each parameter separately, or creating the parameter frame once and then
518  * storing into this frame.
519  * The function returns the size of the parameters pushed.
520  */
521 {
522     struct expent lval;
523
524     /* Initialize variables */
525     SymEntry* Param       = 0;  /* Keep gcc silent */
526     unsigned  ParamSize   = 0;  /* Size of parameters pushed */
527     unsigned  ParamCount  = 0;  /* Number of parameters pushed */
528     unsigned  FrameSize   = 0;  /* Size of parameter frame */
529     unsigned  FrameParams = 0;  /* Number of params in frame */
530     int       FrameOffs   = 0;  /* Offset into parameter frame */
531     int       Ellipsis    = 0;  /* Function is variadic */
532
533     /* As an optimization, we may allocate the complete parameter frame at
534      * once instead of pushing each parameter as it comes. We may do that,
535      * if...
536      *
537      *  - optimizations that increase code size are enabled (allocating the
538      *    stack frame at once gives usually larger code).
539      *  - we have more than one parameter to push (don't count the last param
540      *    for __fastcall__ functions).
541      */
542     if (CodeSizeFactor >= 200) {
543
544         /* Calculate the number and size of the parameters */
545         FrameParams = Func->ParamCount;
546         FrameSize   = Func->ParamSize;
547         if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) {
548             /* Last parameter is not pushed */
549             const SymEntry* LastParam = Func->SymTab->SymTail;
550             FrameSize -= SizeOf (LastParam->Type);
551             --FrameParams;
552         }
553
554         /* Do we have more than one parameter in the frame? */
555         if (FrameParams > 1) {
556             /* Okeydokey, setup the frame */
557             FrameOffs = oursp;
558             g_space (FrameSize);
559             oursp -= FrameSize;
560         } else {
561             /* Don't use a preallocated frame */
562             FrameSize = 0;
563         }
564     }
565
566     /* Parse the actual parameter list */
567     while (curtok != TOK_RPAREN) {
568
569         unsigned CFlags;
570         unsigned Flags;
571
572         /* Add a hint for the optimizer */
573         AddCodeHint ("param:start");
574
575         /* Count arguments */
576         ++ParamCount;
577
578         /* Fetch the pointer to the next argument, check for too many args */
579         if (ParamCount <= Func->ParamCount) {
580             /* Beware: If there are parameters with identical names, they
581              * cannot go into the same symbol table, which means that in this
582              * case of errorneous input, the number of nodes in the symbol
583              * table and ParamCount are NOT equal. We have to handle this case
584              * below to avoid segmentation violations. Since we know that this
585              * problem can only occur if there is more than one parameter,
586              * we will just use the last one.
587              */
588             if (ParamCount == 1) {
589                 /* First argument */
590                 Param = Func->SymTab->SymHead;
591             } else if (Param->NextSym != 0) {
592                 /* Next argument */
593                 Param = Param->NextSym;
594                 CHECK ((Param->Flags & SC_PARAM) != 0);
595             }
596         } else if (!Ellipsis) {
597             /* Too many arguments. Do we have an open param list? */
598             if ((Func->Flags & FD_VARIADIC) == 0) {
599                 /* End of param list reached, no ellipsis */
600                 Error ("Too many arguments in function call");
601             }
602             /* Assume an ellipsis even in case of errors to avoid an error
603              * message for each other argument.
604              */
605             Ellipsis = 1;
606         }
607
608         /* Do some optimization: If we have a constant value to push,
609          * use a special function that may optimize.
610          */
611         CFlags = CF_NONE;
612         if (!Ellipsis && SizeOf (Param->Type) == 1) {
613             CFlags = CF_FORCECHAR;
614         }
615         Flags = CF_NONE;
616         if (evalexpr (CFlags, hie1, &lval) == 0) {
617             /* A constant value */
618             Flags |= CF_CONST;
619         }
620
621         /* If we don't have an argument spec, accept anything, otherwise
622          * convert the actual argument to the type needed.
623          */
624         if (!Ellipsis) {
625             /* Promote the argument if needed */
626             assignadjust (Param->Type, &lval);
627
628             /* If we have a prototype, chars may be pushed as chars */
629             Flags |= CF_FORCECHAR;
630         }
631
632         /* Use the type of the argument for the push */
633         Flags |= TypeOf (lval.e_tptr);
634
635         /* If this is a fastcall function, don't push the last argument */
636         if (ParamCount == Func->ParamCount && (Func->Flags & FD_FASTCALL) != 0) {
637             /* Just load the argument into the primary. This is only needed if
638              * we have a constant argument, otherwise the value is already in
639              * the primary.
640              */
641             if (Flags & CF_CONST) {
642                 exprhs (CF_FORCECHAR, 0, &lval);
643             }
644         } else {
645             unsigned ArgSize = sizeofarg (Flags);
646             if (FrameSize > 0) {
647                 /* We have the space already allocated, store in the frame */
648                 CHECK (FrameSize >= ArgSize);
649                 FrameSize -= ArgSize;
650                 FrameOffs -= ArgSize;
651                 /* Store */
652                 g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
653             } else {
654                 /* Push the argument */
655                 g_push (Flags, lval.e_const);
656             }
657
658             /* Calculate total parameter size */
659             ParamSize += ArgSize;
660         }
661
662         /* Add an optimizer hint */
663         AddCodeHint ("param:end");
664
665         /* Check for end of argument list */
666         if (curtok != TOK_COMMA) {
667             break;
668         }
669         NextToken ();
670     }
671
672     /* Check if we had enough parameters */
673     if (ParamCount < Func->ParamCount) {
674         Error ("Too few arguments in function call");
675     }
676
677     /* The function returns the size of all parameters pushed onto the stack.
678      * However, if there are parameters missing (which is an error and was
679      * flagged by the compiler) AND a stack frame was preallocated above,
680      * we would loose track of the stackpointer and generate an internal error
681      * later. So we correct the value by the parameters that should have been
682      * pushed to avoid an internal compiler error. Since an error was
683      * generated before, no code will be output anyway.
684      */
685     return ParamSize + FrameSize;
686 }
687
688
689
690 static void CallFunction (struct expent* lval)
691 /* Perform a function call.  Called from hie11, this routine will
692  * either call the named function, or the function pointer in a/x.
693  */
694 {
695     FuncDesc*     Func;         /* Function descriptor */
696     unsigned      ParamSize;    /* Number of parameter bytes */
697     CodeMark      Mark;
698
699
700     /* Get a pointer to the function descriptor from the type string */
701     Func = GetFuncDesc (lval->e_tptr);
702
703     /* Initialize vars to keep gcc silent */
704     Mark  = 0;
705
706     /* Check if this is a function pointer. If so, save it. If not, check for
707      * special known library functions that may be inlined.
708      */
709     if (lval->e_flags & E_MEXPR) {
710         /* Function pointer is in primary register, save it */
711         Mark = GetCodePos ();
712         g_save (CF_PTR);
713     } else if (InlineStdFuncs && IsStdFunc ((const char*) lval->e_name)) {
714         /* Inline this function */
715         HandleStdFunc (lval);
716         return;
717     }
718
719     /* Parse the parameter list */
720     ParamSize = FunctionParamList (Func);
721
722     /* We need the closing bracket here */
723     ConsumeRParen ();
724
725     /* */
726     if (lval->e_flags & E_MEXPR) {
727         /* Function called via pointer: Restore it and call function */
728         if (ParamSize != 0) {
729             g_restore (CF_PTR);
730         } else {
731             /* We had no parameters - remove save code */
732             RemoveCode (Mark);
733         }
734         g_callind (TypeOf (lval->e_tptr), ParamSize);
735     } else {
736         g_call (TypeOf (lval->e_tptr), (const char*) lval->e_name, ParamSize);
737     }
738 }
739
740
741
742 void doasm (void)
743 /* This function parses ASM statements. The syntax of the ASM directive
744  * looks like the one defined for C++ (C has no ASM directive), that is,
745  * a string literal in parenthesis.
746  */
747 {
748     /* Skip the ASM */
749     NextToken ();
750
751     /* Need left parenthesis */
752     ConsumeLParen ();
753
754     /* String literal */
755     if (curtok != TOK_SCONST) {
756         Error ("String literal expected");
757     } else {
758         /* Write the string directly into the output, followed by a newline */
759         AddCodeLine (GetLiteral (curval));
760
761         /* Reset the string pointer, effectivly clearing the string from the
762          * string table. Since we're working with one token lookahead, this
763          * will fail if the next token is also a string token, but that's a
764          * syntax error anyway, because we expect a right paren.
765          */
766         ResetLiteralPoolOffs (curval);
767     }
768
769     /* Skip the string token */
770     NextToken ();
771
772     /* Closing paren needed */
773     ConsumeRParen ();
774 }
775
776
777
778 static int primary (struct expent* lval)
779 /* This is the lowest level of the expression parser. */
780 {
781     int k;
782
783     /* not a test at all, yet */
784     lval->e_test = 0;
785
786     /* Character and integer constants. */
787     if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
788         lval->e_flags = E_MCONST | E_TCONST;
789         lval->e_tptr  = curtype;
790         lval->e_const = curval;
791         NextToken ();
792         return 0;
793     }
794
795     /* Process parenthesized subexpression by calling the whole parser
796      * recursively.
797      */
798     if (curtok == TOK_LPAREN) {
799         NextToken ();
800         memset (lval, 0, sizeof (*lval));       /* Remove any attributes */
801         k = hie0 (lval);
802         ConsumeRParen ();
803         return k;
804     }
805
806     /* All others may only be used if the expression evaluation is not called
807      * recursively by the preprocessor.
808      */
809     if (Preprocessing) {
810         /* Illegal expression in PP mode */
811         Error ("Preprocessor expression expected");
812         lval->e_flags = E_MCONST;
813         lval->e_tptr = type_int;
814         return 0;
815     }
816
817     /* Identifier? */
818     if (curtok == TOK_IDENT) {
819
820         SymEntry* Sym;
821         ident Ident;
822
823         /* Get a pointer to the symbol table entry */
824         Sym = FindSym (CurTok.Ident);
825
826         /* Is the symbol known? */
827         if (Sym) {
828
829             /* We found the symbol - skip the name token */
830             NextToken ();
831
832             /* The expression type is the symbol type */
833             lval->e_tptr = Sym->Type;
834
835             /* Check for illegal symbol types */
836             CHECK ((Sym->Flags & SC_LABEL) != SC_LABEL);
837             if (Sym->Flags & SC_TYPE) {
838                 /* Cannot use type symbols */
839                 Error ("Variable identifier expected");
840                 /* Assume an int type to make lval valid */
841                 lval->e_flags = E_MLOCAL | E_TLOFFS;
842                 lval->e_tptr = type_int;
843                 lval->e_const = 0;
844                 return 0;
845             }
846
847             /* Check for legal symbol types */
848             if ((Sym->Flags & SC_CONST) == SC_CONST) {
849                 /* Enum or some other numeric constant */
850                 lval->e_flags = E_MCONST;
851                 lval->e_const = Sym->V.ConstVal;
852                 return 0;
853             } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
854                 /* Function */
855                 lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
856                 lval->e_name = (unsigned long) Sym->Name;
857                 lval->e_const = 0;
858             } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
859                 /* Local variable. If this is a parameter for a variadic
860                  * function, we have to add some address calculations, and the
861                  * address is not const.
862                  */
863                 if ((Sym->Flags & SC_PARAM) == SC_PARAM && IsVariadic (CurrentFunc)) {
864                     /* Variadic parameter */
865                     g_leavariadic (Sym->V.Offs - GetParamSize (CurrentFunc));
866                     lval->e_flags = E_MEXPR;
867                     lval->e_const = 0;
868                 } else {
869                     /* Normal parameter */
870                     lval->e_flags = E_MLOCAL | E_TLOFFS;
871                     lval->e_const = Sym->V.Offs;
872                 }
873             } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
874                 /* Static variable */
875                 if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) {
876                     lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
877                     lval->e_name = (unsigned long) Sym->Name;
878                 } else {
879                     lval->e_flags = E_MGLOBAL | E_MCONST | E_TLLAB;
880                     lval->e_name = Sym->V.Label;
881                 }
882                 lval->e_const = 0;
883             } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) {
884                 /* Register variable, zero page based */
885                 lval->e_flags = E_MGLOBAL | E_MCONST | E_TREGISTER;
886                 lval->e_name  = Sym->V.Offs;
887                 lval->e_const = 0;
888             } else {
889                 /* Local static variable */
890                 lval->e_flags = E_MGLOBAL | E_MCONST | E_TLLAB;
891                 lval->e_name  = Sym->V.Offs;
892                 lval->e_const = 0;
893             }
894
895             /* The symbol is referenced now */
896             Sym->Flags |= SC_REF;
897             if (IsTypeFunc (lval->e_tptr) || IsTypeArray (lval->e_tptr)) {
898                 return 0;
899             }
900             return 1;
901         }
902
903         /* We did not find the symbol. Remember the name, then skip it */
904         strcpy (Ident, CurTok.Ident);
905         NextToken ();
906
907         /* IDENT is either an auto-declared function or an undefined variable. */
908         if (curtok == TOK_LPAREN) {
909             /* Declare a function returning int. For that purpose, prepare a
910              * function signature for a function having an empty param list
911              * and returning int.
912              */
913             Warning ("Function call without a prototype");
914             Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
915             lval->e_tptr  = Sym->Type;
916             lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
917             lval->e_name  = (unsigned long) Sym->Name;
918             lval->e_const = 0;
919             return 0;
920
921         } else {
922
923             /* Undeclared Variable */
924             Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
925             lval->e_flags = E_MLOCAL | E_TLOFFS;
926             lval->e_tptr = type_int;
927             lval->e_const = 0;
928             Error ("Undefined symbol: `%s'", Ident);
929             return 1;
930
931         }
932     }
933
934     /* String literal? */
935     if (curtok == TOK_SCONST) {
936         lval->e_flags = E_MCONST | E_TLIT;
937         lval->e_const = curval;
938         lval->e_tptr  = GetCharArrayType (strlen (GetLiteral (curval)));
939         NextToken ();
940         return 0;
941     }
942
943     /* ASM statement? */
944     if (curtok == TOK_ASM) {
945         doasm ();
946         lval->e_tptr  = type_void;
947         lval->e_flags = E_MEXPR;
948         lval->e_const = 0;
949         return 0;
950     }
951
952     /* __AX__ and __EAX__ pseudo values? */
953     if (curtok == TOK_AX || curtok == TOK_EAX) {
954         lval->e_tptr  = (curtok == TOK_AX)? type_uint : type_ulong;
955         lval->e_flags = E_MREG;
956         lval->e_test &= ~E_CC;
957         lval->e_const = 0;
958         NextToken ();
959         return 1;               /* May be used as lvalue */
960     }
961
962     /* Illegal primary. */
963     Error ("Expression expected");
964     lval->e_flags = E_MCONST;
965     lval->e_tptr = type_int;
966     return 0;
967 }
968
969
970
971 static int arrayref (int k, struct expent* lval)
972 /* Handle an array reference */
973 {
974     unsigned lflags;
975     unsigned rflags;
976     int ConstBaseAddr;
977     int ConstSubAddr;
978     int l;
979     struct expent lval2;
980     CodeMark Mark1;
981     CodeMark Mark2;
982     type* tptr1;
983     type* tptr2;
984
985
986     /* Skip the bracket */
987     NextToken ();
988
989     /* Get the type of left side */
990     tptr1 = lval->e_tptr;
991
992     /* We can apply a special treatment for arrays that have a const base
993      * address. This is true for most arrays and will produce a lot better
994      * code. Check if this is a const base address.
995      */
996     lflags = lval->e_flags & ~E_MCTYPE;
997     ConstBaseAddr = (lflags == E_MCONST)       || /* Constant numeric address */
998                      (lflags & E_MGLOBAL) != 0 || /* Static array, or ... */
999                      lflags == E_MLOCAL;          /* Local array */
1000
1001     /* If we have a constant base, we delay the address fetch */
1002     Mark1 = GetCodePos ();
1003     Mark2 = 0;          /* Silence gcc */
1004     if (!ConstBaseAddr) {
1005         /* Get a pointer to the array into the primary */
1006         exprhs (CF_NONE, k, lval);
1007
1008         /* Get the array pointer on stack. Do not push more than 16
1009          * bit, even if this value is greater, since we cannot handle
1010          * other than 16bit stuff when doing indexing.
1011          */
1012         Mark2 = GetCodePos ();
1013         g_push (CF_PTR, 0);
1014     }
1015
1016     /* TOS now contains ptr to array elements. Get the subscript. */
1017     l = hie0 (&lval2);
1018     if (l == 0 && lval2.e_flags == E_MCONST) {
1019
1020         /* The array subscript is a constant - remove value from stack */
1021         if (!ConstBaseAddr) {
1022             RemoveCode (Mark2);
1023             pop (CF_PTR);
1024         } else {
1025             /* Get an array pointer into the primary */
1026             exprhs (CF_NONE, k, lval);
1027         }
1028
1029         if (IsClassPtr (tptr1)) {
1030
1031             /* Scale the subscript value according to element size */
1032             lval2.e_const *= PSizeOf (tptr1);
1033
1034             /* Remove code for lhs load */
1035             RemoveCode (Mark1);
1036
1037             /* Handle constant base array on stack. Be sure NOT to
1038              * handle pointers the same way, this won't work.
1039              */
1040             if (IsTypeArray (tptr1) &&
1041                 ((lval->e_flags & ~E_MCTYPE) == E_MCONST ||
1042                 (lval->e_flags & ~E_MCTYPE) == E_MLOCAL ||
1043                 (lval->e_flags & E_MGLOBAL) != 0 ||
1044                 (lval->e_flags == E_MEOFFS))) {
1045                 lval->e_const += lval2.e_const;
1046
1047             } else {
1048                 /* Pointer - load into primary and remember offset */
1049                 if ((lval->e_flags & E_MEXPR) == 0 || k != 0) {
1050                     exprhs (CF_NONE, k, lval);
1051                 }
1052                 lval->e_const = lval2.e_const;
1053                 lval->e_flags = E_MEOFFS;
1054             }
1055
1056             /* Result is of element type */
1057             lval->e_tptr = Indirect (tptr1);
1058
1059             /* Done */
1060             goto end_array;
1061
1062         } else if (IsClassPtr (tptr2 = lval2.e_tptr)) {
1063             /* Subscript is pointer, get element type */
1064             lval2.e_tptr = Indirect (tptr2);
1065
1066             /* Scale the rhs value in the primary register */
1067             g_scale (TypeOf (tptr1), SizeOf (lval2.e_tptr));
1068             /* */
1069             lval->e_tptr = lval2.e_tptr;
1070         } else {
1071             Error ("Cannot subscript");
1072         }
1073
1074         /* Add the subscript. Since arrays are indexed by integers,
1075          * we will ignore the true type of the subscript here and
1076          * use always an int.
1077          */
1078         g_inc (CF_INT | CF_CONST, lval2.e_const);
1079
1080     } else {
1081
1082         /* Array subscript is not constant. Load it into the primary */
1083         Mark2 = GetCodePos ();
1084         exprhs (CF_NONE, l, &lval2);
1085
1086         tptr2 = lval2.e_tptr;
1087         if (IsClassPtr (tptr1)) {
1088
1089             /* Get the element type */
1090             lval->e_tptr = Indirect (tptr1);
1091
1092             /* Indexing is based on int's, so we will just use the integer
1093              * portion of the index (which is in (e)ax, so there's no further
1094              * action required).
1095              */
1096             g_scale (CF_INT, SizeOf (lval->e_tptr));
1097
1098         } else if (IsClassPtr (tptr2)) {
1099
1100             /* Get the element type */
1101             lval2.e_tptr = Indirect (tptr2);
1102
1103             /* Get the int value on top. If we go here, we're sure,
1104              * both values are 16 bit (the first one was truncated
1105              * if necessary and the second one is a pointer).
1106              * Note: If ConstBaseAddr is true, we don't have a value on
1107              * stack, so to "swap" both, just push the subscript.
1108              */
1109             if (ConstBaseAddr) {
1110                 g_push (CF_INT, 0);
1111                 exprhs (CF_NONE, k, lval);
1112                 ConstBaseAddr = 0;
1113             } else {
1114                 g_swap (CF_INT);
1115             }
1116
1117             /* Scale it */
1118             g_scale (TypeOf (tptr1), SizeOf (lval2.e_tptr));
1119             lval->e_tptr = lval2.e_tptr;
1120         } else {
1121             Error ("Cannot subscript");
1122         }
1123
1124         /* The offset is now in the primary register. It didn't have a
1125          * constant base address for the lhs, the lhs address is already
1126          * on stack, and we must add the offset. If the base address was
1127          * constant, we call special functions to add the address to the
1128          * offset value.
1129          */
1130         if (!ConstBaseAddr) {
1131             /* Add the subscript. Both values are int sized. */
1132             g_add (CF_INT, 0);
1133         } else {
1134
1135             /* If the subscript has itself a constant address, it is often
1136              * a better idea to reverse again the order of the evaluation.
1137              * This will generate better code if the subscript is a byte
1138              * sized variable. But beware: This is only possible if the
1139              * subscript was not scaled, that is, if this was a byte array
1140              * or pointer.
1141              */
1142             rflags = lval2.e_flags & ~E_MCTYPE;
1143             ConstSubAddr = (rflags == E_MCONST)       || /* Constant numeric address */
1144                             (rflags & E_MGLOBAL) != 0 || /* Static array, or ... */
1145                             rflags == E_MLOCAL;          /* Local array */
1146
1147             if (ConstSubAddr && SizeOf (lval->e_tptr) == 1) {
1148
1149                 type* SavedType;
1150
1151                 /* Reverse the order of evaluation */
1152                 unsigned flags = (SizeOf (lval2.e_tptr) == 1)? CF_CHAR : CF_INT;
1153                 RemoveCode (Mark2);
1154
1155                 /* Get a pointer to the array into the primary. We have changed
1156                  * e_tptr above but we need the original type to load the
1157                  * address, so restore it temporarily.
1158                  */
1159                 SavedType = lval->e_tptr;
1160                 lval->e_tptr = tptr1;
1161                 exprhs (CF_NONE, k, lval);
1162                 lval->e_tptr = SavedType;
1163
1164                 /* Add the variable */
1165                 if (rflags == E_MLOCAL) {
1166                     g_addlocal (flags, lval2.e_const);
1167                 } else {
1168                     flags |= GlobalModeFlags (lval2.e_flags);
1169                     g_addstatic (flags, lval2.e_name, lval2.e_const);
1170                 }
1171             } else {
1172                 if (lflags == E_MCONST) {
1173                     /* Constant numeric address. Just add it */
1174                     g_inc (CF_INT | CF_UNSIGNED, lval->e_const);
1175                 } else if (lflags == E_MLOCAL) {
1176                     /* Base address is a local variable address */
1177                     if (IsTypeArray (tptr1)) {
1178                         g_addaddr_local (CF_INT, lval->e_const);
1179                     } else {
1180                         g_addlocal (CF_PTR, lval->e_const);
1181                     }
1182                 } else {
1183                     /* Base address is a static variable address */
1184                     unsigned flags = CF_INT;
1185                     flags |= GlobalModeFlags (lval->e_flags);
1186                     if (IsTypeArray (tptr1)) {
1187                         g_addaddr_static (flags, lval->e_name, lval->e_const);
1188                     } else {
1189                         g_addstatic (flags, lval->e_name, lval->e_const);
1190                     }
1191                 }
1192             }
1193         }
1194     }
1195     lval->e_flags = E_MEXPR;
1196 end_array:
1197     ConsumeRBrack ();
1198     return !IsTypeArray (lval->e_tptr);
1199
1200 }
1201
1202
1203
1204 static int structref (int k, struct expent* lval)
1205 /* Process struct field after . or ->. */
1206 {
1207     ident Ident;
1208     SymEntry* Field;
1209     int flags;
1210
1211     /* Skip the token and check for an identifier */
1212     NextToken ();
1213     if (curtok != TOK_IDENT) {
1214         Error ("Identifier expected");
1215         lval->e_tptr = type_int;
1216         return 0;
1217     }
1218
1219     /* Get the symbol table entry and check for a struct field */
1220     strcpy (Ident, CurTok.Ident);
1221     NextToken ();
1222     Field = FindStructField (lval->e_tptr, Ident);
1223     if (Field == 0) {
1224         Error ("Struct/union has no field named `%s'", Ident);
1225         lval->e_tptr = type_int;
1226         return 0;
1227     }
1228
1229     /* If we have constant input data, the result is also constant */
1230     flags = lval->e_flags & ~E_MCTYPE;
1231     if (flags == E_MCONST ||
1232         (k == 0 && (flags == E_MLOCAL ||
1233                     (flags & E_MGLOBAL) != 0 ||
1234                     lval->e_flags  == E_MEOFFS))) {
1235         lval->e_const += Field->V.Offs;
1236     } else {
1237         if ((flags & E_MEXPR) == 0 || k != 0) {
1238             exprhs (CF_NONE, k, lval);
1239         }
1240         lval->e_const = Field->V.Offs;
1241         lval->e_flags = E_MEOFFS;
1242     }
1243     lval->e_tptr = Field->Type;
1244     return !IsTypeArray (Field->Type);
1245 }
1246
1247
1248
1249 static int hie11 (struct expent *lval)
1250 /* Handle compound types (structs and arrays) */
1251 {
1252     int k;
1253     type* tptr;
1254
1255
1256     k = primary (lval);
1257     if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) {
1258         /* Not for us */
1259         return k;
1260     }
1261
1262     while (1) {
1263
1264         if (curtok == TOK_LBRACK) {
1265
1266             /* Array reference */
1267             k = arrayref (k, lval);
1268
1269         } else if (curtok == TOK_LPAREN) {
1270
1271             /* Function call. Skip the opening parenthesis */
1272             NextToken ();
1273             tptr = lval->e_tptr;
1274             if (IsTypeFunc (tptr) || IsTypeFuncPtr (tptr)) {
1275                 if (IsTypeFuncPtr (tptr)) {
1276                     /* Pointer to function. Handle transparently */
1277                     exprhs (CF_NONE, k, lval);  /* Function pointer to A/X */
1278                     ++lval->e_tptr;             /* Skip T_PTR */
1279                     lval->e_flags |= E_MEXPR;
1280                 }
1281                 CallFunction (lval);
1282                 lval->e_flags = E_MEXPR;
1283                 lval->e_tptr += DECODE_SIZE + 1;        /* Set to result */
1284             } else {
1285                 Error ("Illegal function call");
1286             }
1287             k = 0;
1288
1289         } else if (curtok == TOK_DOT) {
1290
1291             if (!IsClassStruct (lval->e_tptr)) {
1292                 Error ("Struct expected");
1293             }
1294             k = structref (0, lval);
1295
1296         } else if (curtok == TOK_PTR_REF) {
1297
1298             tptr = lval->e_tptr;
1299             if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
1300                 Error ("Struct pointer expected");
1301             }
1302             k = structref (k, lval);
1303
1304         } else {
1305             return k;
1306         }
1307     }
1308 }
1309
1310
1311
1312 static void store (struct expent* lval)
1313 /* Store primary reg into this reference */
1314 {
1315     int f;
1316     unsigned flags;
1317
1318     f = lval->e_flags;
1319     flags = TypeOf (lval->e_tptr);
1320     if (f & E_MGLOBAL) {
1321         flags |= GlobalModeFlags (f);
1322         if (lval->e_test) {
1323             /* Just testing */
1324             flags |= CF_TEST;
1325         }
1326
1327         /* Generate code */
1328         g_putstatic (flags, lval->e_name, lval->e_const);
1329
1330     } else if (f & E_MLOCAL) {
1331         g_putlocal (flags, lval->e_const, 0);
1332     } else if (f == E_MEOFFS) {
1333         g_putind (flags, lval->e_const);
1334     } else if (f != E_MREG) {
1335         if (f & E_MEXPR) {
1336             g_putind (flags, 0);
1337         } else {
1338             /* Store into absolute address */
1339             g_putstatic (flags | CF_ABSOLUTE, lval->e_const, 0);
1340         }
1341     }
1342
1343     /* Assume that each one of the stores will invalidate CC */
1344     lval->e_test &= ~E_CC;
1345 }
1346
1347
1348
1349 static void pre_incdec (struct expent* lval, void (*inc) (unsigned, unsigned long))
1350 /* Handle --i and ++i */
1351 {
1352     int k;
1353     unsigned flags;
1354     unsigned long val;
1355
1356     NextToken ();
1357     if ((k = hie10 (lval)) == 0) {
1358         Error ("Invalid lvalue");
1359         return;
1360     }
1361
1362     /* Get the data type */
1363     flags = TypeOf (lval->e_tptr) | CF_FORCECHAR | CF_CONST;
1364
1365     /* Get the increment value in bytes */
1366     val = (lval->e_tptr [0] == T_PTR)? PSizeOf (lval->e_tptr) : 1;
1367
1368     /* We're currently only able to handle some adressing modes */
1369     if ((lval->e_flags & E_MGLOBAL) == 0 &&     /* Global address? */
1370         (lval->e_flags & E_MLOCAL) == 0  &&     /* Local address? */
1371         (lval->e_flags & E_MCONST) == 0  &&     /* Constant address? */
1372         (lval->e_flags & E_MEXPR) == 0) {       /* Address in a/x? */
1373
1374         /* Use generic code. Push the address if needed */
1375         PushAddr (lval);
1376
1377         /* Fetch the value */
1378         exprhs (CF_NONE, k, lval);
1379
1380         /* Increment value in primary */
1381         inc (flags, val);
1382
1383         /* Store the result back */
1384         store (lval);
1385
1386     } else {
1387
1388         /* Special code for some addressing modes - use the special += ops */
1389         if (lval->e_flags & E_MGLOBAL) {
1390             flags |= GlobalModeFlags (lval->e_flags);
1391             if (inc == g_inc) {
1392                 g_addeqstatic (flags, lval->e_name, lval->e_const, val);
1393             } else {
1394                 g_subeqstatic (flags, lval->e_name, lval->e_const, val);
1395             }
1396         } else if (lval->e_flags & E_MLOCAL) {
1397             /* ref to localvar */
1398             if (inc == g_inc) {
1399                 g_addeqlocal (flags, lval->e_const, val);
1400             } else {
1401                 g_subeqlocal (flags, lval->e_const, val);
1402             }
1403         } else if (lval->e_flags & E_MCONST) {
1404             /* ref to absolute address */
1405             flags |= CF_ABSOLUTE;
1406             if (inc == g_inc) {
1407                 g_addeqstatic (flags, lval->e_const, 0, val);
1408             } else {
1409                 g_subeqstatic (flags, lval->e_const, 0, val);
1410             }
1411         } else if (lval->e_flags & E_MEXPR) {
1412             /* Address in a/x, check if we have an offset */
1413             unsigned Offs = (lval->e_flags == E_MEOFFS)? lval->e_const : 0;
1414             if (inc == g_inc) {
1415                 g_addeqind (flags, Offs, val);
1416             } else {
1417                 g_subeqind (flags, Offs, val);
1418             }
1419         } else {
1420             Internal ("Invalid addressing mode");
1421         }
1422
1423     }
1424
1425     /* Result is an expression */
1426     lval->e_flags = E_MEXPR;
1427 }
1428
1429
1430
1431 static void post_incdec (struct expent *lval, int k, void (*inc) (unsigned, unsigned long))
1432 /* Handle i-- and i++ */
1433 {
1434     unsigned flags;
1435
1436     NextToken ();
1437     if (k == 0) {
1438         Error ("Invalid lvalue");
1439         return;
1440     }
1441
1442     /* Get the data type */
1443     flags = TypeOf (lval->e_tptr);
1444
1445     /* Push the address if needed */
1446     PushAddr (lval);
1447
1448     /* Fetch the value and save it (since it's the result of the expression) */
1449     exprhs (CF_NONE, 1, lval);
1450     g_save (flags | CF_FORCECHAR);
1451
1452     /* If we have a pointer expression, increment by the size of the type */
1453     if (lval->e_tptr[0] == T_PTR) {
1454         inc (flags | CF_CONST | CF_FORCECHAR, SizeOf (lval->e_tptr + 1));
1455     } else {
1456         inc (flags | CF_CONST | CF_FORCECHAR, 1);
1457     }
1458
1459     /* Store the result back */
1460     store (lval);
1461
1462     /* Restore the original value */
1463     g_restore (flags | CF_FORCECHAR);
1464     lval->e_flags = E_MEXPR;
1465 }
1466
1467
1468
1469 static void unaryop (int tok, struct expent* lval)
1470 /* Handle unary -/+ and ~ */
1471 {
1472     int k;
1473     unsigned flags;
1474
1475     NextToken ();
1476     k = hie10 (lval);
1477     if (k == 0 && lval->e_flags & E_MCONST) {
1478         /* Value is constant */
1479         switch (tok) {
1480             case TOK_MINUS: lval->e_const =     -lval->e_const; break;
1481             case TOK_PLUS:                                      break;
1482             case TOK_COMP:  lval->e_const = ~lval->e_const;     break;
1483             default:        Internal ("Unexpected token: %d", tok);
1484         }
1485     } else {
1486         /* Value is not constant */
1487         exprhs (CF_NONE, k, lval);
1488
1489         /* Get the type of the expression */
1490         flags = TypeOf (lval->e_tptr);
1491
1492         /* Handle the operation */
1493         switch (tok) {
1494             case TOK_MINUS: g_neg (flags);  break;
1495             case TOK_PLUS:                  break;
1496             case TOK_COMP:  g_com (flags);  break;
1497             default:    Internal ("Unexpected token: %d", tok);
1498         }
1499         lval->e_flags = E_MEXPR;
1500     }
1501 }
1502
1503
1504
1505 static int typecast (struct expent* lval)
1506 /* Handle an explicit cast */
1507 {
1508     int k;
1509     type Type[MAXTYPELEN];
1510
1511     /* Skip the left paren */
1512     NextToken ();
1513
1514     /* Read the type */
1515     ParseType (Type);
1516
1517     /* Closing paren */
1518     ConsumeRParen ();
1519
1520     /* Read the expression we have to cast */
1521     k = hie10 (lval);
1522
1523     /* If the expression is a function, treat it as pointer-to-function */
1524     if (IsTypeFunc (lval->e_tptr)) {
1525         lval->e_tptr = PointerTo (lval->e_tptr);
1526     }
1527
1528     /* Check for a constant on the right side */
1529     if (k == 0 && lval->e_flags == E_MCONST) {
1530
1531         /* A cast of a constant to something else. If the new type is an int,
1532          * be sure to handle the size extension correctly. If the new type is
1533          * not an int, the cast is implementation specific anyway, so leave
1534          * the value alone.
1535          */
1536         if (IsClassInt (Type)) {
1537
1538             /* Get the current and new size of the value */
1539             unsigned OldSize = SizeOf (lval->e_tptr);
1540             unsigned NewSize = SizeOf (Type);
1541             unsigned OldBits = OldSize * 8;
1542             unsigned NewBits = NewSize * 8;
1543
1544             /* Check if the new datatype will have a smaller range */
1545             if (NewSize < OldSize) {
1546
1547                 /* Cut the value to the new size */
1548                 lval->e_const &= (0xFFFFFFFFUL >> (32 - NewBits));
1549
1550                 /* If the new value is signed, sign extend the value */
1551                 if (!IsSignUnsigned (Type)) {
1552                     lval->e_const |= ((~0L) << NewBits);
1553                 }
1554
1555             } else if (NewSize > OldSize) {
1556
1557                 /* Sign extend the value if needed */
1558                 if (!IsSignUnsigned (Type) && !IsSignUnsigned (lval->e_tptr)) {
1559                     if (lval->e_const & (0x01UL << (OldBits-1))) {
1560                         lval->e_const |= ((~0L) << OldBits);
1561                     }
1562                 }
1563             }
1564         }
1565
1566     } else {
1567
1568         /* Not a constant. Be sure to ignore casts to void */
1569         if (!IsTypeVoid (Type)) {
1570
1571             /* If the size does not change, leave the value alone. Otherwise,
1572              * we have to load the value into the primary and generate code to
1573              * cast the value in the primary register.
1574              */
1575             if (SizeOf (Type) != SizeOf (lval->e_tptr)) {
1576
1577                 /* Load the value into the primary */
1578                 exprhs (CF_NONE, k, lval);
1579
1580                 /* Mark the lhs as const to avoid a manipulation of TOS */
1581                 g_typecast (TypeOf (Type) | CF_CONST, TypeOf (lval->e_tptr));
1582
1583                 /* Value is now in primary */
1584                 lval->e_flags = E_MEXPR;
1585                 k = 0;
1586             }
1587         }
1588     }
1589
1590     /* In any case, use the new type */
1591     lval->e_tptr = TypeDup (Type);
1592
1593     /* Done */
1594     return k;
1595 }
1596
1597
1598
1599 static int hie10 (struct expent* lval)
1600 /* Handle ++, --, !, unary - etc. */
1601 {
1602     int k;
1603     type* t;
1604
1605     switch (curtok) {
1606
1607         case TOK_INC:
1608             pre_incdec (lval, g_inc);
1609             return 0;
1610
1611         case TOK_DEC:
1612             pre_incdec (lval, g_dec);
1613             return 0;
1614
1615         case TOK_PLUS:
1616         case TOK_MINUS:
1617         case TOK_COMP:
1618             unaryop (curtok, lval);
1619             return 0;
1620
1621         case TOK_BOOL_NOT:
1622             NextToken ();
1623             if (evalexpr (CF_NONE, hie10, lval) == 0) {
1624                 /* Constant expression */
1625                 lval->e_const = !lval->e_const;
1626             } else {
1627                 g_bneg (TypeOf (lval->e_tptr));
1628                 lval->e_test |= E_CC;                   /* bneg will set cc */
1629                 lval->e_flags = E_MEXPR;                /* say it's an expr */
1630             }
1631             return 0;                           /* expr not storable */
1632
1633         case TOK_STAR:
1634             NextToken ();
1635             if (evalexpr (CF_NONE, hie10, lval) != 0) {
1636                 /* Expression is not const, indirect value loaded into primary */
1637                 lval->e_flags = E_MEXPR;
1638                 lval->e_const = 0;              /* Offset is zero now */
1639             }
1640             t = lval->e_tptr;
1641             if (IsClassPtr (t)) {
1642                 lval->e_tptr = Indirect (t);
1643             } else {
1644                 Error ("Illegal indirection");
1645             }
1646             return 1;
1647
1648         case TOK_AND:
1649             NextToken ();
1650             k = hie10 (lval);
1651             /* The & operator may be applied to any lvalue, and it may be
1652              * applied to functions, even if they're no lvalues.
1653              */
1654             if (k == 0 && !IsTypeFunc (lval->e_tptr)) {
1655                 /* Allow the & operator with an array */
1656                 if (!IsTypeArray (lval->e_tptr)) {
1657                     Error ("Illegal address");
1658                 }
1659             } else {
1660                 t = TypeAlloc (TypeLen (lval->e_tptr) + 2);
1661                 t [0] = T_PTR;
1662                 TypeCpy (t + 1, lval->e_tptr);
1663                 lval->e_tptr = t;
1664             }
1665             return 0;
1666
1667         case TOK_SIZEOF:
1668             NextToken ();
1669             if (istypeexpr ()) {
1670                 type Type[MAXTYPELEN];
1671                 NextToken ();
1672                 lval->e_const = SizeOf (ParseType (Type));
1673                 ConsumeRParen ();
1674             } else {
1675                 /* Remember the output queue pointer */
1676                 CodeMark Mark = GetCodePos ();
1677                 hie10 (lval);
1678                 lval->e_const = SizeOf (lval->e_tptr);
1679                 /* Remove any generated code */
1680                 RemoveCode (Mark);
1681             }
1682             lval->e_flags = E_MCONST | E_TCONST;
1683             lval->e_tptr = type_uint;
1684             lval->e_test &= ~E_CC;
1685             return 0;
1686
1687         default:
1688             if (istypeexpr ()) {
1689                 /* A cast */
1690                 return typecast (lval);
1691             }
1692     }
1693
1694     k = hie11 (lval);
1695     switch (curtok) {
1696         case TOK_INC:
1697             post_incdec (lval, k, g_inc);
1698             return 0;
1699
1700         case TOK_DEC:
1701             post_incdec (lval, k, g_dec);
1702             return 0;
1703
1704         default:
1705             return k;
1706     }
1707 }
1708
1709
1710
1711 static int hie_internal (GenDesc** ops,         /* List of generators */
1712                          struct expent* lval,   /* parent expr's lval */
1713                          int (*hienext) (struct expent*),
1714                          int* UsedGen)          /* next higher level */
1715 /* Helper function */
1716 {
1717     int k;
1718     struct expent lval2;
1719     CodeMark Mark1;
1720     CodeMark Mark2;
1721     GenDesc* Gen;
1722     token_t tok;                        /* The operator token */
1723     unsigned ltype, type;
1724     int rconst;                         /* Operand is a constant */
1725
1726
1727     k = hienext (lval);
1728
1729     *UsedGen = 0;
1730     while ((Gen = FindGen (curtok, ops)) != 0) {
1731
1732         /* Tell the caller that we handled it's ops */
1733         *UsedGen = 1;
1734
1735         /* All operators that call this function expect an int on the lhs */
1736         if (!IsClassInt (lval->e_tptr)) {
1737             Error ("Integer expression expected");
1738         }
1739
1740         /* Remember the operator token, then skip it */
1741         tok = curtok;
1742         NextToken ();
1743
1744         /* Get the lhs on stack */
1745         Mark1 = GetCodePos ();
1746         ltype = TypeOf (lval->e_tptr);
1747         if (k == 0 && lval->e_flags == E_MCONST) {
1748             /* Constant value */
1749             Mark2 = GetCodePos ();
1750             g_push (ltype | CF_CONST, lval->e_const);
1751         } else {
1752             /* Value not constant */
1753             exprhs (CF_NONE, k, lval);
1754             Mark2 = GetCodePos ();
1755             g_push (ltype, 0);
1756         }
1757
1758         /* Get the right hand side */
1759         rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
1760
1761         /* Check the type of the rhs */
1762         if (!IsClassInt (lval2.e_tptr)) {
1763             Error ("Integer expression expected");
1764         }
1765
1766         /* Check for const operands */
1767         if (k == 0 && lval->e_flags == E_MCONST && rconst) {
1768
1769             /* Both operands are constant, remove the generated code */
1770             RemoveCode (Mark1);
1771             pop (ltype);
1772
1773             /* Evaluate the result */
1774             lval->e_const = kcalc (tok, lval->e_const, lval2.e_const);
1775
1776             /* Get the type of the result */
1777             lval->e_tptr = promoteint (lval->e_tptr, lval2.e_tptr);
1778
1779         } else {
1780
1781             /* If the right hand side is constant, and the generator function
1782              * expects the lhs in the primary, remove the push of the primary
1783              * now.
1784              */
1785             unsigned rtype = TypeOf (lval2.e_tptr);
1786             type = 0;
1787             if (rconst) {
1788                 /* Second value is constant - check for div */
1789                 type |= CF_CONST;
1790                 rtype |= CF_CONST;
1791                 if (tok == TOK_DIV && lval2.e_const == 0) {
1792                     Error ("Division by zero");
1793                 } else if (tok == TOK_MOD && lval2.e_const == 0) {
1794                     Error ("Modulo operation with zero");
1795                 }
1796                 if ((Gen->Flags & GEN_NOPUSH) != 0) {
1797                     RemoveCode (Mark2);
1798                     pop (ltype);
1799                     ltype |= CF_REG;    /* Value is in register */
1800                 }
1801             }
1802
1803             /* Determine the type of the operation result. */
1804             type |= g_typeadjust (ltype, rtype);
1805             lval->e_tptr = promoteint (lval->e_tptr, lval2.e_tptr);
1806
1807             /* Generate code */
1808             Gen->Func (type, lval2.e_const);
1809             lval->e_flags = E_MEXPR;
1810         }
1811
1812         /* We have a rvalue now */
1813         k = 0;
1814     }
1815
1816     return k;
1817 }
1818
1819
1820
1821 static int hie_compare (GenDesc** ops,          /* List of generators */
1822                         struct expent* lval,    /* parent expr's lval */
1823                         int (*hienext) (struct expent*))
1824 /* Helper function for the compare operators */
1825 {
1826     int k;
1827     struct expent lval2;
1828     CodeMark Mark1;
1829     CodeMark Mark2;
1830     GenDesc* Gen;
1831     token_t tok;                        /* The operator token */
1832     unsigned ltype;
1833     int rconst;                         /* Operand is a constant */
1834
1835
1836     k = hienext (lval);
1837
1838     while ((Gen = FindGen (curtok, ops)) != 0) {
1839
1840         /* Remember the operator token, then skip it */
1841         tok = curtok;
1842         NextToken ();
1843
1844         /* Get the lhs on stack */
1845         Mark1 = GetCodePos ();
1846         ltype = TypeOf (lval->e_tptr);
1847         if (k == 0 && lval->e_flags == E_MCONST) {
1848             /* Constant value */
1849             Mark2 = GetCodePos ();
1850             g_push (ltype | CF_CONST, lval->e_const);
1851         } else {
1852             /* Value not constant */
1853             exprhs (CF_NONE, k, lval);
1854             Mark2 = GetCodePos ();
1855             g_push (ltype, 0);
1856         }
1857
1858         /* Get the right hand side */
1859         rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
1860
1861         /* Make sure, the types are compatible */
1862         if (IsClassInt (lval->e_tptr)) {
1863             if (!IsClassInt (lval2.e_tptr) && !(IsClassPtr(lval2.e_tptr) && IsNullPtr(lval))) {
1864                 Error ("Incompatible types");
1865             }
1866         } else if (IsClassPtr (lval->e_tptr)) {
1867             if (IsClassPtr (lval2.e_tptr)) {
1868                 /* Both pointers are allowed in comparison if they point to
1869                  * the same type, or if one of them is a void pointer.
1870                  */
1871                 type* left  = Indirect (lval->e_tptr);
1872                 type* right = Indirect (lval2.e_tptr);
1873                 if (TypeCmp (left, right) < TC_EQUAL && *left != T_VOID && *right != T_VOID) {
1874                     /* Incomatible pointers */
1875                     Error ("Incompatible types");
1876                 }
1877             } else if (!IsNullPtr (&lval2)) {
1878                 Error ("Incompatible types");
1879             }
1880         }
1881
1882         /* Check for const operands */
1883         if (k == 0 && lval->e_flags == E_MCONST && rconst) {
1884
1885             /* Both operands are constant, remove the generated code */
1886             RemoveCode (Mark1);
1887             pop (ltype);
1888
1889             /* Evaluate the result */
1890             lval->e_const = kcalc (tok, lval->e_const, lval2.e_const);
1891
1892         } else {
1893
1894             /* If the right hand side is constant, and the generator function
1895              * expects the lhs in the primary, remove the push of the primary
1896              * now.
1897              */
1898             unsigned flags = 0;
1899             if (rconst) {
1900                 flags |= CF_CONST;
1901                 if ((Gen->Flags & GEN_NOPUSH) != 0) {
1902                     RemoveCode (Mark2);
1903                     pop (ltype);
1904                     ltype |= CF_REG;    /* Value is in register */
1905                 }
1906             }
1907
1908             /* Determine the type of the operation result. If the left
1909              * operand is of type char and the right is a constant, or
1910              * if both operands are of type char, we will encode the
1911              * operation as char operation. Otherwise the default
1912              * promotions are used.
1913              */
1914             if (IsTypeChar (lval->e_tptr) && (IsTypeChar (lval2.e_tptr) || rconst)) {
1915                 flags |= CF_CHAR;
1916                 if (IsSignUnsigned (lval->e_tptr) || IsSignUnsigned (lval2.e_tptr)) {
1917                     flags |= CF_UNSIGNED;
1918                 }
1919                 if (rconst) {
1920                     flags |= CF_FORCECHAR;
1921                 }
1922             } else {
1923                 unsigned rtype = TypeOf (lval2.e_tptr) | (flags & CF_CONST);
1924                 flags |= g_typeadjust (ltype, rtype);
1925             }
1926
1927             /* Generate code */
1928             Gen->Func (flags, lval2.e_const);
1929             lval->e_flags = E_MEXPR;
1930         }
1931
1932         /* Result type is always int */
1933         lval->e_tptr = type_int;
1934
1935         /* We have a rvalue now, condition codes are set */
1936         k = 0;
1937         lval->e_test |= E_CC;
1938     }
1939
1940     return k;
1941 }
1942
1943
1944
1945 static int hie9 (struct expent *lval)
1946 /* Process * and / operators. */
1947 {
1948     static GenDesc* hie9_ops [] = {
1949         &GenMUL, &GenDIV, &GenMOD, 0
1950     };
1951     int UsedGen;
1952
1953     return hie_internal (hie9_ops, lval, hie10, &UsedGen);
1954 }
1955
1956
1957
1958 static void parseadd (int k, struct expent* lval)
1959 /* Parse an expression with the binary plus operator. lval contains the
1960  * unprocessed left hand side of the expression and will contain the
1961  * result of the expression on return.
1962  */
1963 {
1964     struct expent lval2;
1965     unsigned flags;             /* Operation flags */
1966     CodeMark Mark;              /* Remember code position */
1967     type* lhst;                 /* Type of left hand side */
1968     type* rhst;                 /* Type of right hand side */
1969
1970
1971     /* Skip the PLUS token */
1972     NextToken ();
1973
1974     /* Get the left hand side type, initialize operation flags */
1975     lhst = lval->e_tptr;
1976     flags = 0;
1977
1978     /* Check for constness on both sides */
1979     if (k == 0 && lval->e_flags == E_MCONST) {
1980
1981         /* The left hand side is a constant. Good. Get rhs */
1982         if (evalexpr (CF_NONE, hie9, &lval2) == 0) {
1983
1984             /* Right hand side is also constant. Get the rhs type */
1985             rhst = lval2.e_tptr;
1986
1987             /* Both expressions are constants. Check for pointer arithmetic */
1988             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
1989                 /* Left is pointer, right is int, must scale rhs */
1990                 lval->e_const = lval->e_const + lval2.e_const * PSizeOf (lhst);
1991                 /* Result type is a pointer */
1992             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
1993                 /* Left is int, right is pointer, must scale lhs */
1994                 lval->e_const = lval->e_const * PSizeOf (rhst) + lval2.e_const;
1995                 /* Result type is a pointer */
1996                 lval->e_tptr = lval2.e_tptr;
1997             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
1998                 /* Integer addition */
1999                 lval->e_const += lval2.e_const;
2000                 typeadjust (lval, &lval2, 1);
2001             } else {
2002                 /* OOPS */
2003                 Error ("Invalid operands for binary operator `+'");
2004             }
2005
2006             /* Result is constant, condition codes not set */
2007             lval->e_test = E_MCONST;
2008
2009         } else {
2010
2011             /* lhs is constant, rhs is not. Get the rhs type. */
2012             rhst = lval2.e_tptr;
2013
2014             /* Check for pointer arithmetic */
2015             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2016                 /* Left is pointer, right is int, must scale rhs */
2017                 g_scale (CF_INT, PSizeOf (lhst));
2018                 /* Operate on pointers, result type is a pointer */
2019                 flags = CF_PTR;
2020             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2021                 /* Left is int, right is pointer, must scale lhs */
2022                 lval->e_const *= PSizeOf (rhst);
2023                 /* Operate on pointers, result type is a pointer */
2024                 flags = CF_PTR;
2025                 lval->e_tptr = lval2.e_tptr;
2026             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2027                 /* Integer addition */
2028                 flags = typeadjust (lval, &lval2, 1);
2029             } else {
2030                 /* OOPS */
2031                 Error ("Invalid operands for binary operator `+'");
2032             }
2033
2034             /* Generate code for the add */
2035             g_inc (flags | CF_CONST, lval->e_const);
2036
2037             /* Result is in primary register */
2038             lval->e_flags = E_MEXPR;
2039             lval->e_test &= ~E_CC;
2040
2041         }
2042
2043     } else {
2044
2045         /* Left hand side is not constant. Get the value onto the stack. */
2046         exprhs (CF_NONE, k, lval);              /* --> primary register */
2047         Mark = GetCodePos ();
2048         g_push (TypeOf (lval->e_tptr), 0);      /* --> stack */
2049
2050         /* Evaluate the rhs */
2051         if (evalexpr (CF_NONE, hie9, &lval2) == 0) {
2052
2053             /* Right hand side is a constant. Get the rhs type */
2054             rhst = lval2.e_tptr;
2055
2056             /* Remove pushed value from stack */
2057             RemoveCode (Mark);
2058             pop (TypeOf (lval->e_tptr));
2059
2060             /* Check for pointer arithmetic */
2061             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2062                 /* Left is pointer, right is int, must scale rhs */
2063                 lval2.e_const *= PSizeOf (lhst);
2064                 /* Operate on pointers, result type is a pointer */
2065                 flags = CF_PTR;
2066             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2067                 /* Left is int, right is pointer, must scale lhs (ptr only) */
2068                 g_scale (CF_INT | CF_CONST, PSizeOf (rhst));
2069                 /* Operate on pointers, result type is a pointer */
2070                 flags = CF_PTR;
2071                 lval->e_tptr = lval2.e_tptr;
2072             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2073                 /* Integer addition */
2074                 flags = typeadjust (lval, &lval2, 1);
2075             } else {
2076                 /* OOPS */
2077                 Error ("Invalid operands for binary operator `+'");
2078             }
2079
2080             /* Generate code for the add */
2081             g_inc (flags | CF_CONST, lval2.e_const);
2082
2083             /* Result is in primary register */
2084             lval->e_flags = E_MEXPR;
2085             lval->e_test &= ~E_CC;
2086
2087         } else {
2088
2089             /* lhs and rhs are not constant. Get the rhs type. */
2090             rhst = lval2.e_tptr;
2091
2092             /* Check for pointer arithmetic */
2093             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2094                 /* Left is pointer, right is int, must scale rhs */
2095                 g_scale (CF_INT, PSizeOf (lhst));
2096                 /* Operate on pointers, result type is a pointer */
2097                 flags = CF_PTR;
2098             } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
2099                 /* Left is int, right is pointer, must scale lhs */
2100                 g_tosint (TypeOf (rhst));       /* Make sure, TOS is int */
2101                 g_swap (CF_INT);                /* Swap TOS and primary */
2102                 g_scale (CF_INT, PSizeOf (rhst));
2103                 /* Operate on pointers, result type is a pointer */
2104                 flags = CF_PTR;
2105                 lval->e_tptr = lval2.e_tptr;
2106             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2107                 /* Integer addition */
2108                 flags = typeadjust (lval, &lval2, 0);
2109             } else {
2110                 /* OOPS */
2111                 Error ("Invalid operands for binary operator `+'");
2112             }
2113
2114             /* Generate code for the add */
2115             g_add (flags, 0);
2116
2117             /* Result is in primary register */
2118             lval->e_flags = E_MEXPR;
2119             lval->e_test &= ~E_CC;
2120
2121         }
2122
2123     }
2124 }
2125
2126
2127
2128 static void parsesub (int k, struct expent* lval)
2129 /* Parse an expression with the binary minus operator. lval contains the
2130  * unprocessed left hand side of the expression and will contain the
2131  * result of the expression on return.
2132  */
2133 {
2134     struct expent lval2;
2135     unsigned flags;             /* Operation flags */
2136     type* lhst;                 /* Type of left hand side */
2137     type* rhst;                 /* Type of right hand side */
2138     CodeMark Mark1;             /* Save position of output queue */
2139     CodeMark Mark2;             /* Another position in the queue */
2140     int rscale;                 /* Scale factor for the result */
2141
2142
2143     /* Skip the MINUS token */
2144     NextToken ();
2145
2146     /* Get the left hand side type, initialize operation flags */
2147     lhst = lval->e_tptr;
2148     flags = 0;
2149     rscale = 1;                 /* Scale by 1, that is, don't scale */
2150
2151     /* Remember the output queue position, then bring the value onto the stack */
2152     Mark1 = GetCodePos ();
2153     exprhs (CF_NONE, k, lval);  /* --> primary register */
2154     Mark2 = GetCodePos ();
2155     g_push (TypeOf (lhst), 0);  /* --> stack */
2156
2157     /* Parse the right hand side */
2158     if (evalexpr (CF_NONE, hie9, &lval2) == 0) {
2159
2160         /* The right hand side is constant. Get the rhs type. */
2161         rhst = lval2.e_tptr;
2162
2163         /* Check left hand side */
2164         if (k == 0 && lval->e_flags & E_MCONST) {
2165
2166             /* Both sides are constant, remove generated code */
2167             RemoveCode (Mark1);
2168             pop (TypeOf (lhst));        /* Clean up the stack */
2169
2170             /* Check for pointer arithmetic */
2171             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2172                 /* Left is pointer, right is int, must scale rhs */
2173                 lval->e_const -= lval2.e_const * PSizeOf (lhst);
2174                 /* Operate on pointers, result type is a pointer */
2175             } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
2176                 /* Left is pointer, right is pointer, must scale result */
2177                 if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
2178                     Error ("Incompatible pointer types");
2179                 } else {
2180                     lval->e_const = (lval->e_const - lval2.e_const) / PSizeOf (lhst);
2181                 }
2182                 /* Operate on pointers, result type is an integer */
2183                 lval->e_tptr = type_int;
2184             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2185                 /* Integer subtraction */
2186                 typeadjust (lval, &lval2, 1);
2187                 lval->e_const -= lval2.e_const;
2188             } else {
2189                 /* OOPS */
2190                 Error ("Invalid operands for binary operator `-'");
2191             }
2192
2193             /* Result is constant, condition codes not set */
2194             lval->e_flags = E_MCONST;
2195             lval->e_test &= ~E_CC;
2196
2197         } else {
2198
2199             /* Left hand side is not constant, right hand side is.
2200              * Remove pushed value from stack.
2201              */
2202             RemoveCode (Mark2);
2203             pop (TypeOf (lhst));
2204
2205             if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2206                 /* Left is pointer, right is int, must scale rhs */
2207                 lval2.e_const *= PSizeOf (lhst);
2208                 /* Operate on pointers, result type is a pointer */
2209                 flags = CF_PTR;
2210             } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
2211                 /* Left is pointer, right is pointer, must scale result */
2212                 if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
2213                     Error ("Incompatible pointer types");
2214                 } else {
2215                     rscale = PSizeOf (lhst);
2216                 }
2217                 /* Operate on pointers, result type is an integer */
2218                 flags = CF_PTR;
2219                 lval->e_tptr = type_int;
2220             } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2221                 /* Integer subtraction */
2222                 flags = typeadjust (lval, &lval2, 1);
2223             } else {
2224                 /* OOPS */
2225                 Error ("Invalid operands for binary operator `-'");
2226             }
2227
2228             /* Do the subtraction */
2229             g_dec (flags | CF_CONST, lval2.e_const);
2230
2231             /* If this was a pointer subtraction, we must scale the result */
2232             if (rscale != 1) {
2233                 g_scale (flags, -rscale);
2234             }
2235
2236             /* Result is in primary register */
2237             lval->e_flags = E_MEXPR;
2238             lval->e_test &= ~E_CC;
2239
2240         }
2241
2242     } else {
2243
2244         /* Right hand side is not constant. Get the rhs type. */
2245         rhst = lval2.e_tptr;
2246
2247         /* Check for pointer arithmetic */
2248         if (IsClassPtr (lhst) && IsClassInt (rhst)) {
2249             /* Left is pointer, right is int, must scale rhs */
2250             g_scale (CF_INT, PSizeOf (lhst));
2251             /* Operate on pointers, result type is a pointer */
2252             flags = CF_PTR;
2253         } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
2254             /* Left is pointer, right is pointer, must scale result */
2255             if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
2256                 Error ("Incompatible pointer types");
2257             } else {
2258                 rscale = PSizeOf (lhst);
2259             }
2260             /* Operate on pointers, result type is an integer */
2261             flags = CF_PTR;
2262             lval->e_tptr = type_int;
2263         } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
2264             /* Integer subtraction. If the left hand side descriptor says that
2265              * the lhs is const, we have to remove this mark, since this is no
2266              * longer true, lhs is on stack instead.
2267              */
2268             if (lval->e_flags == E_MCONST) {
2269                 lval->e_flags = E_MEXPR;
2270             }
2271             /* Adjust operand types */
2272             flags = typeadjust (lval, &lval2, 0);
2273         } else {
2274             /* OOPS */
2275             Error ("Invalid operands for binary operator `-'");
2276         }
2277
2278         /* Generate code for the sub (the & is a hack here) */
2279         g_sub (flags & ~CF_CONST, 0);
2280
2281         /* If this was a pointer subtraction, we must scale the result */
2282         if (rscale != 1) {
2283             g_scale (flags, -rscale);
2284         }
2285
2286         /* Result is in primary register */
2287         lval->e_flags = E_MEXPR;
2288         lval->e_test &= ~E_CC;
2289     }
2290 }
2291
2292
2293
2294 static int hie8 (struct expent* lval)
2295 /* Process + and - binary operators. */
2296 {
2297     int k = hie9 (lval);
2298     while (curtok == TOK_PLUS || curtok == TOK_MINUS) {
2299
2300         if (curtok == TOK_PLUS) {
2301             parseadd (k, lval);
2302         } else {
2303             parsesub (k, lval);
2304         }
2305         k = 0;
2306     }
2307     return k;
2308 }
2309
2310
2311
2312
2313 static int hie7 (struct expent *lval)
2314 /* Parse << and >>. */
2315 {
2316     static GenDesc* hie7_ops [] = {
2317         &GenASL, &GenASR, 0
2318     };
2319     int UsedGen;
2320
2321     return hie_internal (hie7_ops, lval, hie8, &UsedGen);
2322 }
2323
2324
2325
2326 static int hie6 (struct expent *lval)
2327 /* process greater-than type comparators */
2328 {
2329     static GenDesc* hie6_ops [] = {
2330         &GenLT, &GenLE, &GenGE, &GenGT, 0
2331     };
2332     return hie_compare (hie6_ops, lval, hie7);
2333 }
2334
2335
2336
2337 static int hie5 (struct expent *lval)
2338 {
2339     static GenDesc* hie5_ops[] = {
2340         &GenEQ, &GenNE, 0
2341     };
2342     return hie_compare (hie5_ops, lval, hie6);
2343 }
2344
2345
2346
2347 static int hie4 (struct expent* lval)
2348 /* Handle & (bitwise and) */
2349 {
2350     static GenDesc* hie4_ops [] = {
2351         &GenAND, 0
2352     };
2353     int UsedGen;
2354
2355     return hie_internal (hie4_ops, lval, hie5, &UsedGen);
2356 }
2357
2358
2359
2360 static int hie3 (struct expent *lval)
2361 /* Handle ^ (bitwise exclusive or) */
2362 {
2363     static GenDesc* hie3_ops [] = {
2364         &GenXOR, 0
2365     };
2366     int UsedGen;
2367
2368     return hie_internal (hie3_ops, lval, hie4, &UsedGen);
2369 }
2370
2371
2372
2373 static int hie2 (struct expent *lval)
2374 /* Handle | (bitwise or) */
2375 {
2376     static GenDesc* hie2_ops [] = {
2377         &GenOR, 0
2378     };
2379     int UsedGen;
2380
2381     return hie_internal (hie2_ops, lval, hie3, &UsedGen);
2382 }
2383
2384
2385
2386 static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
2387 /* Process "exp && exp" */
2388 {
2389     int k;
2390     int lab;
2391     struct expent lval2;
2392
2393     k = hie2 (lval);
2394     if (curtok == TOK_BOOL_AND) {
2395
2396         /* Tell our caller that we're evaluating a boolean */
2397         *BoolOp = 1;
2398
2399         /* Get a label that we will use for false expressions */
2400         lab = GetLocalLabel ();
2401
2402         /* If the expr hasn't set condition codes, set the force-test flag */
2403         if ((lval->e_test & E_CC) == 0) {
2404             lval->e_test |= E_FORCETEST;
2405         }
2406
2407         /* Load the value */
2408         exprhs (CF_FORCECHAR, k, lval);
2409
2410         /* Generate the jump */
2411         g_falsejump (CF_NONE, lab);
2412
2413         /* Parse more boolean and's */
2414         while (curtok == TOK_BOOL_AND) {
2415
2416             /* Skip the && */
2417             NextToken ();
2418
2419             /* Get rhs */
2420             k = hie2 (&lval2);
2421             if ((lval2.e_test & E_CC) == 0) {
2422                 lval2.e_test |= E_FORCETEST;
2423             }
2424             exprhs (CF_FORCECHAR, k, &lval2);
2425
2426             /* Do short circuit evaluation */
2427             if (curtok == TOK_BOOL_AND) {
2428                 g_falsejump (CF_NONE, lab);
2429             } else {
2430                 /* Last expression - will evaluate to true */
2431                 g_truejump (CF_NONE, TrueLab);
2432             }
2433         }
2434
2435         /* Define the false jump label here */
2436         g_defloclabel (lab);
2437
2438         /* Define the label */
2439         lval->e_flags = E_MEXPR;
2440         lval->e_test |= E_CC;   /* Condition codes are set */
2441         k = 0;
2442     }
2443     return k;
2444 }
2445
2446
2447
2448 static int hieOr (struct expent *lval)
2449 /* Process "exp || exp". */
2450 {
2451     int k;
2452     struct expent lval2;
2453     int BoolOp = 0;             /* Did we have a boolean op? */
2454     int AndOp;                  /* Did we have a && operation? */
2455     unsigned TrueLab;           /* Jump to this label if true */
2456     unsigned DoneLab;
2457
2458     /* Get a label */
2459     TrueLab = GetLocalLabel ();
2460
2461     /* Call the next level parser */
2462     k = hieAnd (lval, TrueLab, &BoolOp);
2463
2464     /* Any boolean or's? */
2465     if (curtok == TOK_BOOL_OR) {
2466
2467         /* If the expr hasn't set condition codes, set the force-test flag */
2468         if ((lval->e_test & E_CC) == 0) {
2469             lval->e_test |= E_FORCETEST;
2470         }
2471
2472         /* Get first expr */
2473         exprhs (CF_FORCECHAR, k, lval);
2474
2475         /* For each expression jump to TrueLab if true. Beware: If we
2476          * had && operators, the jump is already in place!
2477          */
2478         if (!BoolOp) {
2479             g_truejump (CF_NONE, TrueLab);
2480         }
2481
2482         /* Remember that we had a boolean op */
2483         BoolOp = 1;
2484
2485         /* while there's more expr */
2486         while (curtok == TOK_BOOL_OR) {
2487
2488             /* skip the || */
2489             NextToken ();
2490
2491             /* Get a subexpr */
2492             AndOp = 0;
2493             k = hieAnd (&lval2, TrueLab, &AndOp);
2494             if ((lval2.e_test & E_CC) == 0) {
2495                 lval2.e_test |= E_FORCETEST;
2496             }
2497             exprhs (CF_FORCECHAR, k, &lval2);
2498
2499             /* If there is more to come, add shortcut boolean eval.
2500              * Beware: If we had && operators, the jump is already
2501              * in place!
2502              */
2503 #if     0
2504 /* Seems this sometimes generates wrong code */
2505             if (curtok == TOK_BOOL_OR && !AndOp) {
2506                 g_truejump (CF_NONE, TrueLab);
2507             }
2508 #else
2509             g_truejump (CF_NONE, TrueLab);
2510 #endif
2511         }
2512         lval->e_flags = E_MEXPR;
2513         lval->e_test |= E_CC;                   /* Condition codes are set */
2514         k = 0;
2515     }
2516
2517     /* If we really had boolean ops, generate the end sequence */
2518     if (BoolOp) {
2519         DoneLab = GetLocalLabel ();
2520         g_getimmed (CF_INT | CF_CONST, 0, 0);   /* Load FALSE */
2521         g_falsejump (CF_NONE, DoneLab);
2522         g_defloclabel (TrueLab);
2523         g_getimmed (CF_INT | CF_CONST, 1, 0);   /* Load TRUE */
2524         g_defloclabel (DoneLab);
2525     }
2526     return k;
2527 }
2528
2529
2530
2531 static int hieQuest (struct expent *lval)
2532 /* Parse "lvalue ? exp : exp" */
2533 {
2534     int k;
2535     int labf;
2536     int labt;
2537     struct expent lval2;        /* Expression 2 */
2538     struct expent lval3;        /* Expression 3 */
2539     type* type2;                /* Type of expression 2 */
2540     type* type3;                /* Type of expression 3 */
2541     type* rtype;                /* Type of result */
2542     CodeMark Mark1;             /* Save position in output code */
2543     CodeMark Mark2;             /* Save position in output code */
2544
2545
2546
2547     k = hieOr (lval);
2548     if (curtok == TOK_QUEST) {
2549         NextToken ();
2550         if ((lval->e_test & E_CC) == 0) {
2551             /* Condition codes not set, force a test */
2552             lval->e_test |= E_FORCETEST;
2553         }
2554         exprhs (CF_NONE, k, lval);
2555         labf = GetLocalLabel ();
2556         g_falsejump (CF_NONE, labf);
2557
2558         /* Parse second and third expression */
2559         expression1 (&lval2);
2560         labt = GetLocalLabel ();
2561         ConsumeColon ();
2562         g_jump (labt);
2563         g_defloclabel (labf);
2564         expression1 (&lval3);
2565
2566         /* Check if any conversions are needed, if so, do them.
2567          * Conversion rules for ?: expression are:
2568          *   - if both expressions are int expressions, default promotion
2569          *     rules for ints apply.
2570          *   - if both expressions are pointers of the same type, the
2571          *     result of the expression is of this type.
2572          *   - if one of the expressions is a pointer and the other is
2573          *     a zero constant, the resulting type is that of the pointer
2574          *     type.
2575          *   - all other cases are flagged by an error.
2576          */
2577         type2 = lval2.e_tptr;
2578         type3 = lval3.e_tptr;
2579         if (IsClassInt (type2) && IsClassInt (type3)) {
2580
2581             /* Get common type */
2582             rtype = promoteint (type2, type3);
2583
2584             /* Convert the third expression to this type if needed */
2585             g_typecast (TypeOf (rtype), TypeOf (type3));
2586
2587             /* Setup a new label so that the expr3 code will jump around
2588              * the type cast code for expr2.
2589              */
2590             labf = GetLocalLabel ();    /* Get new label */
2591             Mark1 = GetCodePos ();      /* Remember current position */
2592             g_jump (labf);              /* Jump around code */
2593
2594             /* The jump for expr2 goes here */
2595             g_defloclabel (labt);
2596
2597             /* Create the typecast code for expr2 */
2598             Mark2 = GetCodePos ();      /* Remember position */
2599             g_typecast (TypeOf (rtype), TypeOf (type2));
2600
2601             /* If the typecast did not produce code, remove the jump,
2602              * otherwise output the label.
2603              */
2604             if (GetCodePos() == Mark2) {
2605                 RemoveCode (Mark1);     /* Remove code */
2606             } else {
2607                 /* We have typecast code, output label */
2608                 g_defloclabel (labf);
2609                 labt = 0;               /* Mark other label as invalid */
2610             }
2611
2612         } else if (IsClassPtr (type2) && IsClassPtr (type3)) {
2613             /* Must point to same type */
2614             if (TypeCmp (Indirect (type2), Indirect (type3)) < TC_EQUAL) {
2615                 Error ("Incompatible pointer types");
2616             }
2617             /* Result has the common type */
2618             rtype = lval2.e_tptr;
2619         } else if (IsClassPtr (type2) && IsNullPtr (&lval3)) {
2620             /* Result type is pointer, no cast needed */
2621             rtype = lval2.e_tptr;
2622         } else if (IsNullPtr (&lval2) && IsClassPtr (type3)) {
2623             /* Result type is pointer, no cast needed */
2624             rtype = lval3.e_tptr;
2625         } else {
2626             Error ("Incompatible types");
2627             rtype = lval2.e_tptr;               /* Doesn't matter here */
2628         }
2629
2630         /* If we don't have the label defined until now, do it */
2631         if (labt) {
2632             g_defloclabel (labt);
2633         }
2634
2635         /* Setup the target expression */
2636         lval->e_flags = E_MEXPR;
2637         lval->e_tptr = rtype;
2638         k = 0;
2639     }
2640     return k;
2641 }
2642
2643
2644
2645 static void opeq (GenDesc* Gen, struct expent *lval, int k)
2646 /* Process "op=" operators. */
2647 {
2648     struct expent lval2;
2649     unsigned flags;
2650     CodeMark Mark;
2651     int MustScale;
2652
2653     NextToken ();
2654     if (k == 0) {
2655         Error ("Invalid lvalue in assignment");
2656         return;
2657     }
2658
2659     /* Determine the type of the lhs */
2660     flags = TypeOf (lval->e_tptr);
2661     MustScale = (Gen->Func == g_add || Gen->Func == g_sub) &&
2662                 lval->e_tptr [0] == T_PTR;
2663
2664     /* Get the lhs address on stack (if needed) */
2665     PushAddr (lval);
2666
2667     /* Fetch the lhs into the primary register if needed */
2668     exprhs (CF_NONE, k, lval);
2669
2670     /* Bring the lhs on stack */
2671     Mark = GetCodePos ();
2672     g_push (flags, 0);
2673
2674     /* Evaluate the rhs */
2675     if (evalexpr (CF_NONE, hie1, &lval2) == 0) {
2676         /* The resulting value is a constant. If the generator has the NOPUSH
2677          * flag set, don't push the lhs.
2678          */
2679         if (Gen->Flags & GEN_NOPUSH) {
2680             RemoveCode (Mark);
2681             pop (flags);
2682         }
2683         if (MustScale) {
2684             /* lhs is a pointer, scale rhs */
2685             lval2.e_const *= SizeOf (lval->e_tptr+1);
2686         }
2687
2688         /* If the lhs is character sized, the operation may be later done
2689          * with characters.
2690          */
2691         if (SizeOf (lval->e_tptr) == 1) {
2692             flags |= CF_FORCECHAR;
2693         }
2694
2695         /* Special handling for add and sub - some sort of a hack, but short code */
2696         if (Gen->Func == g_add) {
2697             g_inc (flags | CF_CONST, lval2.e_const);
2698         } else if (Gen->Func == g_sub) {
2699             g_dec (flags | CF_CONST, lval2.e_const);
2700         } else {
2701             Gen->Func (flags | CF_CONST, lval2.e_const);
2702         }
2703     } else {
2704         /* rhs is not constant and already in the primary register */
2705         if (MustScale) {
2706             /* lhs is a pointer, scale rhs */
2707             g_scale (TypeOf (lval2.e_tptr), SizeOf (lval->e_tptr+1));
2708         }
2709
2710         /* If the lhs is character sized, the operation may be later done
2711          * with characters.
2712          */
2713         if (SizeOf (lval->e_tptr) == 1) {
2714             flags |= CF_FORCECHAR;
2715         }
2716
2717         /* Adjust the types of the operands if needed */
2718         Gen->Func (g_typeadjust (flags, TypeOf (lval2.e_tptr)), 0);
2719     }
2720     store (lval);
2721     lval->e_flags = E_MEXPR;
2722 }
2723
2724
2725
2726 static void addsubeq (GenDesc* Gen, struct expent *lval, int k)
2727 /* Process the += and -= operators */
2728 {
2729     struct expent lval2;
2730     unsigned flags;
2731     int MustScale;
2732
2733
2734     if (k == 0) {
2735         Error ("Invalid lvalue in assignment");
2736         return;
2737     }
2738
2739
2740     /* We're currently only able to handle some adressing modes */
2741     if ((lval->e_flags & E_MGLOBAL) == 0 &&     /* Global address? */
2742         (lval->e_flags & E_MLOCAL) == 0  &&     /* Local address? */
2743         (lval->e_flags & E_MCONST) == 0) {      /* Constant address? */
2744         /* Use generic routine */
2745         opeq (Gen, lval, k);
2746         return;
2747     }
2748
2749     /* Skip the operator */
2750     NextToken ();
2751
2752     /* Check if we have a pointer expression and must scale rhs */
2753     MustScale = (lval->e_tptr [0] == T_PTR);
2754
2755     /* Determine the code generator flags */
2756     flags = TypeOf (lval->e_tptr) | CF_FORCECHAR;
2757
2758     /* Evaluate the rhs */
2759     if (evalexpr (CF_NONE, hie1, &lval2) == 0) {
2760         /* The resulting value is a constant. */
2761         if (MustScale) {
2762             /* lhs is a pointer, scale rhs */
2763             lval2.e_const *= SizeOf (lval->e_tptr+1);
2764         }
2765         flags |= CF_CONST;
2766     } else {
2767         /* rhs is not constant and already in the primary register */
2768         if (MustScale) {
2769             /* lhs is a pointer, scale rhs */
2770             g_scale (TypeOf (lval2.e_tptr), SizeOf (lval->e_tptr+1));
2771         }
2772     }
2773
2774     /* Adjust the rhs to the lhs */
2775     g_typeadjust (flags, TypeOf (lval2.e_tptr));
2776
2777     /* Output apropriate code */
2778     if (lval->e_flags & E_MGLOBAL) {
2779         /* Static variable */
2780         flags |= GlobalModeFlags (lval->e_flags);
2781         if (Gen->Tok == TOK_PLUS_ASSIGN) {
2782             g_addeqstatic (flags, lval->e_name, lval->e_const, lval2.e_const);
2783         } else {
2784             g_subeqstatic (flags, lval->e_name, lval->e_const, lval2.e_const);
2785         }
2786     } else if (lval->e_flags & E_MLOCAL) {
2787         /* ref to localvar */
2788         if (Gen->Tok == TOK_PLUS_ASSIGN) {
2789             g_addeqlocal (flags, lval->e_const, lval2.e_const);
2790         } else {
2791             g_subeqlocal (flags, lval->e_const, lval2.e_const);
2792         }
2793     } else if (lval->e_flags & E_MCONST) {
2794         /* ref to absolute address */
2795         flags |= CF_ABSOLUTE;
2796         if (Gen->Tok == TOK_PLUS_ASSIGN) {
2797             g_addeqstatic (flags, lval->e_const, 0, lval2.e_const);
2798         } else {
2799             g_subeqstatic (flags, lval->e_const, 0, lval2.e_const);
2800         }
2801     } else if (lval->e_flags & E_MEXPR) {
2802         /* Address in a/x. */
2803         if (Gen->Tok == TOK_PLUS_ASSIGN) {
2804             g_addeqind (flags, lval->e_const, lval2.e_const);
2805         } else {
2806             g_subeqind (flags, lval->e_const, lval2.e_const);
2807         }
2808     } else {
2809         Internal ("Invalid addressing mode");
2810     }
2811
2812     /* Expression is in the primary now */
2813     lval->e_flags = E_MEXPR;
2814 }
2815
2816
2817
2818 static void Assignment (struct expent* lval)
2819 /* Parse an assignment */
2820 {
2821     int k;
2822     struct expent lval2;
2823     unsigned flags;
2824     type* ltype = lval->e_tptr;
2825
2826     /* Check for assignment to const */
2827     if (IsQualConst (ltype)) {
2828         Error ("Assignment to const");
2829     }
2830
2831     /* cc65 does not have full support for handling structs by value. Since
2832      * assigning structs is one of the more useful operations from this
2833      * familiy, allow it here.
2834      */
2835     if (IsClassStruct (ltype)) {
2836
2837         /* Bring the address of the lhs into the primary and push it */
2838         exprhs (0, 0, lval);
2839         g_push (CF_PTR | CF_UNSIGNED, 0);
2840
2841         /* Get the expression on the right of the '=' into the primary */
2842         k = hie1 (&lval2);
2843         if (k) {
2844             /* Get the address */
2845             exprhs (0, 0, &lval2);
2846         } else {
2847             /* We need an lvalue */
2848             Error ("Invalid lvalue in assignment");
2849         }
2850
2851         /* Push the address (or whatever is in ax in case of errors) */
2852         g_push (CF_PTR | CF_UNSIGNED, 0);
2853
2854         /* Check for equality of the structs */
2855         if (TypeCmp (ltype, lval2.e_tptr) < TC_EQUAL) {
2856             Error ("Incompatible types");
2857         }
2858
2859         /* Load the size of the struct into the primary */
2860         g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, SizeOf (ltype), 0);
2861
2862         /* Call the memcpy function */
2863         g_call (CF_FIXARGC, "memcpy", 4);
2864
2865     } else {
2866
2867         /* Get the address on stack if needed */
2868         PushAddr (lval);
2869
2870         /* No struct, setup flags for the load */
2871         flags = SizeOf (ltype) == 1? CF_FORCECHAR : CF_NONE;
2872
2873         /* Get the expression on the right of the '=' into the primary */
2874         if (evalexpr (flags, hie1, &lval2) == 0) {
2875             /* Constant expression. Adjust the types */
2876             assignadjust (ltype, &lval2);
2877             /* Put the value into the primary register */
2878             lconst (flags, &lval2);
2879         } else {
2880             /* Expression is not constant and already in the primary */
2881             assignadjust (ltype, &lval2);
2882         }
2883
2884         /* Generate a store instruction */
2885         store (lval);
2886
2887     }
2888
2889     /* Value is still in primary */
2890     lval->e_flags = E_MEXPR;
2891 }
2892
2893
2894
2895 int hie1 (struct expent* lval)
2896 /* Parse first level of expression hierarchy. */
2897 {
2898     int k;
2899
2900     k = hieQuest (lval);
2901     switch (curtok) {
2902
2903         case TOK_RPAREN:
2904         case TOK_SEMI:
2905             return k;
2906
2907         case TOK_ASSIGN:
2908             NextToken ();
2909             if (k == 0) {
2910                 Error ("Invalid lvalue in assignment");
2911             } else {
2912                 Assignment (lval);
2913             }
2914             break;
2915
2916         case TOK_PLUS_ASSIGN:
2917             addsubeq (&GenPASGN, lval, k);
2918             break;
2919
2920         case TOK_MINUS_ASSIGN:
2921             addsubeq (&GenSASGN, lval, k);
2922             break;
2923
2924         case TOK_MUL_ASSIGN:
2925             opeq (&GenMASGN, lval, k);
2926             break;
2927
2928         case TOK_DIV_ASSIGN:
2929             opeq (&GenDASGN, lval, k);
2930             break;
2931
2932         case TOK_MOD_ASSIGN:
2933             opeq (&GenMOASGN, lval, k);
2934             break;
2935
2936         case TOK_SHL_ASSIGN:
2937             opeq (&GenSLASGN, lval, k);
2938             break;
2939
2940         case TOK_SHR_ASSIGN:
2941             opeq (&GenSRASGN, lval, k);
2942             break;
2943
2944         case TOK_AND_ASSIGN:
2945             opeq (&GenAASGN, lval, k);
2946             break;
2947
2948         case TOK_XOR_ASSIGN:
2949             opeq (&GenXOASGN, lval, k);
2950             break;
2951
2952         case TOK_OR_ASSIGN:
2953             opeq (&GenOASGN, lval, k);
2954             break;
2955
2956         default:
2957             return k;
2958     }
2959     return 0;
2960 }
2961
2962
2963
2964 int hie0 (struct expent *lval)
2965 /* Parse comma operator. */
2966 {
2967     int k;
2968
2969     k = hie1 (lval);
2970     while (curtok == TOK_COMMA) {
2971         NextToken ();
2972         k = hie1 (lval);
2973     }
2974     return k;
2975 }
2976
2977
2978
2979 int evalexpr (unsigned flags, int (*f) (struct expent*), struct expent* lval)
2980 /* Will evaluate an expression via the given function. If the result is a
2981  * constant, 0 is returned and the value is put in the lval struct. If the
2982  * result is not constant, exprhs is called to bring the value into the
2983  * primary register and 1 is returned.
2984  */
2985 {
2986     int k;
2987
2988     /* Evaluate */
2989     k = f (lval);
2990     if (k == 0 && lval->e_flags == E_MCONST) {
2991         /* Constant expression */
2992         return 0;
2993     } else {
2994         /* Not constant, load into the primary */
2995         exprhs (flags, k, lval);
2996         return 1;
2997     }
2998 }
2999
3000
3001
3002 int expr (int (*func) (struct expent*), struct expent *lval)
3003 /* Expression parser; func is either hie0 or hie1. */
3004 {
3005     int k;
3006     int savsp;
3007
3008     savsp = oursp;
3009
3010     k = (*func) (lval);
3011
3012     /* Do some checks if code generation is still constistent */
3013     if (savsp != oursp) {
3014         if (Debug) {
3015             fprintf (stderr, "oursp != savesp (%d != %d)\n", oursp, savsp);
3016         } else {
3017             Internal ("oursp != savsp (%d != %d)", oursp, savsp);
3018         }
3019     }
3020     return k;
3021 }
3022
3023
3024
3025 void expression1 (struct expent* lval)
3026 /* Evaluate an expression on level 1 (no comma operator) and put it into
3027  * the primary register
3028  */
3029 {
3030     memset (lval, 0, sizeof (*lval));
3031     exprhs (CF_NONE, expr (hie1, lval), lval);
3032 }
3033
3034
3035
3036 void expression (struct expent* lval)
3037 /* Evaluate an expression and put it into the primary register */
3038 {
3039     memset (lval, 0, sizeof (*lval));
3040     exprhs (CF_NONE, expr (hie0, lval), lval);
3041 }
3042
3043
3044
3045 void constexpr (struct expent* lval)
3046 /* Get a constant value */
3047 {
3048     memset (lval, 0, sizeof (*lval));
3049     if (expr (hie1, lval) != 0 || (lval->e_flags & E_MCONST) == 0) {
3050         Error ("Constant expression expected");
3051         /* To avoid any compiler errors, make the expression a valid const */
3052         lval->e_flags = E_MCONST;
3053         lval->e_tptr = type_int;
3054         lval->e_const = 0;
3055     }
3056 }
3057
3058
3059
3060 void intexpr (struct expent* lval)
3061 /* Get an integer expression */
3062 {
3063     expression (lval);
3064     if (!IsClassInt (lval->e_tptr)) {
3065         Error ("Integer expression expected");
3066         /* To avoid any compiler errors, make the expression a valid int */
3067         lval->e_flags = E_MCONST;
3068         lval->e_tptr = type_int;
3069         lval->e_const = 0;
3070     }
3071 }
3072
3073
3074
3075 void boolexpr (struct expent* lval)
3076 /* Get a boolean expression */
3077 {
3078     /* Read an expression */
3079     expression (lval);
3080
3081     /* If it's an integer, it's ok. If it's not an integer, but a pointer,
3082      * the pointer used in a boolean context is also ok
3083      */
3084     if (!IsClassInt (lval->e_tptr) && !IsClassPtr (lval->e_tptr)) {
3085         Error ("Boolean expression expected");
3086         /* To avoid any compiler errors, make the expression a valid int */
3087         lval->e_flags = E_MCONST;
3088         lval->e_tptr = type_int;
3089         lval->e_const = 0;
3090     }
3091 }
3092
3093
3094
3095 void test (unsigned label, int cond)
3096 /* Generate code to perform test and jump if false. */
3097 {
3098     int k;
3099     struct expent lval;
3100
3101     /* Eat the parenthesis */
3102     ConsumeLParen ();
3103
3104     /* Prepare the expression, setup labels */
3105     memset (&lval, 0, sizeof (lval));
3106
3107     /* Generate code to eval the expr */
3108     k = expr (hie0, &lval);
3109     if (k == 0 && lval.e_flags == E_MCONST) {
3110         /* Constant rvalue */
3111         if (cond == 0 && lval.e_const == 0) {
3112             g_jump (label);
3113             Warning ("Unreachable code");
3114         } else if (cond && lval.e_const) {
3115             g_jump (label);
3116         }
3117         ConsumeRParen ();
3118         return;
3119     }
3120
3121     /* If the expr hasn't set condition codes, set the force-test flag */
3122     if ((lval.e_test & E_CC) == 0) {
3123         lval.e_test |= E_FORCETEST;
3124     }
3125
3126     /* Load the value into the primary register */
3127     exprhs (CF_FORCECHAR, k, &lval);
3128
3129     /* Check for the closing brace */
3130     ConsumeRParen ();
3131
3132     /* Generate the jump */
3133     if (cond) {
3134         g_truejump (CF_NONE, label);
3135     } else {
3136         /* Special case (putting this here is a small hack - but hey, the
3137          * compiler itself is one big hack...): If a semicolon follows, we
3138          * don't have a statement and may omit the jump.
3139          */
3140         if (curtok != TOK_SEMI) {
3141             g_falsejump (CF_NONE, label);
3142         }
3143     }
3144 }
3145
3146
3147
3148