Many signedness and type propagation fixes
[fw/sdcc] / src / SDCCast.c
1 /*-------------------------------------------------------------------------
2   SDCCast.c - source file for parser support & all ast related routines
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26
27 int currLineno = 0;
28 set *astList = NULL;
29 set *operKeyReset = NULL;
30 ast *staticAutos = NULL;
31 int labelKey = 1;
32
33 #define LRVAL(x) x->left->rvalue
34 #define RRVAL(x) x->right->rvalue
35 #define TRVAL(x) x->rvalue
36 #define LLVAL(x) x->left->lvalue
37 #define RLVAL(x) x->right->lvalue
38 #define TLVAL(x) x->lvalue
39 #define RTYPE(x) x->right->ftype
40 #define RETYPE(x) x->right->etype
41 #define LTYPE(x) x->left->ftype
42 #define LETYPE(x) x->left->etype
43 #define TTYPE(x) x->ftype
44 #define TETYPE(x) x->etype
45 #define ALLOCATE 1
46 #define DEALLOCATE 2
47
48 int noLineno = 0;
49 int noAlloc = 0;
50 symbol *currFunc=NULL;
51 static ast *createIval (ast *, sym_link *, initList *, ast *);
52 static ast *createIvalCharPtr (ast *, sym_link *, ast *);
53 static ast *optimizeCompare (ast *);
54 ast *optimizeRRCRLC (ast *);
55 ast *optimizeSWAP (ast *);
56 ast *optimizeGetHbit (ast *);
57 ast *backPatchLabels (ast *, symbol *, symbol *);
58 void PA(ast *t);
59 int inInitMode = 0;
60 memmap *GcurMemmap=NULL;  /* points to the memmap that's currently active */
61 FILE *codeOutFile;
62 int 
63 ptt (ast * tree)
64 {
65   printTypeChain (tree->ftype, stdout);
66   return 0;
67 }
68
69
70 /*-----------------------------------------------------------------*/
71 /* newAst - creates a fresh node for an expression tree            */
72 /*-----------------------------------------------------------------*/
73 static ast *
74 newAst_ (unsigned type)
75 {
76   ast *ex;
77   static int oldLineno = 0;
78
79   ex = Safe_alloc ( sizeof (ast));
80
81   ex->type = type;
82   ex->lineno = (noLineno ? oldLineno : mylineno);
83   ex->filename = currFname;
84   ex->level = NestLevel;
85   ex->block = currBlockno;
86   ex->initMode = inInitMode;
87   ex->seqPoint = seqPointNo;
88   return ex;
89 }
90
91 ast *
92 newAst_VALUE (value * val)
93 {
94   ast *ex = newAst_ (EX_VALUE);
95   ex->opval.val = val;
96   return ex;
97 }
98
99 ast *
100 newAst_OP (unsigned op)
101 {
102   ast *ex = newAst_ (EX_OP);
103   ex->opval.op = op;
104   return ex;
105 }
106
107 ast *
108 newAst_LINK (sym_link * val)
109 {
110   ast *ex = newAst_ (EX_LINK);
111   ex->opval.lnk = val;
112   return ex;
113 }
114
115 /*-----------------------------------------------------------------*/
116 /* newNode - creates a new node                                    */
117 /*-----------------------------------------------------------------*/
118 ast *
119 newNode (long op, ast * left, ast * right)
120 {
121   ast *ex;
122
123   ex = newAst_OP (op);
124   ex->left = left;
125   ex->right = right;
126
127   return ex;
128 }
129
130 /*-----------------------------------------------------------------*/
131 /* newIfxNode - creates a new Ifx Node                             */
132 /*-----------------------------------------------------------------*/
133 ast *
134 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
135 {
136   ast *ifxNode;
137
138   /* if this is a literal then we already know the result */
139   if (condAst->etype && IS_LITERAL (condAst->etype))
140     {
141       /* then depending on the expression value */
142       if (floatFromVal (condAst->opval.val))
143         ifxNode = newNode (GOTO,
144                            newAst_VALUE (symbolVal (trueLabel)),
145                            NULL);
146       else
147         ifxNode = newNode (GOTO,
148                            newAst_VALUE (symbolVal (falseLabel)),
149                            NULL);
150     }
151   else
152     {
153       ifxNode = newNode (IFX, condAst, NULL);
154       ifxNode->trueLabel = trueLabel;
155       ifxNode->falseLabel = falseLabel;
156     }
157
158   return ifxNode;
159 }
160
161 /*-----------------------------------------------------------------*/
162 /* copyAstValues - copies value portion of ast if needed     */
163 /*-----------------------------------------------------------------*/
164 void
165 copyAstValues (ast * dest, ast * src)
166 {
167   switch (src->opval.op)
168     {
169     case BLOCK:
170       dest->values.sym = copySymbolChain (src->values.sym);
171       break;
172
173     case SWITCH:
174       dest->values.switchVals.swVals =
175         copyValue (src->values.switchVals.swVals);
176       dest->values.switchVals.swDefault =
177         src->values.switchVals.swDefault;
178       dest->values.switchVals.swNum =
179         src->values.switchVals.swNum;
180       break;
181
182     case INLINEASM:
183       dest->values.inlineasm =  Safe_strdup(src->values.inlineasm);
184       break;
185
186     case ARRAYINIT:
187         dest->values.constlist = copyLiteralList(src->values.constlist);
188         break;
189
190     case FOR:
191       AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
192       AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
193       AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
194       AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
195       AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
196       AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
197       AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
198     }
199
200 }
201
202 /*-----------------------------------------------------------------*/
203 /* copyAst - makes a copy of a given astession                     */
204 /*-----------------------------------------------------------------*/
205 ast *
206 copyAst (ast * src)
207 {
208   ast *dest;
209
210   if (!src)
211     return NULL;
212
213   dest = Safe_alloc ( sizeof (ast));
214
215   dest->type = src->type;
216   dest->lineno = src->lineno;
217   dest->level = src->level;
218   dest->funcName = src->funcName;
219
220   if (src->ftype)
221     dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
222
223   /* if this is a leaf */
224   /* if value */
225   if (src->type == EX_VALUE)
226     {
227       dest->opval.val = copyValue (src->opval.val);
228       goto exit;
229     }
230
231   /* if link */
232   if (src->type == EX_LINK)
233     {
234       dest->opval.lnk = copyLinkChain (src->opval.lnk);
235       goto exit;
236     }
237
238   dest->opval.op = src->opval.op;
239
240   /* if this is a node that has special values */
241   copyAstValues (dest, src);
242
243   dest->trueLabel = copySymbol (src->trueLabel);
244   dest->falseLabel = copySymbol (src->falseLabel);
245   dest->left = copyAst (src->left);
246   dest->right = copyAst (src->right);
247 exit:
248   return dest;
249
250 }
251
252 /*-----------------------------------------------------------------*/
253 /* removeIncDecOps: remove for side effects in *_ASSIGN's          */
254 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
255 /*-----------------------------------------------------------------*/
256 ast *removeIncDecOps (ast * tree) {
257
258   // traverse the tree and remove inc/dec ops
259
260   if (!tree)
261     return NULL;
262
263   if (tree->type == EX_OP &&
264       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
265     if (tree->left)
266       tree=tree->left;
267     else
268       tree=tree->right;
269   }
270
271   tree->left=removeIncDecOps(tree->left);
272   tree->right=removeIncDecOps(tree->right);
273
274  return tree;
275 }
276
277 /*-----------------------------------------------------------------*/
278 /* removePreIncDecOps: remove for side effects in *_ASSIGN's       */
279 /*                  "*++s += 3" -> "*++s = *++s + 3"               */
280 /*-----------------------------------------------------------------*/
281 ast *removePreIncDecOps (ast * tree) {
282
283   // traverse the tree and remove pre-inc/dec ops
284
285   if (!tree)
286     return NULL;
287
288   if (tree->type == EX_OP &&
289       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
290     if (tree->right)
291       tree=tree->right;
292   }
293
294   tree->left=removePreIncDecOps(tree->left);
295   tree->right=removePreIncDecOps(tree->right);
296
297  return tree;
298 }
299
300 /*-----------------------------------------------------------------*/
301 /* removePostIncDecOps: remove for side effects in *_ASSIGN's      */
302 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
303 /*-----------------------------------------------------------------*/
304 ast *removePostIncDecOps (ast * tree) {
305
306   // traverse the tree and remove pre-inc/dec ops
307
308   if (!tree)
309     return NULL;
310
311   if (tree->type == EX_OP &&
312       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
313     if (tree->left)
314       tree=tree->left;
315   }
316
317   tree->left=removePostIncDecOps(tree->left);
318   tree->right=removePostIncDecOps(tree->right);
319
320  return tree;
321 }
322
323 /*-----------------------------------------------------------------*/
324 /* hasSEFcalls - returns TRUE if tree has a function call          */
325 /*-----------------------------------------------------------------*/
326 bool
327 hasSEFcalls (ast * tree)
328 {
329   if (!tree)
330     return FALSE;
331
332   if (tree->type == EX_OP &&
333       (tree->opval.op == CALL ||
334        tree->opval.op == PCALL ||
335        tree->opval.op == '=' ||
336        tree->opval.op == INC_OP ||
337        tree->opval.op == DEC_OP))
338     return TRUE;
339
340   return (hasSEFcalls (tree->left) |
341           hasSEFcalls (tree->right));
342 }
343
344 /*-----------------------------------------------------------------*/
345 /* isAstEqual - compares two asts & returns 1 if they are equal    */
346 /*-----------------------------------------------------------------*/
347 static int
348 isAstEqual (ast * t1, ast * t2)
349 {
350   if (!t1 && !t2)
351     return 1;
352
353   if (!t1 || !t2)
354     return 0;
355
356   /* match type */
357   if (t1->type != t2->type)
358     return 0;
359
360   switch (t1->type)
361     {
362     case EX_OP:
363       if (t1->opval.op != t2->opval.op)
364         return 0;
365       return (isAstEqual (t1->left, t2->left) &&
366               isAstEqual (t1->right, t2->right));
367       break;
368
369     case EX_VALUE:
370       if (t1->opval.val->sym)
371         {
372           if (!t2->opval.val->sym)
373             return 0;
374           else
375             return isSymbolEqual (t1->opval.val->sym,
376                                   t2->opval.val->sym);
377         }
378       else
379         {
380           if (t2->opval.val->sym)
381             return 0;
382           else
383             return (floatFromVal (t1->opval.val) ==
384                     floatFromVal (t2->opval.val));
385         }
386       break;
387
388       /* only compare these two types */
389     default:
390       return 0;
391     }
392
393   return 0;
394 }
395
396 /*-----------------------------------------------------------------*/
397 /* resolveSymbols - resolve symbols from the symbol table          */
398 /*-----------------------------------------------------------------*/
399 ast *
400 resolveSymbols (ast * tree)
401 {
402   /* walk the entire tree and check for values */
403   /* with symbols if we find one then replace  */
404   /* symbol with that from the symbol table    */
405
406   if (tree == NULL)
407     return tree;
408
409 #if 0
410   /* print the line          */
411   /* if not block & function */
412   if (tree->type == EX_OP &&
413       (tree->opval.op != FUNCTION &&
414        tree->opval.op != BLOCK &&
415        tree->opval.op != NULLOP))
416     {
417       filename = tree->filename;
418       lineno = tree->lineno;
419     }
420 #endif
421
422   /* make sure we resolve the true & false labels for ifx */
423   if (tree->type == EX_OP && tree->opval.op == IFX)
424     {
425       symbol *csym;
426
427       if (tree->trueLabel)
428         {
429           if ((csym = findSym (LabelTab, tree->trueLabel,
430                                tree->trueLabel->name)))
431             tree->trueLabel = csym;
432           else
433             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
434                       tree->trueLabel->name);
435         }
436
437       if (tree->falseLabel)
438         {
439           if ((csym = findSym (LabelTab,
440                                tree->falseLabel,
441                                tree->falseLabel->name)))
442             tree->falseLabel = csym;
443           else
444             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
445                       tree->falseLabel->name);
446         }
447
448     }
449
450   /* if this is a label resolve it from the labelTab */
451   if (IS_AST_VALUE (tree) &&
452       tree->opval.val->sym &&
453       tree->opval.val->sym->islbl)
454     {
455
456       symbol *csym = findSym (LabelTab, tree->opval.val->sym,
457                               tree->opval.val->sym->name);
458
459       if (!csym)
460         werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
461                   tree->opval.val->sym->name);
462       else
463         tree->opval.val->sym = csym;
464
465       goto resolveChildren;
466     }
467
468   /* do only for leafs */
469   if (IS_AST_VALUE (tree) &&
470       tree->opval.val->sym &&
471       !tree->opval.val->sym->implicit)
472     {
473
474       symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
475
476       /* if found in the symbol table & they r not the same */
477       if (csym && tree->opval.val->sym != csym)
478         {
479           tree->opval.val->sym = csym;
480           tree->opval.val->type = csym->type;
481           tree->opval.val->etype = csym->etype;
482         }
483
484       /* if not found in the symbol table */
485       /* mark it as undefined assume it is */
486       /* an integer in data space         */
487       if (!csym && !tree->opval.val->sym->implicit)
488         {
489
490           /* if this is a function name then */
491           /* mark it as returning an int     */
492           if (tree->funcName)
493             {
494               tree->opval.val->sym->type = newLink (DECLARATOR);
495               DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
496               tree->opval.val->sym->type->next =
497                 tree->opval.val->sym->etype = newIntLink ();
498               tree->opval.val->etype = tree->opval.val->etype;
499               tree->opval.val->type = tree->opval.val->sym->type;
500               werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
501                         tree->opval.val->sym->name);
502               //tree->opval.val->sym->undefined = 1;
503               allocVariables (tree->opval.val->sym);
504             }
505           else
506             {
507               tree->opval.val->sym->undefined = 1;
508               tree->opval.val->type =
509                 tree->opval.val->etype = newIntLink ();
510               tree->opval.val->sym->type =
511                 tree->opval.val->sym->etype = newIntLink ();
512             }
513         }
514     }
515
516 resolveChildren:
517   resolveSymbols (tree->left);
518   resolveSymbols (tree->right);
519
520   return tree;
521 }
522
523 /*-----------------------------------------------------------------*/
524 /* setAstLineno - walks a ast tree & sets the line number          */
525 /*-----------------------------------------------------------------*/
526 int setAstLineno (ast * tree, int lineno)
527 {
528   if (!tree)
529     return 0;
530
531   tree->lineno = lineno;
532   setAstLineno (tree->left, lineno);
533   setAstLineno (tree->right, lineno);
534   return 0;
535 }
536
537 /*-----------------------------------------------------------------*/
538 /* funcOfType :- function of type with name                        */
539 /*-----------------------------------------------------------------*/
540 symbol *
541 funcOfType (char *name, sym_link * type, sym_link * argType,
542             int nArgs, int rent)
543 {
544   symbol *sym;
545   /* create the symbol */
546   sym = newSymbol (name, 0);
547
548   /* setup return value */
549   sym->type = newLink (DECLARATOR);
550   DCL_TYPE (sym->type) = FUNCTION;
551   sym->type->next = copyLinkChain (type);
552   sym->etype = getSpec (sym->type);
553   FUNC_ISREENT(sym->type) = rent ? 1 : 0;
554
555   /* if arguments required */
556   if (nArgs)
557     {
558       value *args;
559       args = FUNC_ARGS(sym->type) = newValue ();
560
561       while (nArgs--)
562         {
563           args->type = copyLinkChain (argType);
564           args->etype = getSpec (args->type);
565           SPEC_EXTR(args->etype)=1;
566           if (!nArgs)
567             break;
568           args = args->next = newValue ();
569         }
570     }
571
572   /* save it */
573   addSymChain (sym);
574   sym->cdef = 1;
575   allocVariables (sym);
576   return sym;
577
578 }
579
580 /*-----------------------------------------------------------------*/
581 /* funcOfTypeVarg :- function of type with name and argtype        */
582 /*-----------------------------------------------------------------*/
583 symbol *
584 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
585 {
586   
587     symbol *sym;
588     int i ;
589     /* create the symbol */
590     sym = newSymbol (name, 0);
591     
592     /* setup return value */
593     sym->type = newLink (DECLARATOR);
594     DCL_TYPE (sym->type) = FUNCTION;
595     sym->type->next = typeFromStr(rtype);
596     sym->etype = getSpec (sym->type);
597     
598     /* if arguments required */
599     if (nArgs) {
600         value *args;
601         args = FUNC_ARGS(sym->type) = newValue ();
602         
603         for ( i = 0 ; i < nArgs ; i++ ) {
604             args->type = typeFromStr(atypes[i]);
605             args->etype = getSpec (args->type);
606             SPEC_EXTR(args->etype)=1;
607             if ((i + 1) == nArgs) break;
608             args = args->next = newValue ();
609         }
610     }
611
612     /* save it */
613     addSymChain (sym);
614     sym->cdef = 1;
615     allocVariables (sym);
616     return sym;
617
618 }
619
620 /*-----------------------------------------------------------------*/
621 /* reverseParms - will reverse a parameter tree                    */
622 /*-----------------------------------------------------------------*/
623 static void
624 reverseParms (ast * ptree)
625 {
626   ast *ttree;
627   if (!ptree)
628     return;
629
630   /* top down if we find a nonParm tree then quit */
631   if (ptree->type == EX_OP && ptree->opval.op == PARAM)
632     {
633       ttree = ptree->left;
634       ptree->left = ptree->right;
635       ptree->right = ttree;
636       reverseParms (ptree->left);
637       reverseParms (ptree->right);
638     }
639
640   return;
641 }
642
643 /*-----------------------------------------------------------------*/
644 /* processParms  - makes sure the parameters are okay and do some  */
645 /*                 processing with them                            */
646 /*-----------------------------------------------------------------*/
647 int 
648 processParms (ast * func,
649               value *defParm,
650               ast * actParm,
651               int *parmNumber, // unused, although updated
652               bool rightmost)
653 {
654   /* if none of them exist */
655   if (!defParm && !actParm)
656     return 0;
657
658   if (defParm) {
659     if (getenv("DEBUG_SANITY")) {
660       fprintf (stderr, "processParms: %s ", defParm->name);
661     }
662     /* make sure the type is complete and sane */
663     checkTypeSanity(defParm->etype, defParm->name);
664   }
665
666   /* if the function is being called via a pointer &   */
667   /* it has not been defined a reentrant then we cannot */
668   /* have parameters                                   */
669   if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto)
670     {
671       werror (W_NONRENT_ARGS);
672       return 1;
673     }
674
675   /* if defined parameters ended but actual parameters */
676   /* exist and this is not defined as a variable arg   */
677   if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
678     {
679       //if (func->type==EX_VALUE && func->opval.val->sym->undefined)
680       //  return 1; /* Already gave them an undefined function error */
681       werror (E_TOO_MANY_PARMS);
682       return 1;
683     }
684
685   /* if defined parameters present but no actual parameters */
686   if (defParm && !actParm)
687     {
688       werror (E_TOO_FEW_PARMS);
689       return 1;
690     }
691
692   if (IS_VOID(actParm->ftype)) {
693     werror (E_VOID_VALUE_USED);
694     return 1;
695   }
696
697   /* If this is a varargs function... */
698   if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype))
699     {
700       ast *newType = NULL;
701       sym_link *ftype;
702
703       if (IS_CAST_OP (actParm)
704           || (IS_AST_LIT_VALUE (actParm) && actParm->values.literalFromCast))
705         {
706           /* Parameter was explicitly typecast; don't touch it. */
707           return 0;
708         }
709
710       ftype = actParm->ftype;
711           
712       /* If it's a small integer, upcast to int. */
713       if (IS_INTEGRAL (ftype)
714           && (getSize (ftype) < (unsigned) INTSIZE))
715         {
716           if (IS_AST_OP(actParm) &&
717               (actParm->opval.op == LEFT_OP ||
718                actParm->opval.op == '*' ||
719                actParm->opval.op == '+' ||
720                actParm->opval.op == '-') &&
721               actParm->right) {
722             // we should cast an operand instead of the result
723             actParm->decorated = 0;
724             actParm->left = newNode( CAST, newAst_LINK(newIntLink()),
725                                          actParm->left);
726             actParm = decorateType(actParm);
727           } else {
728             newType = newAst_LINK(INTTYPE);
729           }
730         }
731
732       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
733         {
734           newType = newAst_LINK (copyLinkChain(ftype));
735           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
736         }
737
738       if (IS_AGGREGATE (ftype))
739         {
740           newType = newAst_LINK (copyLinkChain (ftype));
741           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
742         }
743       if (newType)
744         {
745           /* cast required; change this op to a cast. */
746           ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)));
747
748           actParm->type = EX_OP;
749           actParm->opval.op = CAST;
750           actParm->left = newType;
751           actParm->right = parmCopy;
752           decorateType (actParm);
753         }
754       else if (actParm->type == EX_OP && actParm->opval.op == PARAM)
755         {
756           return (processParms (func, NULL, actParm->left, parmNumber, FALSE) ||
757           processParms (func, NULL, actParm->right, parmNumber, rightmost));
758         }
759       return 0;
760     }
761
762   /* if defined parameters ended but actual has not & */
763   /* reentrant */
764   if (!defParm && actParm &&
765       (options.stackAuto || IFFUNC_ISREENT (func->ftype)))
766     return 0;
767
768   resolveSymbols (actParm);
769   /* if this is a PARAM node then match left & right */
770   if (actParm->type == EX_OP && actParm->opval.op == PARAM)
771     {
772       return (processParms (func, defParm, actParm->left, parmNumber, FALSE) ||
773               processParms (func, defParm->next, actParm->right, parmNumber, rightmost));
774     }
775   else
776     {
777       /* If we have found a value node by following only right-hand links,
778        * then we know that there are no more values after us.
779        *
780        * Therefore, if there are more defined parameters, the caller didn't
781        * supply enough.
782        */
783       if (rightmost && defParm->next)
784         {
785           werror (E_TOO_FEW_PARMS);
786           return 1;
787         }
788     }
789
790   /* the parameter type must be at least castable */
791   if (compareType (defParm->type, actParm->ftype) == 0) {
792     werror (E_INCOMPAT_TYPES);
793     printFromToType (actParm->ftype, defParm->type);
794     return 1;
795   }
796
797   /* if the parameter is castable then add the cast */
798   if (compareType (defParm->type, actParm->ftype) < 0)
799     {
800       ast *pTree = decorateType(resolveSymbols (copyAst (actParm)));
801
802       /* now change the current one to a cast */
803       actParm->type = EX_OP;
804       actParm->opval.op = CAST;
805       actParm->left = newAst_LINK (defParm->type);
806       actParm->right = pTree;
807       actParm->etype = defParm->etype;
808       actParm->ftype = defParm->type;
809       actParm->decorated=0; /* force typechecking */
810       decorateType (actParm);
811     }
812
813   /* make a copy and change the regparm type to the defined parm */
814   actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype));
815   SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype);
816   SPEC_ARGREG  (actParm->etype) = SPEC_ARGREG (defParm->etype);
817   (*parmNumber)++;
818   return 0;
819 }
820 /*-----------------------------------------------------------------*/
821 /* createIvalType - generates ival for basic types                 */
822 /*-----------------------------------------------------------------*/
823 static ast *
824 createIvalType (ast * sym, sym_link * type, initList * ilist)
825 {
826   ast *iExpr;
827
828   /* if initList is deep */
829   if (ilist->type == INIT_DEEP)
830     ilist = ilist->init.deep;
831
832   iExpr = decorateType (resolveSymbols (list2expr (ilist)));
833   return decorateType (newNode ('=', sym, iExpr));
834 }
835
836 /*-----------------------------------------------------------------*/
837 /* createIvalStruct - generates initial value for structures       */
838 /*-----------------------------------------------------------------*/
839 static ast *
840 createIvalStruct (ast * sym, sym_link * type, initList * ilist)
841 {
842   ast *rast = NULL;
843   ast *lAst;
844   symbol *sflds;
845   initList *iloop;
846
847   sflds = SPEC_STRUCT (type)->fields;
848   if (ilist->type != INIT_DEEP)
849     {
850       werror (E_INIT_STRUCT, "");
851       return NULL;
852     }
853
854   iloop = ilist->init.deep;
855
856   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
857     {
858       /* if we have come to end */
859       if (!iloop)
860         break;
861       sflds->implicit = 1;
862       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
863       lAst = decorateType (resolveSymbols (lAst));
864       rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)));
865     }
866
867   if (iloop) {
868     werrorfl (filename, sym->opval.val->sym->lineDef,
869               W_EXCESS_INITIALIZERS, "struct", 
870               sym->opval.val->sym->name);
871   }
872
873   return rast;
874 }
875
876
877 /*-----------------------------------------------------------------*/
878 /* createIvalArray - generates code for array initialization       */
879 /*-----------------------------------------------------------------*/
880 static ast *
881 createIvalArray (ast * sym, sym_link * type, initList * ilist)
882 {
883   ast *rast = NULL;
884   initList *iloop;
885   int lcnt = 0, size = 0;
886   literalList *literalL;
887
888   /* take care of the special   case  */
889   /* array of characters can be init  */
890   /* by a string                      */
891   if (IS_CHAR (type->next))
892     if ((rast = createIvalCharPtr (sym,
893                                    type,
894                         decorateType (resolveSymbols (list2expr (ilist))))))
895
896       return decorateType (resolveSymbols (rast));
897
898     /* not the special case             */
899     if (ilist->type != INIT_DEEP)
900     {
901         werror (E_INIT_STRUCT, "");
902         return NULL;
903     }
904
905     iloop = ilist->init.deep;
906     lcnt = DCL_ELEM (type);
907
908     if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
909     {
910         ast *aSym;
911
912         aSym = decorateType (resolveSymbols(sym));
913         
914         rast = newNode(ARRAYINIT, aSym, NULL);
915         rast->values.constlist = literalL;
916         
917         // Make sure size is set to length of initializer list.
918         while (iloop)
919         {
920             size++;
921             iloop = iloop->next;
922         }
923         
924         if (lcnt && size > lcnt)
925         {
926             // Array size was specified, and we have more initializers than needed.
927             char *name=sym->opval.val->sym->name;
928             int lineno=sym->opval.val->sym->lineDef;
929             
930             werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
931         }
932     }
933     else
934     {
935         for (;;)
936         {
937             ast *aSym;
938             
939             aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
940             aSym = decorateType (resolveSymbols (aSym));
941             rast = createIval (aSym, type->next, iloop, rast);
942             iloop = (iloop ? iloop->next : NULL);
943             if (!iloop)
944             {
945                 break;
946             }
947             
948             /* no of elements given and we    */
949             /* have generated for all of them */
950             if (!--lcnt) 
951             {
952                 // there has to be a better way
953                 char *name=sym->opval.val->sym->name;
954                 int lineno=sym->opval.val->sym->lineDef;
955                 werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
956                 
957                 break;
958             }
959         }
960     }
961
962     /* if we have not been given a size  */
963     if (!DCL_ELEM (type))
964     {
965         DCL_ELEM (type) = size;
966     }
967
968     return decorateType (resolveSymbols (rast));
969 }
970
971
972 /*-----------------------------------------------------------------*/
973 /* createIvalCharPtr - generates initial values for char pointers  */
974 /*-----------------------------------------------------------------*/
975 static ast *
976 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
977 {
978   ast *rast = NULL;
979
980   /* if this is a pointer & right is a literal array then */
981   /* just assignment will do                              */
982   if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
983                          SPEC_SCLS (iexpr->etype) == S_CODE)
984                         && IS_ARRAY (iexpr->ftype)))
985     return newNode ('=', sym, iexpr);
986
987   /* left side is an array so we have to assign each */
988   /* element                                         */
989   if ((IS_LITERAL (iexpr->etype) ||
990        SPEC_SCLS (iexpr->etype) == S_CODE)
991       && IS_ARRAY (iexpr->ftype))
992     {
993       /* for each character generate an assignment */
994       /* to the array element */
995       char *s = SPEC_CVAL (iexpr->etype).v_char;
996       int i = 0;
997       int size = getSize (iexpr->ftype);
998       int symsize = getSize (type);
999       
1000       if (size>symsize)
1001         {
1002           if (size>(symsize+1))
1003             werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1004                       "string", sym->opval.val->sym->name);
1005           size = symsize;
1006         }
1007
1008       for (i=0;i<size;i++)
1009         {
1010           rast = newNode (NULLOP,
1011                           rast,
1012                           newNode ('=',
1013                                    newNode ('[', sym,
1014                                    newAst_VALUE (valueFromLit ((float) i))),
1015                                    newAst_VALUE (valueFromLit (*s))));
1016           s++;
1017         }
1018
1019       // now WE don't need iexpr's symbol anymore
1020       freeStringSymbol(AST_SYMBOL(iexpr));
1021
1022       return decorateType (resolveSymbols (rast));
1023     }
1024
1025   return NULL;
1026 }
1027
1028 /*-----------------------------------------------------------------*/
1029 /* createIvalPtr - generates initial value for pointers            */
1030 /*-----------------------------------------------------------------*/
1031 static ast *
1032 createIvalPtr (ast * sym, sym_link * type, initList * ilist)
1033 {
1034   ast *rast;
1035   ast *iexpr;
1036
1037   /* if deep then   */
1038   if (ilist->type == INIT_DEEP)
1039     ilist = ilist->init.deep;
1040
1041   iexpr = decorateType (resolveSymbols (list2expr (ilist)));
1042
1043   /* if character pointer */
1044   if (IS_CHAR (type->next))
1045     if ((rast = createIvalCharPtr (sym, type, iexpr)))
1046       return rast;
1047
1048   return newNode ('=', sym, iexpr);
1049 }
1050
1051 /*-----------------------------------------------------------------*/
1052 /* createIval - generates code for initial value                   */
1053 /*-----------------------------------------------------------------*/
1054 static ast *
1055 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
1056 {
1057   ast *rast = NULL;
1058
1059   if (!ilist)
1060     return NULL;
1061
1062   /* if structure then    */
1063   if (IS_STRUCT (type))
1064     rast = createIvalStruct (sym, type, ilist);
1065   else
1066     /* if this is a pointer */
1067   if (IS_PTR (type))
1068     rast = createIvalPtr (sym, type, ilist);
1069   else
1070     /* if this is an array   */
1071   if (IS_ARRAY (type))
1072     rast = createIvalArray (sym, type, ilist);
1073   else
1074     /* if type is SPECIFIER */
1075   if (IS_SPEC (type))
1076     rast = createIvalType (sym, type, ilist);
1077
1078   if (wid)
1079     return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)));
1080   else
1081     return decorateType (resolveSymbols (rast));
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* initAggregates - initialises aggregate variables with initv     */
1086 /*-----------------------------------------------------------------*/
1087 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1088   return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
1089 }
1090
1091 /*-----------------------------------------------------------------*/
1092 /* gatherAutoInit - creates assignment expressions for initial     */
1093 /*    values                 */
1094 /*-----------------------------------------------------------------*/
1095 static ast *
1096 gatherAutoInit (symbol * autoChain)
1097 {
1098   ast *init = NULL;
1099   ast *work;
1100   symbol *sym;
1101
1102   inInitMode = 1;
1103   for (sym = autoChain; sym; sym = sym->next)
1104     {
1105
1106       /* resolve the symbols in the ival */
1107       if (sym->ival)
1108         resolveIvalSym (sym->ival);
1109
1110       /* if this is a static variable & has an */
1111       /* initial value the code needs to be lifted */
1112       /* here to the main portion since they can be */
1113       /* initialised only once at the start    */
1114       if (IS_STATIC (sym->etype) && sym->ival &&
1115           SPEC_SCLS (sym->etype) != S_CODE)
1116         {
1117           symbol *newSym;
1118           
1119           /* insert the symbol into the symbol table */
1120           /* with level = 0 & name = rname       */
1121           newSym = copySymbol (sym);
1122           addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1123
1124           /* now lift the code to main */
1125           if (IS_AGGREGATE (sym->type)) {
1126             work = initAggregates (sym, sym->ival, NULL);
1127           } else {
1128             if (getNelements(sym->type, sym->ival)>1) {
1129               werrorfl (filename, sym->lineDef,
1130                         W_EXCESS_INITIALIZERS, "scalar", 
1131                         sym->name);
1132             }
1133             work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1134                             list2expr (sym->ival));
1135           }
1136
1137           setAstLineno (work, sym->lineDef);
1138
1139           sym->ival = NULL;
1140           if (staticAutos)
1141             staticAutos = newNode (NULLOP, staticAutos, work);
1142           else
1143             staticAutos = work;
1144
1145           continue;
1146         }
1147
1148       /* if there is an initial value */
1149       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1150         {
1151           initList *ilist=sym->ival;
1152           
1153           while (ilist->type == INIT_DEEP) {
1154             ilist = ilist->init.deep;
1155           }
1156
1157           /* update lineno for error msg */
1158           lineno=sym->lineDef;
1159           setAstLineno (ilist->init.node, lineno);
1160           
1161           if (IS_AGGREGATE (sym->type)) {
1162             work = initAggregates (sym, sym->ival, NULL);
1163           } else {
1164             if (getNelements(sym->type, sym->ival)>1) {
1165               werrorfl (filename, sym->lineDef,
1166                         W_EXCESS_INITIALIZERS, "scalar", 
1167                         sym->name);
1168             }
1169             work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1170                             list2expr (sym->ival));
1171           }
1172           
1173           // just to be sure
1174           setAstLineno (work, sym->lineDef);
1175
1176           sym->ival = NULL;
1177           if (init)
1178             init = newNode (NULLOP, init, work);
1179           else
1180             init = work;
1181         }
1182     }
1183   inInitMode = 0;
1184   return init;
1185 }
1186
1187 /*-----------------------------------------------------------------*/
1188 /* freeStringSymbol - delete a literal string if no more usage     */
1189 /*-----------------------------------------------------------------*/
1190 void freeStringSymbol(symbol *sym) {
1191   /* make sure this is a literal string */
1192   assert (sym->isstrlit);
1193   if (--sym->isstrlit == 0) { // lower the usage count
1194     memmap *segment=SPEC_OCLS(sym->etype);
1195     if (segment) {
1196       deleteSetItem(&segment->syms, sym);
1197     }
1198   }
1199 }
1200   
1201 /*-----------------------------------------------------------------*/
1202 /* stringToSymbol - creates a symbol from a literal string         */
1203 /*-----------------------------------------------------------------*/
1204 static value *
1205 stringToSymbol (value * val)
1206 {
1207   char name[SDCC_NAME_MAX + 1];
1208   static int charLbl = 0;
1209   symbol *sym;
1210   set *sp;
1211   int size;
1212
1213   // have we heard this before?
1214   for (sp=statsg->syms; sp; sp=sp->next) {
1215     sym=sp->item;
1216     size = getSize (sym->type);
1217     if (sym->isstrlit && size == getSize (val->type) &&
1218         !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
1219       // yes, this is old news. Don't publish it again.
1220       sym->isstrlit++; // but raise the usage count
1221       return symbolVal(sym);
1222     }
1223   }
1224
1225   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1226   sym = newSymbol (name, 0);    /* make it @ level 0 */
1227   strncpyz (sym->rname, name, SDCC_NAME_MAX);
1228
1229   /* copy the type from the value passed */
1230   sym->type = copyLinkChain (val->type);
1231   sym->etype = getSpec (sym->type);
1232   /* change to storage class & output class */
1233   SPEC_SCLS (sym->etype) = S_CODE;
1234   SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1235   SPEC_STAT (sym->etype) = 1;
1236   /* make the level & block = 0 */
1237   sym->block = sym->level = 0;
1238   sym->isstrlit = 1;
1239   /* create an ival */
1240   sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1241   if (noAlloc == 0)
1242     {
1243       /* allocate it */
1244       addSymChain (sym);
1245       allocVariables (sym);
1246     }
1247   sym->ival = NULL;
1248   return symbolVal (sym);
1249
1250 }
1251
1252 /*-----------------------------------------------------------------*/
1253 /* processBlockVars - will go thru the ast looking for block if    */
1254 /*                    a block is found then will allocate the syms */
1255 /*                    will also gather the auto inits present      */
1256 /*-----------------------------------------------------------------*/
1257 ast *
1258 processBlockVars (ast * tree, int *stack, int action)
1259 {
1260   if (!tree)
1261     return NULL;
1262
1263   /* if this is a block */
1264   if (tree->type == EX_OP && tree->opval.op == BLOCK)
1265     {
1266       ast *autoInit;
1267
1268       if (action == ALLOCATE)
1269         {
1270           *stack += allocVariables (tree->values.sym);
1271           autoInit = gatherAutoInit (tree->values.sym);
1272         
1273           /* if there are auto inits then do them */
1274           if (autoInit)
1275             tree->left = newNode (NULLOP, autoInit, tree->left);
1276         }
1277       else                      /* action is deallocate */
1278         deallocLocal (tree->values.sym);
1279     }
1280
1281   processBlockVars (tree->left, stack, action);
1282   processBlockVars (tree->right, stack, action);
1283   return tree;
1284 }
1285
1286
1287 /*-------------------------------------------------------------*/
1288 /* constExprTree - returns TRUE if this tree is a constant     */
1289 /*                 expression                                  */
1290 /*-------------------------------------------------------------*/
1291 bool constExprTree (ast *cexpr) {
1292
1293   if (!cexpr) {
1294     return TRUE;
1295   }
1296
1297   cexpr = decorateType (resolveSymbols (cexpr));
1298
1299   switch (cexpr->type) 
1300     {
1301     case EX_VALUE:
1302       if (IS_AST_LIT_VALUE(cexpr)) {
1303         // this is a literal
1304         return TRUE;
1305       }
1306       if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1307         // a function's address will never change
1308         return TRUE;
1309       }
1310       if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1311         // an array's address will never change
1312         return TRUE;
1313       }
1314       if (IS_AST_SYM_VALUE(cexpr) && 
1315           IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1316         // a symbol in code space will never change
1317         // This is only for the 'char *s="hallo"' case and will have to leave
1318         //printf(" code space symbol");
1319         return TRUE;
1320       }
1321       return FALSE;
1322     case EX_LINK:
1323       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1324               "unexpected link in expression tree\n");
1325       return FALSE;
1326     case EX_OP:
1327       if (cexpr->opval.op==ARRAYINIT) {
1328         // this is a list of literals
1329         return TRUE;
1330       }
1331       if (cexpr->opval.op=='=') {
1332         return constExprTree(cexpr->right);
1333       }
1334       if (cexpr->opval.op==CAST) {
1335         // cast ignored, maybe we should throw a warning here?
1336         return constExprTree(cexpr->right);
1337       }
1338       if (cexpr->opval.op=='&') { 
1339         return TRUE;
1340       }
1341       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1342         return FALSE;
1343       }
1344       if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1345         return TRUE;
1346       }
1347       return FALSE;
1348     case EX_OPERAND:
1349       return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1350     }
1351   return FALSE;
1352 }
1353     
1354 /*-----------------------------------------------------------------*/
1355 /* constExprValue - returns the value of a constant expression     */
1356 /*                  or NULL if it is not a constant expression     */
1357 /*-----------------------------------------------------------------*/
1358 value *
1359 constExprValue (ast * cexpr, int check)
1360 {
1361   cexpr = decorateType (resolveSymbols (cexpr));
1362
1363   /* if this is not a constant then */
1364   if (!IS_LITERAL (cexpr->ftype))
1365     {
1366       /* then check if this is a literal array
1367          in code segment */
1368       if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1369           SPEC_CVAL (cexpr->etype).v_char &&
1370           IS_ARRAY (cexpr->ftype))
1371         {
1372           value *val = valFromType (cexpr->ftype);
1373           SPEC_SCLS (val->etype) = S_LITERAL;
1374           val->sym = cexpr->opval.val->sym;
1375           val->sym->type = copyLinkChain (cexpr->ftype);
1376           val->sym->etype = getSpec (val->sym->type);
1377           strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1378           return val;
1379         }
1380
1381       /* if we are casting a literal value then */
1382       if (IS_AST_OP (cexpr) &&
1383           cexpr->opval.op == CAST &&
1384           IS_LITERAL (cexpr->right->ftype))
1385         {
1386         return valCastLiteral (cexpr->ftype,
1387                                floatFromVal (cexpr->right->opval.val));
1388         }
1389
1390       if (IS_AST_VALUE (cexpr))
1391         {
1392         return cexpr->opval.val;
1393         }
1394
1395       if (check)
1396         werror (E_CONST_EXPECTED, "found expression");
1397
1398       return NULL;
1399     }
1400
1401   /* return the value */
1402   return cexpr->opval.val;
1403
1404 }
1405
1406 /*-----------------------------------------------------------------*/
1407 /* isLabelInAst - will return true if a given label is found       */
1408 /*-----------------------------------------------------------------*/
1409 bool 
1410 isLabelInAst (symbol * label, ast * tree)
1411 {
1412   if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1413     return FALSE;
1414
1415   if (IS_AST_OP (tree) &&
1416       tree->opval.op == LABEL &&
1417       isSymbolEqual (AST_SYMBOL (tree->left), label))
1418     return TRUE;
1419
1420   return isLabelInAst (label, tree->right) &&
1421     isLabelInAst (label, tree->left);
1422
1423 }
1424
1425 /*-----------------------------------------------------------------*/
1426 /* isLoopCountable - return true if the loop count can be determi- */
1427 /* -ned at compile time .                                          */
1428 /*-----------------------------------------------------------------*/
1429 bool 
1430 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1431                  symbol ** sym, ast ** init, ast ** end)
1432 {
1433
1434   /* the loop is considered countable if the following
1435      conditions are true :-
1436
1437      a) initExpr :- <sym> = <const>
1438      b) condExpr :- <sym> < <const1>
1439      c) loopExpr :- <sym> ++
1440    */
1441
1442   /* first check the initExpr */
1443   if (IS_AST_OP (initExpr) &&
1444       initExpr->opval.op == '=' &&      /* is assignment */
1445       IS_AST_SYM_VALUE (initExpr->left))
1446     {                           /* left is a symbol */
1447
1448       *sym = AST_SYMBOL (initExpr->left);
1449       *init = initExpr->right;
1450     }
1451   else
1452     return FALSE;
1453
1454   /* for now the symbol has to be of
1455      integral type */
1456   if (!IS_INTEGRAL ((*sym)->type))
1457     return FALSE;
1458
1459   /* now check condExpr */
1460   if (IS_AST_OP (condExpr))
1461     {
1462
1463       switch (condExpr->opval.op)
1464         {
1465         case '<':
1466           if (IS_AST_SYM_VALUE (condExpr->left) &&
1467               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1468               IS_AST_LIT_VALUE (condExpr->right))
1469             {
1470               *end = condExpr->right;
1471               break;
1472             }
1473           return FALSE;
1474
1475         case '!':
1476           if (IS_AST_OP (condExpr->left) &&
1477               condExpr->left->opval.op == '>' &&
1478               IS_AST_LIT_VALUE (condExpr->left->right) &&
1479               IS_AST_SYM_VALUE (condExpr->left->left) &&
1480               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1481             {
1482
1483               *end = newNode ('+', condExpr->left->right,
1484                               newAst_VALUE (constVal ("1")));
1485               break;
1486             }
1487           return FALSE;
1488
1489         default:
1490           return FALSE;
1491         }
1492
1493     }
1494
1495   /* check loop expression is of the form <sym>++ */
1496   if (!IS_AST_OP (loopExpr))
1497     return FALSE;
1498
1499   /* check if <sym> ++ */
1500   if (loopExpr->opval.op == INC_OP)
1501     {
1502
1503       if (loopExpr->left)
1504         {
1505           /* pre */
1506           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1507               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1508             return TRUE;
1509
1510         }
1511       else
1512         {
1513           /* post */
1514           if (IS_AST_SYM_VALUE (loopExpr->right) &&
1515               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1516             return TRUE;
1517         }
1518
1519     }
1520   else
1521     {
1522       /* check for += */
1523       if (loopExpr->opval.op == ADD_ASSIGN)
1524         {
1525
1526           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1527               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1528               IS_AST_LIT_VALUE (loopExpr->right) &&
1529               (int) AST_LIT_VALUE (loopExpr->right) != 1)
1530             return TRUE;
1531         }
1532     }
1533
1534   return FALSE;
1535 }
1536
1537 /*-----------------------------------------------------------------*/
1538 /* astHasVolatile - returns true if ast contains any volatile      */
1539 /*-----------------------------------------------------------------*/
1540 bool 
1541 astHasVolatile (ast * tree)
1542 {
1543   if (!tree)
1544     return FALSE;
1545
1546   if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1547     return TRUE;
1548
1549   if (IS_AST_OP (tree))
1550     return astHasVolatile (tree->left) ||
1551       astHasVolatile (tree->right);
1552   else
1553     return FALSE;
1554 }
1555
1556 /*-----------------------------------------------------------------*/
1557 /* astHasPointer - return true if the ast contains any ptr variable */
1558 /*-----------------------------------------------------------------*/
1559 bool 
1560 astHasPointer (ast * tree)
1561 {
1562   if (!tree)
1563     return FALSE;
1564
1565   if (IS_AST_LINK (tree))
1566     return TRUE;
1567
1568   /* if we hit an array expression then check
1569      only the left side */
1570   if (IS_AST_OP (tree) && tree->opval.op == '[')
1571     return astHasPointer (tree->left);
1572
1573   if (IS_AST_VALUE (tree))
1574     return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1575
1576   return astHasPointer (tree->left) ||
1577     astHasPointer (tree->right);
1578
1579 }
1580
1581 /*-----------------------------------------------------------------*/
1582 /* astHasSymbol - return true if the ast has the given symbol      */
1583 /*-----------------------------------------------------------------*/
1584 bool 
1585 astHasSymbol (ast * tree, symbol * sym)
1586 {
1587   if (!tree || IS_AST_LINK (tree))
1588     return FALSE;
1589
1590   if (IS_AST_VALUE (tree))
1591     {
1592       if (IS_AST_SYM_VALUE (tree))
1593         return isSymbolEqual (AST_SYMBOL (tree), sym);
1594       else
1595         return FALSE;
1596     }
1597   
1598   return astHasSymbol (tree->left, sym) ||
1599     astHasSymbol (tree->right, sym);
1600 }
1601
1602 /*-----------------------------------------------------------------*/
1603 /* astHasDeref - return true if the ast has an indirect access     */
1604 /*-----------------------------------------------------------------*/
1605 static bool 
1606 astHasDeref (ast * tree)
1607 {
1608   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1609     return FALSE;
1610
1611   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1612   
1613   return astHasDeref (tree->left) || astHasDeref (tree->right);
1614 }
1615
1616 /*-----------------------------------------------------------------*/
1617 /* isConformingBody - the loop body has to conform to a set of rules */
1618 /* for the loop to be considered reversible read on for rules      */
1619 /*-----------------------------------------------------------------*/
1620 bool 
1621 isConformingBody (ast * pbody, symbol * sym, ast * body)
1622 {
1623
1624   /* we are going to do a pre-order traversal of the
1625      tree && check for the following conditions. (essentially
1626      a set of very shallow tests )
1627      a) the sym passed does not participate in
1628      any arithmetic operation
1629      b) There are no function calls
1630      c) all jumps are within the body
1631      d) address of loop control variable not taken
1632      e) if an assignment has a pointer on the
1633      left hand side make sure right does not have
1634      loop control variable */
1635
1636   /* if we reach the end or a leaf then true */
1637   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1638     return TRUE;
1639   
1640   /* if anything else is "volatile" */
1641   if (IS_VOLATILE (TETYPE (pbody)))
1642     return FALSE;
1643
1644   /* we will walk the body in a pre-order traversal for
1645      efficiency sake */
1646   switch (pbody->opval.op)
1647     {
1648 /*------------------------------------------------------------------*/
1649     case '[':
1650       // if the loopvar is used as an index
1651       if (astHasSymbol(pbody->right, sym)) {
1652         return FALSE;
1653       }
1654       return isConformingBody (pbody->right, sym, body);
1655
1656 /*------------------------------------------------------------------*/
1657     case PTR_OP:
1658     case '.':
1659       return TRUE;
1660
1661 /*------------------------------------------------------------------*/
1662     case INC_OP:
1663     case DEC_OP:
1664
1665       /* sure we are not sym is not modified */
1666       if (pbody->left &&
1667           IS_AST_SYM_VALUE (pbody->left) &&
1668           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1669         return FALSE;
1670
1671       if (pbody->right &&
1672           IS_AST_SYM_VALUE (pbody->right) &&
1673           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1674         return FALSE;
1675
1676       return TRUE;
1677
1678 /*------------------------------------------------------------------*/
1679
1680     case '*':                   /* can be unary  : if right is null then unary operation */
1681     case '+':
1682     case '-':
1683     case '&':
1684
1685       /* if right is NULL then unary operation  */
1686 /*------------------------------------------------------------------*/
1687 /*----------------------------*/
1688       /*  address of                */
1689 /*----------------------------*/
1690       if (!pbody->right)
1691         {
1692           if (IS_AST_SYM_VALUE (pbody->left) &&
1693               isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1694             return FALSE;
1695           else
1696             return isConformingBody (pbody->left, sym, body);
1697         }
1698       else
1699         {
1700           if (astHasSymbol (pbody->left, sym) ||
1701               astHasSymbol (pbody->right, sym))
1702             return FALSE;
1703         }
1704
1705
1706 /*------------------------------------------------------------------*/
1707     case '|':
1708     case '^':
1709     case '/':
1710     case '%':
1711     case LEFT_OP:
1712     case RIGHT_OP:
1713
1714       if (IS_AST_SYM_VALUE (pbody->left) &&
1715           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1716         return FALSE;
1717
1718       if (IS_AST_SYM_VALUE (pbody->right) &&
1719           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1720         return FALSE;
1721
1722       return isConformingBody (pbody->left, sym, body) &&
1723         isConformingBody (pbody->right, sym, body);
1724
1725     case '~':
1726     case '!':
1727     case RRC:
1728     case RLC:
1729     case GETHBIT:
1730     case SWAP:
1731       if (IS_AST_SYM_VALUE (pbody->left) &&
1732           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1733         return FALSE;
1734       return isConformingBody (pbody->left, sym, body);
1735
1736 /*------------------------------------------------------------------*/
1737
1738     case AND_OP:
1739     case OR_OP:
1740     case '>':
1741     case '<':
1742     case LE_OP:
1743     case GE_OP:
1744     case EQ_OP:
1745     case NE_OP:
1746     case '?':
1747     case ':':
1748     case SIZEOF:                /* evaluate wihout code generation */
1749       
1750       if (IS_AST_SYM_VALUE (pbody->left) &&
1751           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1752         return FALSE;
1753
1754       if (IS_AST_SYM_VALUE (pbody->right) &&
1755           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1756         return FALSE;
1757
1758       return isConformingBody (pbody->left, sym, body) &&
1759         isConformingBody (pbody->right, sym, body);
1760
1761 /*------------------------------------------------------------------*/
1762     case '=':
1763
1764       /* if left has a pointer & right has loop
1765          control variable then we cannot */
1766       if (astHasPointer (pbody->left) &&
1767           astHasSymbol (pbody->right, sym))
1768         return FALSE;
1769       if (astHasVolatile (pbody->left))
1770         return FALSE;
1771
1772       if (IS_AST_SYM_VALUE (pbody->left)) {
1773         // if the loopvar has an assignment
1774         if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1775           return FALSE;
1776         // if the loopvar is used in another (maybe conditional) block
1777         if (astHasSymbol (pbody->right, sym) &&
1778             (pbody->level >= body->level)) {
1779           return FALSE;
1780         }
1781       }
1782
1783       if (astHasVolatile (pbody->left))
1784         return FALSE;
1785       
1786       if (astHasDeref(pbody->right)) return FALSE;
1787
1788       return isConformingBody (pbody->left, sym, body) &&
1789         isConformingBody (pbody->right, sym, body);
1790
1791     case MUL_ASSIGN:
1792     case DIV_ASSIGN:
1793     case AND_ASSIGN:
1794     case OR_ASSIGN:
1795     case XOR_ASSIGN:
1796     case RIGHT_ASSIGN:
1797     case LEFT_ASSIGN:
1798     case SUB_ASSIGN:
1799     case ADD_ASSIGN:
1800       assert ("Parser should not have generated this\n");
1801
1802 /*------------------------------------------------------------------*/
1803 /*----------------------------*/
1804       /*      comma operator        */
1805 /*----------------------------*/
1806     case ',':
1807       return isConformingBody (pbody->left, sym, body) &&
1808         isConformingBody (pbody->right, sym, body);
1809
1810 /*------------------------------------------------------------------*/
1811 /*----------------------------*/
1812       /*       function call        */
1813 /*----------------------------*/
1814     case CALL:
1815         /* if local & not passed as paramater then ok */
1816         if (sym->level && !astHasSymbol(pbody->right,sym)) 
1817             return TRUE;
1818       return FALSE;
1819
1820 /*------------------------------------------------------------------*/
1821 /*----------------------------*/
1822       /*     return statement       */
1823 /*----------------------------*/
1824     case RETURN:
1825       return FALSE;
1826
1827     case GOTO:
1828       if (isLabelInAst (AST_SYMBOL (pbody->left), body))
1829         return TRUE;
1830       else
1831         return FALSE;
1832     case SWITCH:
1833       if (astHasSymbol (pbody->left, sym))
1834         return FALSE;
1835
1836     default:
1837       break;
1838     }
1839
1840   return isConformingBody (pbody->left, sym, body) &&
1841     isConformingBody (pbody->right, sym, body);
1842
1843
1844
1845 }
1846
1847 /*-----------------------------------------------------------------*/
1848 /* isLoopReversible - takes a for loop as input && returns true    */
1849 /* if the for loop is reversible. If yes will set the value of     */
1850 /* the loop control var & init value & termination value           */
1851 /*-----------------------------------------------------------------*/
1852 bool
1853 isLoopReversible (ast * loop, symbol ** loopCntrl,
1854                   ast ** init, ast ** end)
1855 {
1856   /* if option says don't do it then don't */
1857   if (optimize.noLoopReverse)
1858     return 0;
1859   /* there are several tests to determine this */
1860
1861   /* for loop has to be of the form
1862      for ( <sym> = <const1> ;
1863      [<sym> < <const2>]  ;
1864      [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
1865      forBody */
1866   if (!isLoopCountable (AST_FOR (loop, initExpr),
1867                         AST_FOR (loop, condExpr),
1868                         AST_FOR (loop, loopExpr),
1869                         loopCntrl, init, end))
1870     return 0;
1871
1872   /* now do some serious checking on the body of the loop
1873    */
1874
1875   return isConformingBody (loop->left, *loopCntrl, loop->left);
1876
1877 }
1878
1879 /*-----------------------------------------------------------------*/
1880 /* replLoopSym - replace the loop sym by loop sym -1               */
1881 /*-----------------------------------------------------------------*/
1882 static void 
1883 replLoopSym (ast * body, symbol * sym)
1884 {
1885   /* reached end */
1886   if (!body || IS_AST_LINK (body))
1887     return;
1888
1889   if (IS_AST_SYM_VALUE (body))
1890     {
1891
1892       if (isSymbolEqual (AST_SYMBOL (body), sym))
1893         {
1894
1895           body->type = EX_OP;
1896           body->opval.op = '-';
1897           body->left = newAst_VALUE (symbolVal (sym));
1898           body->right = newAst_VALUE (constVal ("1"));
1899
1900         }
1901
1902       return;
1903
1904     }
1905
1906   replLoopSym (body->left, sym);
1907   replLoopSym (body->right, sym);
1908
1909 }
1910
1911 /*-----------------------------------------------------------------*/
1912 /* reverseLoop - do the actual loop reversal                       */
1913 /*-----------------------------------------------------------------*/
1914 ast *
1915 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
1916 {
1917   ast *rloop;
1918
1919   /* create the following tree
1920      <sym> = loopCount ;
1921      for_continue:
1922      forbody
1923      <sym> -= 1;
1924      if (sym) goto for_continue ;
1925      <sym> = end */
1926
1927   /* put it together piece by piece */
1928   rloop = newNode (NULLOP,
1929                    createIf (newAst_VALUE (symbolVal (sym)),
1930                              newNode (GOTO,
1931                                       newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
1932                                       NULL), NULL),
1933                    newNode ('=',
1934                             newAst_VALUE (symbolVal (sym)),
1935                             end));
1936
1937   replLoopSym (loop->left, sym);
1938   setAstLineno (rloop, init->lineno);
1939
1940   rloop = newNode (NULLOP,
1941                    newNode ('=',
1942                             newAst_VALUE (symbolVal (sym)),
1943                             newNode ('-', end, init)),
1944                    createLabel (AST_FOR (loop, continueLabel),
1945                                 newNode (NULLOP,
1946                                          loop->left,
1947                                          newNode (NULLOP,
1948                                                   newNode (SUB_ASSIGN,
1949                                                            newAst_VALUE (symbolVal (sym)),
1950                                                            newAst_VALUE (constVal ("1"))),
1951                                                   rloop))));
1952
1953   rloop->lineno=init->lineno;
1954   return decorateType (rloop);
1955
1956 }
1957
1958 /*-----------------------------------------------------------------*/
1959 /* searchLitOp - search tree (*ops only) for an ast with literal */
1960 /*-----------------------------------------------------------------*/
1961 static ast *
1962 searchLitOp (ast *tree, ast **parent, const char *ops)
1963 {
1964   ast *ret;
1965
1966   if (tree && optimize.global_cse)
1967     {
1968       /* is there a literal operand? */
1969       if (tree->right &&
1970           IS_AST_OP(tree->right) &&
1971           tree->right->right &&
1972           (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
1973         {
1974           if (IS_LITERAL (RTYPE (tree->right)) ^
1975               IS_LITERAL (LTYPE (tree->right)))
1976             {
1977               tree->right->decorated = 0;
1978               tree->decorated = 0;
1979               *parent = tree;
1980               return tree->right;
1981             }
1982           ret = searchLitOp (tree->right, parent, ops);
1983           if (ret)
1984             return ret;
1985         }
1986       if (tree->left &&
1987           IS_AST_OP(tree->left) &&
1988           tree->left->right &&
1989           (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
1990         {
1991           if (IS_LITERAL (RTYPE (tree->left)) ^
1992               IS_LITERAL (LTYPE (tree->left)))
1993             {
1994               tree->left->decorated = 0;
1995               tree->decorated = 0;
1996               *parent = tree;
1997               return tree->left;
1998             }
1999           ret = searchLitOp (tree->left, parent, ops);
2000           if (ret)
2001             return ret;
2002         }
2003     }
2004   return NULL;
2005 }
2006
2007 /*-----------------------------------------------------------------*/
2008 /* decorateType - compute type for this tree also does type checking */
2009 /*          this is done bottom up, since type have to flow upwards */
2010 /*          it also does constant folding, and paramater checking  */
2011 /*-----------------------------------------------------------------*/
2012 ast *
2013 decorateType (ast * tree)
2014 {
2015   int parmNumber;
2016   sym_link *p;
2017
2018   if (!tree)
2019     return tree;
2020
2021   /* if already has type then do nothing */
2022   if (tree->decorated)
2023     return tree;
2024
2025   tree->decorated = 1;
2026
2027 #if 0
2028   /* print the line          */
2029   /* if not block & function */
2030   if (tree->type == EX_OP &&
2031       (tree->opval.op != FUNCTION &&
2032        tree->opval.op != BLOCK &&
2033        tree->opval.op != NULLOP))
2034     {
2035       filename = tree->filename;
2036       lineno = tree->lineno;
2037     }
2038 #endif
2039
2040   /* if any child is an error | this one is an error do nothing */
2041   if (tree->isError ||
2042       (tree->left && tree->left->isError) ||
2043       (tree->right && tree->right->isError))
2044     return tree;
2045
2046 /*------------------------------------------------------------------*/
2047 /*----------------------------*/
2048   /*   leaf has been reached    */
2049 /*----------------------------*/
2050   lineno=tree->lineno;
2051   /* if this is of type value */
2052   /* just get the type        */
2053   if (tree->type == EX_VALUE)
2054     {
2055
2056       if (IS_LITERAL (tree->opval.val->etype))
2057         {
2058
2059           /* if this is a character array then declare it */
2060           if (IS_ARRAY (tree->opval.val->type))
2061             tree->opval.val = stringToSymbol (tree->opval.val);
2062
2063           /* otherwise just copy the type information */
2064           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2065           return tree;
2066         }
2067
2068       if (tree->opval.val->sym)
2069         {
2070           /* if the undefined flag is set then give error message */
2071           if (tree->opval.val->sym->undefined)
2072             {
2073               werror (E_ID_UNDEF, tree->opval.val->sym->name);
2074               /* assume int */
2075               TTYPE (tree) = TETYPE (tree) =
2076                 tree->opval.val->type = tree->opval.val->sym->type =
2077                 tree->opval.val->etype = tree->opval.val->sym->etype =
2078                 copyLinkChain (INTTYPE);
2079             }
2080           else
2081             {
2082
2083               /* if impilicit i.e. struct/union member then no type */
2084               if (tree->opval.val->sym->implicit)
2085                 TTYPE (tree) = TETYPE (tree) = NULL;
2086
2087               else
2088                 {
2089
2090                   /* else copy the type */
2091                   COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2092
2093                   /* and mark it as referenced */
2094                   tree->opval.val->sym->isref = 1;
2095                 }
2096             }
2097         }
2098
2099       return tree;
2100     }
2101
2102   /* if type link for the case of cast */
2103   if (tree->type == EX_LINK)
2104     {
2105       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2106       return tree;
2107     }
2108
2109   {
2110     ast *dtl, *dtr;
2111
2112     #if 0
2113     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2114       {
2115         if (tree->left && tree->left->type == EX_OPERAND
2116             && (tree->left->opval.op == INC_OP
2117                 || tree->left->opval.op == DEC_OP)
2118             && tree->left->left)
2119           {
2120             tree->left->right = tree->left->left;
2121             tree->left->left = NULL;
2122           }
2123         if (tree->right && tree->right->type == EX_OPERAND
2124             && (tree->right->opval.op == INC_OP
2125                 || tree->right->opval.op == DEC_OP)
2126             && tree->right->left)
2127           {
2128             tree->right->right = tree->right->left;
2129             tree->right->left = NULL;
2130           }
2131       }
2132     #endif
2133     
2134     dtl = decorateType (tree->left);
2135     /* delay right side for '?' operator since conditional macro expansions might
2136        rely on this */
2137     dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right));
2138
2139     /* this is to take care of situations
2140        when the tree gets rewritten */
2141     if (dtl != tree->left)
2142       tree->left = dtl;
2143     if (dtr != tree->right)
2144       tree->right = dtr;
2145     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2146       return tree;
2147
2148     if (IS_AST_OP(tree) &&
2149         (tree->opval.op == CAST || tree->opval.op == '=') &&
2150         (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
2151         (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) {
2152       // this is a cast/assign to a bigger type
2153       if (IS_AST_OP(tree->right) &&
2154           IS_INTEGRAL(tree->right->ftype) &&
2155           (tree->right->opval.op == LEFT_OP ||
2156            tree->right->opval.op == '*' ||
2157            tree->right->opval.op == '+' ||
2158            tree->right->opval.op == '-') &&
2159           tree->right->right) {
2160         // we should cast an operand instead of the result
2161         tree->right->decorated = 0;
2162         tree->right->left = newNode( CAST, newAst_LINK(newIntLink()),
2163                                      tree->right->left);
2164         tree->right = decorateType(tree->right);
2165       }
2166     }
2167   }
2168
2169   /* depending on type of operator do */
2170
2171   switch (tree->opval.op)
2172     {
2173         /*------------------------------------------------------------------*/
2174         /*----------------------------*/
2175         /*        array node          */
2176         /*----------------------------*/
2177     case '[':
2178
2179       /* determine which is the array & which the index */
2180       if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && IS_INTEGRAL (LTYPE (tree)))
2181         {
2182
2183           ast *tempTree = tree->left;
2184           tree->left = tree->right;
2185           tree->right = tempTree;
2186         }
2187
2188       /* first check if this is a array or a pointer */
2189       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2190         {
2191           werror (E_NEED_ARRAY_PTR, "[]");
2192           goto errorTreeReturn;
2193         }
2194
2195       /* check if the type of the idx */
2196       if (!IS_INTEGRAL (RTYPE (tree)))
2197         {
2198           werror (E_IDX_NOT_INT);
2199           goto errorTreeReturn;
2200         }
2201
2202       /* if the left is an rvalue then error */
2203       if (LRVAL (tree))
2204         {
2205           werror (E_LVALUE_REQUIRED, "array access");
2206           goto errorTreeReturn;
2207         }
2208       RRVAL (tree) = 1;
2209       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2210       return tree;
2211
2212       /*------------------------------------------------------------------*/
2213       /*----------------------------*/
2214       /*      struct/union          */
2215       /*----------------------------*/
2216     case '.':
2217       /* if this is not a structure */
2218       if (!IS_STRUCT (LTYPE (tree)))
2219         {
2220           werror (E_STRUCT_UNION, ".");
2221           goto errorTreeReturn;
2222         }
2223       TTYPE (tree) = structElemType (LTYPE (tree),
2224                                      (tree->right->type == EX_VALUE ?
2225                                tree->right->opval.val : NULL));
2226       TETYPE (tree) = getSpec (TTYPE (tree));
2227       return tree;
2228
2229       /*------------------------------------------------------------------*/
2230       /*----------------------------*/
2231       /*    struct/union pointer    */
2232       /*----------------------------*/
2233     case PTR_OP:
2234       /* if not pointer to a structure */
2235       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2236         {
2237           werror (E_PTR_REQD);
2238           goto errorTreeReturn;
2239         }
2240
2241       if (!IS_STRUCT (LTYPE (tree)->next))
2242         {
2243           werror (E_STRUCT_UNION, "->");
2244           goto errorTreeReturn;
2245         }
2246
2247       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2248                                      (tree->right->type == EX_VALUE ?
2249                                tree->right->opval.val : NULL));
2250       TETYPE (tree) = getSpec (TTYPE (tree));
2251
2252       /* adjust the storage class */
2253       switch (DCL_TYPE(tree->left->ftype)) {
2254       case POINTER:
2255         SPEC_SCLS(TETYPE(tree)) = S_DATA; 
2256         break;
2257       case FPOINTER:
2258         SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2259         break;
2260       case CPOINTER:
2261         SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2262         break;
2263       case GPOINTER:
2264         SPEC_SCLS (TETYPE (tree)) = 0;
2265         break;
2266       case PPOINTER:
2267         SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2268         break;
2269       case IPOINTER:
2270         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2271         break;
2272       case EEPPOINTER:
2273         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2274         break;
2275       case UPOINTER:
2276         SPEC_SCLS (TETYPE (tree)) = 0;
2277         break;
2278       case ARRAY:
2279       case FUNCTION:
2280         break;
2281       }
2282       
2283       /* This breaks with extern declarations, bitfields, and perhaps other */
2284       /* cases (gcse). Let's leave this optimization disabled for now and   */
2285       /* ponder if there's a safe way to do this. -- EEP                    */
2286       #if 0
2287       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2288           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2289         {
2290             /* If defined    struct type at addr var
2291                then rewrite  (&struct var)->member
2292                as            temp
2293                and define    membertype at (addr+offsetof(struct var,member)) temp
2294             */
2295             symbol *sym;
2296             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2297                                                 AST_SYMBOL(tree->right));
2298
2299             sym = newSymbol(genSymName (0), 0);
2300             sym->type = TTYPE (tree);
2301             sym->etype = getSpec(sym->type);
2302             sym->lineDef = tree->lineno;
2303             sym->cdef = 1;
2304             sym->isref = 1;
2305             SPEC_STAT (sym->etype) = 1;
2306             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2307                                      + element->offset;
2308             SPEC_ABSA(sym->etype) = 1;
2309             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2310             allocGlobal (sym);
2311             
2312             AST_VALUE (tree) = symbolVal(sym);
2313             TLVAL (tree) = 1;
2314             TRVAL (tree) = 0;
2315             tree->type = EX_VALUE;
2316             tree->left = NULL;
2317             tree->right = NULL;
2318         }
2319       #endif
2320       
2321       return tree;
2322
2323       /*------------------------------------------------------------------*/
2324       /*----------------------------*/
2325       /*  ++/-- operation           */
2326       /*----------------------------*/
2327     case INC_OP:
2328     case DEC_OP:
2329       {
2330         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2331         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2332         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2333           werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2334
2335         if (tree->right)
2336           RLVAL (tree) = 1;
2337         else
2338           LLVAL (tree) = 1;
2339         return tree;
2340       }
2341
2342       /*------------------------------------------------------------------*/
2343       /*----------------------------*/
2344       /*  bitwise and               */
2345       /*----------------------------*/
2346     case '&':                   /* can be unary   */
2347       /* if right is NULL then unary operation  */
2348       if (tree->right)          /* not an unary operation */
2349         {
2350
2351           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2352             {
2353               werror (E_BITWISE_OP);
2354               werror (W_CONTINUE, "left & right types are ");
2355               printTypeChain (LTYPE (tree), stderr);
2356               fprintf (stderr, ",");
2357               printTypeChain (RTYPE (tree), stderr);
2358               fprintf (stderr, "\n");
2359               goto errorTreeReturn;
2360             }
2361
2362           /* if they are both literal */
2363           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2364             {
2365               tree->type = EX_VALUE;
2366               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2367                                           valFromType (RETYPE (tree)), '&');
2368
2369               tree->right = tree->left = NULL;
2370               TETYPE (tree) = tree->opval.val->etype;
2371               TTYPE (tree) = tree->opval.val->type;
2372               return tree;
2373             }
2374
2375           /* see if this is a GETHBIT operation if yes
2376              then return that */
2377           {
2378             ast *otree = optimizeGetHbit (tree);
2379
2380             if (otree != tree)
2381               return decorateType (otree);
2382           }
2383
2384           TTYPE (tree) =
2385             computeType (LTYPE (tree), RTYPE (tree), FALSE);
2386           TETYPE (tree) = getSpec (TTYPE (tree));
2387
2388           /* if left is a literal exchange left & right */
2389           if (IS_LITERAL (LTYPE (tree)))
2390             {
2391               ast *tTree = tree->left;
2392               tree->left = tree->right;
2393               tree->right = tTree;
2394             }
2395
2396           /* if right is a literal and */
2397           /* we can find a 2nd literal in a and-tree then */
2398           /* rearrange the tree */
2399           if (IS_LITERAL (RTYPE (tree)))
2400             {
2401               ast *parent;
2402               ast *litTree = searchLitOp (tree, &parent, "&");
2403               if (litTree)
2404                 {
2405                   ast *tTree = litTree->left;
2406                   litTree->left = tree->right;
2407                   tree->right = tTree;
2408                   /* both operands in tTree are literal now */
2409                   decorateType (parent);
2410                 }
2411             }
2412
2413           LRVAL (tree) = RRVAL (tree) = 1;
2414           return tree;
2415         }
2416
2417       /*------------------------------------------------------------------*/
2418       /*----------------------------*/
2419       /*  address of                */
2420       /*----------------------------*/
2421       p = newLink (DECLARATOR);
2422       /* if bit field then error */
2423       if (IS_BITVAR (tree->left->etype))
2424         {
2425           werror (E_ILLEGAL_ADDR, "address of bit variable");
2426           goto errorTreeReturn;
2427         }
2428
2429       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2430         {
2431           werror (E_ILLEGAL_ADDR, "address of register variable");
2432           goto errorTreeReturn;
2433         }
2434
2435       if (IS_FUNC (LTYPE (tree)))
2436         {
2437           // this ought to be ignored
2438           return (tree->left);
2439         }
2440
2441       if (IS_LITERAL(LTYPE(tree)))
2442         {
2443           werror (E_ILLEGAL_ADDR, "address of literal");
2444           goto errorTreeReturn;
2445         }
2446
2447      if (LRVAL (tree))
2448         {
2449           werror (E_LVALUE_REQUIRED, "address of");
2450           goto errorTreeReturn;
2451         }
2452       if (!LETYPE (tree))
2453         DCL_TYPE (p) = POINTER;
2454       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2455         DCL_TYPE (p) = CPOINTER;
2456       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2457         DCL_TYPE (p) = FPOINTER;
2458       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2459         DCL_TYPE (p) = PPOINTER;
2460       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2461         DCL_TYPE (p) = IPOINTER;
2462       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2463         DCL_TYPE (p) = EEPPOINTER;
2464       else if (SPEC_OCLS(tree->left->etype))
2465           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2466       else
2467           DCL_TYPE (p) = POINTER;
2468
2469       if (IS_AST_SYM_VALUE (tree->left))
2470         {
2471           AST_SYMBOL (tree->left)->addrtaken = 1;
2472           AST_SYMBOL (tree->left)->allocreq = 1;
2473         }
2474
2475       p->next = LTYPE (tree);
2476       TTYPE (tree) = p;
2477       TETYPE (tree) = getSpec (TTYPE (tree));
2478       LLVAL (tree) = 1;
2479       TLVAL (tree) = 1;
2480
2481       #if 0
2482       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2483           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2484         {
2485           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2486                                       AST_SYMBOL(tree->left->right));
2487           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2488                                     valueFromLit(element->offset));
2489           tree->left = NULL;
2490           tree->right = NULL;
2491           tree->type = EX_VALUE;
2492           tree->values.literalFromCast = 1;
2493         }
2494       #endif
2495
2496       return tree;
2497
2498       /*------------------------------------------------------------------*/
2499       /*----------------------------*/
2500       /*  bitwise or                */
2501       /*----------------------------*/
2502     case '|':
2503       /* if the rewrite succeeds then don't go any furthur */
2504       {
2505         ast *wtree = optimizeRRCRLC (tree);
2506         if (wtree != tree)
2507           return decorateType (wtree);
2508         
2509         wtree = optimizeSWAP (tree);
2510         if (wtree != tree)
2511           return decorateType (wtree);
2512         
2513         // fall through
2514       }
2515
2516       /* if left is a literal exchange left & right */
2517       if (IS_LITERAL (LTYPE (tree)))
2518         {
2519           ast *tTree = tree->left;
2520           tree->left = tree->right;
2521           tree->right = tTree;
2522         }
2523
2524       /* if right is a literal and */
2525       /* we can find a 2nd literal in a or-tree then */
2526       /* rearrange the tree */
2527       if (IS_LITERAL (RTYPE (tree)))
2528         {
2529           ast *parent;
2530           ast *litTree = searchLitOp (tree, &parent, "|");
2531           if (litTree)
2532             {
2533               ast *tTree = litTree->left;
2534               litTree->left = tree->right;
2535               tree->right = tTree;
2536               /* both operands in tTree are literal now */
2537               decorateType (parent);
2538             }
2539         }
2540       /*------------------------------------------------------------------*/
2541       /*----------------------------*/
2542       /*  bitwise xor               */
2543       /*----------------------------*/
2544     case '^':
2545       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2546         {
2547           werror (E_BITWISE_OP);
2548           werror (W_CONTINUE, "left & right types are ");
2549           printTypeChain (LTYPE (tree), stderr);
2550           fprintf (stderr, ",");
2551           printTypeChain (RTYPE (tree), stderr);
2552           fprintf (stderr, "\n");
2553           goto errorTreeReturn;
2554         }
2555
2556       /* if they are both literal then */
2557       /* rewrite the tree */
2558       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2559         {
2560           tree->type = EX_VALUE;
2561           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2562                                         valFromType (RETYPE (tree)),
2563                                         tree->opval.op);
2564           tree->right = tree->left = NULL;
2565           TETYPE (tree) = tree->opval.val->etype;
2566           TTYPE (tree) = tree->opval.val->type;
2567           return tree;
2568         }
2569
2570       /* if left is a literal exchange left & right */
2571       if (IS_LITERAL (LTYPE (tree)))
2572         {
2573           ast *tTree = tree->left;
2574           tree->left = tree->right;
2575           tree->right = tTree;
2576         }
2577
2578       /* if right is a literal and */
2579       /* we can find a 2nd literal in a xor-tree then */
2580       /* rearrange the tree */
2581       if (IS_LITERAL (RTYPE (tree)))
2582         {
2583           ast *parent;
2584           ast *litTree = searchLitOp (tree, &parent, "^");
2585           if (litTree)
2586             {
2587               ast *tTree = litTree->left;
2588               litTree->left = tree->right;
2589               tree->right = tTree;
2590               /* both operands in litTree are literal now */
2591               decorateType (parent);
2592             }
2593         }
2594
2595       LRVAL (tree) = RRVAL (tree) = 1;
2596       TETYPE (tree) = getSpec (TTYPE (tree) =
2597                                computeType (LTYPE (tree),
2598                                             RTYPE (tree),
2599                                             FALSE));
2600
2601       /*------------------------------------------------------------------*/
2602       /*----------------------------*/
2603       /*  division                  */
2604       /*----------------------------*/
2605     case '/':
2606       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2607         {
2608           werror (E_INVALID_OP, "divide");
2609           goto errorTreeReturn;
2610         }
2611       /* if they are both literal then */
2612       /* rewrite the tree */
2613       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2614         {
2615           tree->type = EX_VALUE;
2616           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
2617                                     valFromType (RETYPE (tree)));
2618           tree->right = tree->left = NULL;
2619           TETYPE (tree) = getSpec (TTYPE (tree) =
2620                                    tree->opval.val->type);
2621           return tree;
2622         }
2623
2624       LRVAL (tree) = RRVAL (tree) = 1;
2625       TETYPE (tree) = getSpec (TTYPE (tree) =
2626                                computeType (LTYPE (tree),
2627                                             RTYPE (tree),
2628                                             TRUE));
2629
2630       /* if right is a literal and */
2631       /* left is also a division by a literal then */
2632       /* rearrange the tree */
2633       if (IS_LITERAL (RTYPE (tree))
2634           /* avoid infinite loop */
2635           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
2636         {
2637           ast *parent;
2638           ast *litTree = searchLitOp (tree, &parent, "/");
2639           if (litTree)
2640             {
2641               if (IS_LITERAL (RTYPE (litTree)))
2642                 {
2643                   /* foo_div */
2644                   litTree->right = newNode ('*', litTree->right, tree->right);
2645                   litTree->right->lineno = tree->lineno;
2646
2647                   tree->right->opval.val = constVal ("1");
2648                   decorateType (parent);
2649                 }
2650               else
2651                 {
2652                   /* litTree->left is literal: no gcse possible.
2653                      We can't call decorateType(parent), because
2654                      this would cause an infinit loop. */
2655                   parent->decorated = 1;
2656                   decorateType (litTree);
2657                 }
2658             }
2659         }
2660
2661       return tree;
2662
2663       /*------------------------------------------------------------------*/
2664       /*----------------------------*/
2665       /*            modulus         */
2666       /*----------------------------*/
2667     case '%':
2668       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2669         {
2670           werror (E_BITWISE_OP);
2671           werror (W_CONTINUE, "left & right types are ");
2672           printTypeChain (LTYPE (tree), stderr);
2673           fprintf (stderr, ",");
2674           printTypeChain (RTYPE (tree), stderr);
2675           fprintf (stderr, "\n");
2676           goto errorTreeReturn;
2677         }
2678       /* if they are both literal then */
2679       /* rewrite the tree */
2680       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2681         {
2682           tree->type = EX_VALUE;
2683           tree->opval.val = valMod (valFromType (LETYPE (tree)),
2684                                     valFromType (RETYPE (tree)));
2685           tree->right = tree->left = NULL;
2686           TETYPE (tree) = getSpec (TTYPE (tree) =
2687                                    tree->opval.val->type);
2688           return tree;
2689         }
2690       LRVAL (tree) = RRVAL (tree) = 1;
2691       TETYPE (tree) = getSpec (TTYPE (tree) =
2692                                computeType (LTYPE (tree),
2693                                             RTYPE (tree),
2694                                             TRUE));
2695       return tree;
2696
2697       /*------------------------------------------------------------------*/
2698       /*----------------------------*/
2699       /*  address dereference       */
2700       /*----------------------------*/
2701     case '*':                   /* can be unary  : if right is null then unary operation */
2702       if (!tree->right)
2703         {
2704           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2705             {
2706               werror (E_PTR_REQD);
2707               goto errorTreeReturn;
2708             }
2709
2710           if (LRVAL (tree))
2711             {
2712               werror (E_LVALUE_REQUIRED, "pointer deref");
2713               goto errorTreeReturn;
2714             }
2715           if (IS_ADDRESS_OF_OP(tree->left))
2716             {
2717               /* replace *&obj with obj */
2718               return tree->left->left;
2719             }
2720           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
2721           TETYPE (tree) = getSpec (TTYPE (tree));
2722           /* adjust the storage class */
2723           switch (DCL_TYPE(tree->left->ftype)) {
2724             case POINTER:
2725               SPEC_SCLS(TETYPE(tree)) = S_DATA;
2726               break;
2727             case FPOINTER:
2728               SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2729               break;
2730             case CPOINTER:
2731               SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2732               break;
2733             case GPOINTER:
2734               SPEC_SCLS (TETYPE (tree)) = 0;
2735               break;
2736             case PPOINTER:
2737               SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2738               break;
2739             case IPOINTER:
2740               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2741               break;
2742             case EEPPOINTER:
2743               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2744               break;
2745             case UPOINTER:
2746               SPEC_SCLS (TETYPE (tree)) = 0;
2747               break;
2748             case ARRAY:
2749             case FUNCTION:
2750               break;
2751           }
2752           return tree;
2753         }
2754
2755       /*------------------------------------------------------------------*/
2756       /*----------------------------*/
2757       /*      multiplication        */
2758       /*----------------------------*/
2759       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2760         {
2761           werror (E_INVALID_OP, "multiplication");
2762           goto errorTreeReturn;
2763         }
2764
2765       /* if they are both literal then */
2766       /* rewrite the tree */
2767       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2768         {
2769           tree->type = EX_VALUE;
2770           tree->opval.val = valMult (valFromType (LETYPE (tree)),
2771                                      valFromType (RETYPE (tree)));
2772           tree->right = tree->left = NULL;
2773           TETYPE (tree) = getSpec (TTYPE (tree) =
2774                                    tree->opval.val->type);
2775           return tree;
2776         }
2777
2778       /* if left is a literal exchange left & right */
2779       if (IS_LITERAL (LTYPE (tree)))
2780         {
2781           ast *tTree = tree->left;
2782           tree->left = tree->right;
2783           tree->right = tTree;
2784         }
2785
2786       /* if right is a literal and */
2787       /* we can find a 2nd literal in a mul-tree then */
2788       /* rearrange the tree */
2789       if (IS_LITERAL (RTYPE (tree)))
2790         {
2791           ast *parent;
2792           ast *litTree = searchLitOp (tree, &parent, "*");
2793           if (litTree)
2794             {
2795               ast *tTree = litTree->left;
2796               litTree->left = tree->right;
2797               tree->right = tTree;
2798               /* both operands in litTree are literal now */
2799               decorateType (parent);
2800             }
2801         }
2802
2803       LRVAL (tree) = RRVAL (tree) = 1;
2804       TETYPE (tree) = getSpec (TTYPE (tree) =
2805                                computeType (LTYPE (tree),
2806                                             RTYPE (tree),
2807                                             TRUE));
2808
2809       /* promote result to int if left & right are char
2810          this will facilitate hardware multiplies 8bit x 8bit = 16bit */
2811       /* now done by computeType
2812       if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
2813         SPEC_NOUN(TETYPE(tree)) = V_INT;
2814       }
2815       */
2816
2817       return tree;
2818
2819       /*------------------------------------------------------------------*/
2820       /*----------------------------*/
2821       /*    unary '+' operator      */
2822       /*----------------------------*/
2823     case '+':
2824       /* if unary plus */
2825       if (!tree->right)
2826         {
2827           if (!IS_ARITHMETIC (LTYPE (tree)))
2828             {
2829               werror (E_UNARY_OP, '+');
2830               goto errorTreeReturn;
2831             }
2832
2833           /* if left is a literal then do it */
2834           if (IS_LITERAL (LTYPE (tree)))
2835             {
2836               tree->type = EX_VALUE;
2837               tree->opval.val = valFromType (LETYPE (tree));
2838               tree->left = NULL;
2839               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2840               return tree;
2841             }
2842           LRVAL (tree) = 1;
2843           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
2844           return tree;
2845         }
2846
2847       /*------------------------------------------------------------------*/
2848       /*----------------------------*/
2849       /*      addition              */
2850       /*----------------------------*/
2851
2852       /* this is not a unary operation */
2853       /* if both pointers then problem */
2854       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
2855           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
2856         {
2857           werror (E_PTR_PLUS_PTR);
2858           goto errorTreeReturn;
2859         }
2860
2861       if (!IS_ARITHMETIC (LTYPE (tree)) &&
2862           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2863         {
2864           werror (E_PLUS_INVALID, "+");
2865           goto errorTreeReturn;
2866         }
2867
2868       if (!IS_ARITHMETIC (RTYPE (tree)) &&
2869           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
2870         {
2871           werror (E_PLUS_INVALID, "+");
2872           goto errorTreeReturn;
2873         }
2874       /* if they are both literal then */
2875       /* rewrite the tree */
2876       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2877         {
2878           tree->type = EX_VALUE;
2879           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
2880                                      valFromType (RETYPE (tree)));
2881           tree->right = tree->left = NULL;
2882           TETYPE (tree) = getSpec (TTYPE (tree) =
2883                                    tree->opval.val->type);
2884           return tree;
2885         }
2886
2887       /* if the right is a pointer or left is a literal
2888          xchange left & right */
2889       if (IS_ARRAY (RTYPE (tree)) ||
2890           IS_PTR (RTYPE (tree)) ||
2891           IS_LITERAL (LTYPE (tree)))
2892         {
2893           ast *tTree = tree->left;
2894           tree->left = tree->right;
2895           tree->right = tTree;
2896         }
2897
2898       /* if right is a literal and */
2899       /* left is also an addition/subtraction with a literal then */
2900       /* rearrange the tree */
2901       if (IS_LITERAL (RTYPE (tree)))
2902         {
2903           ast *litTree, *parent;
2904           litTree = searchLitOp (tree, &parent, "+-");
2905           if (litTree)
2906             {
2907               if (litTree->opval.op == '+')
2908                 {
2909                   /* foo_aa */
2910                   ast *tTree = litTree->left;
2911                   litTree->left = tree->right;
2912                   tree->right = tree->left;
2913                   tree->left = tTree;
2914                 }
2915               else if (litTree->opval.op == '-')
2916                 {
2917                   if (IS_LITERAL (RTYPE (litTree)))
2918                     {
2919                       /* foo_asr */
2920                       ast *tTree = litTree->left;
2921                       litTree->left = tree->right;
2922                       tree->right = tTree;
2923                     }
2924                   else
2925                     {
2926                       /* foo_asl */
2927                       ast *tTree = litTree->right;
2928                       litTree->right = tree->right;
2929                       tree->right = tTree;
2930                       litTree->opval.op = '+';
2931                       tree->opval.op = '-';
2932                     }
2933                 }
2934               decorateType (parent);
2935             }
2936         }
2937
2938       LRVAL (tree) = RRVAL (tree) = 1;
2939       /* if the left is a pointer */
2940       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
2941         TETYPE (tree) = getSpec (TTYPE (tree) =
2942                                  LTYPE (tree));
2943       else
2944         TETYPE (tree) = getSpec (TTYPE (tree) =
2945                                  computeType (LTYPE (tree),
2946                                               RTYPE (tree),
2947                                               FALSE));
2948       return tree;
2949
2950       /*------------------------------------------------------------------*/
2951       /*----------------------------*/
2952       /*      unary '-'             */
2953       /*----------------------------*/
2954     case '-':                   /* can be unary   */
2955       /* if right is null then unary */
2956       if (!tree->right)
2957         {
2958
2959           if (!IS_ARITHMETIC (LTYPE (tree)))
2960             {
2961               werror (E_UNARY_OP, tree->opval.op);
2962               goto errorTreeReturn;
2963             }
2964
2965           /* if left is a literal then do it */
2966           if (IS_LITERAL (LTYPE (tree)))
2967             {
2968               tree->type = EX_VALUE;
2969               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
2970               tree->left = NULL;
2971               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2972               SPEC_USIGN(TETYPE(tree)) = 0;
2973               return tree;
2974             }
2975           LRVAL (tree) = 1;
2976           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
2977           return tree;
2978         }
2979
2980       /*------------------------------------------------------------------*/
2981       /*----------------------------*/
2982       /*    subtraction             */
2983       /*----------------------------*/
2984
2985       if (!(IS_PTR (LTYPE (tree)) ||
2986             IS_ARRAY (LTYPE (tree)) ||
2987             IS_ARITHMETIC (LTYPE (tree))))
2988         {
2989           werror (E_PLUS_INVALID, "-");
2990           goto errorTreeReturn;
2991         }
2992
2993       if (!(IS_PTR (RTYPE (tree)) ||
2994             IS_ARRAY (RTYPE (tree)) ||
2995             IS_ARITHMETIC (RTYPE (tree))))
2996         {
2997           werror (E_PLUS_INVALID, "-");
2998           goto errorTreeReturn;
2999         }
3000
3001       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3002           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3003             IS_INTEGRAL (RTYPE (tree))))
3004         {
3005           werror (E_PLUS_INVALID, "-");
3006           goto errorTreeReturn;
3007         }
3008
3009       /* if they are both literal then */
3010       /* rewrite the tree */
3011       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3012         {
3013           tree->type = EX_VALUE;
3014           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3015                                       valFromType (RETYPE (tree)));
3016           tree->right = tree->left = NULL;
3017           TETYPE (tree) = getSpec (TTYPE (tree) =
3018                                    tree->opval.val->type);
3019           return tree;
3020         }
3021
3022       /* if the left & right are equal then zero */
3023       if (isAstEqual (tree->left, tree->right))
3024         {
3025           tree->type = EX_VALUE;
3026           tree->left = tree->right = NULL;
3027           tree->opval.val = constVal ("0");
3028           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3029           return tree;
3030         }
3031
3032       /* if both of them are pointers or arrays then */
3033       /* the result is going to be an integer        */
3034       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3035           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3036         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3037       else
3038         /* if only the left is a pointer */
3039         /* then result is a pointer      */
3040       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3041         TETYPE (tree) = getSpec (TTYPE (tree) =
3042                                  LTYPE (tree));
3043       else
3044         TETYPE (tree) = getSpec (TTYPE (tree) =
3045                                  computeType (LTYPE (tree),
3046                                               RTYPE (tree),
3047                                               FALSE));
3048
3049       LRVAL (tree) = RRVAL (tree) = 1;
3050
3051       /* if right is a literal and */
3052       /* left is also an addition/subtraction with a literal then */
3053       /* rearrange the tree */
3054       if (IS_LITERAL (RTYPE (tree))
3055           /* avoid infinite loop */
3056           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
3057         {
3058           ast *litTree, *litParent;
3059           litTree = searchLitOp (tree, &litParent, "+-");
3060           if (litTree)
3061             {
3062               if (litTree->opval.op == '+')
3063                 {
3064                   /* foo_sa */
3065                   litTree->right = newNode ('-', litTree->right, tree->right);
3066                   litTree->right->lineno = tree->lineno;
3067
3068                   tree->right->opval.val = constVal ("0");
3069                 }
3070               else if (litTree->opval.op == '-')
3071                 {
3072                   if (IS_LITERAL (RTYPE (litTree)))
3073                     {
3074                       /* foo_ssr */
3075                       litTree->right = newNode ('+', tree->right, litTree->right);
3076                       litTree->right->lineno = tree->lineno;
3077
3078                       tree->right->opval.val = constVal ("0");
3079                     }
3080                   else
3081                     {
3082                       /* foo_ssl */
3083                       ast *tTree = litTree->right;
3084                       litTree->right = tree->right;
3085                       tree->right = tTree;
3086                     }
3087                 }
3088               decorateType (litParent);
3089             }
3090         }
3091       return tree;
3092
3093       /*------------------------------------------------------------------*/
3094       /*----------------------------*/
3095       /*    complement              */
3096       /*----------------------------*/
3097     case '~':
3098       /* can be only integral type */
3099       if (!IS_INTEGRAL (LTYPE (tree)))
3100         {
3101           werror (E_UNARY_OP, tree->opval.op);
3102           goto errorTreeReturn;
3103         }
3104
3105       /* if left is a literal then do it */
3106       if (IS_LITERAL (LTYPE (tree)))
3107         {
3108           tree->type = EX_VALUE;
3109           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3110           tree->left = NULL;
3111           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3112           return tree;
3113         }
3114       LRVAL (tree) = 1;
3115       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3116       return tree;
3117
3118       /*------------------------------------------------------------------*/
3119       /*----------------------------*/
3120       /*           not              */
3121       /*----------------------------*/
3122     case '!':
3123       /* can be pointer */
3124       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3125           !IS_PTR (LTYPE (tree)) &&
3126           !IS_ARRAY (LTYPE (tree)))
3127         {
3128           werror (E_UNARY_OP, tree->opval.op);
3129           goto errorTreeReturn;
3130         }
3131
3132       /* if left is a literal then do it */
3133       if (IS_LITERAL (LTYPE (tree)))
3134         {
3135           tree->type = EX_VALUE;
3136           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3137           tree->left = NULL;
3138           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3139           return tree;
3140         }
3141       LRVAL (tree) = 1;
3142       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3143       return tree;
3144
3145       /*------------------------------------------------------------------*/
3146       /*----------------------------*/
3147       /*           shift            */
3148       /*----------------------------*/
3149     case RRC:
3150     case RLC:
3151     case SWAP:
3152       TTYPE (tree) = LTYPE (tree);
3153       TETYPE (tree) = LETYPE (tree);
3154       return tree;
3155
3156     case GETHBIT:
3157       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3158       return tree;
3159
3160     case LEFT_OP:
3161     case RIGHT_OP:
3162       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3163         {
3164           werror (E_SHIFT_OP_INVALID);
3165           werror (W_CONTINUE, "left & right types are ");
3166           printTypeChain (LTYPE (tree), stderr);
3167           fprintf (stderr, ",");
3168           printTypeChain (RTYPE (tree), stderr);
3169           fprintf (stderr, "\n");
3170           goto errorTreeReturn;
3171         }
3172
3173       /* if they are both literal then */
3174       /* rewrite the tree */
3175       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3176         {
3177           tree->type = EX_VALUE;
3178           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3179                                       valFromType (RETYPE (tree)),
3180                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3181           tree->right = tree->left = NULL;
3182           TETYPE (tree) = getSpec (TTYPE (tree) =
3183                                    tree->opval.val->type);
3184           return tree;
3185         }
3186
3187       /* if only the right side is a literal & we are
3188          shifting more than size of the left operand then zero */
3189       if (IS_LITERAL (RTYPE (tree)) &&
3190           ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
3191           (getSize (LTYPE (tree)) * 8))
3192         {
3193           if (tree->opval.op==LEFT_OP ||
3194               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) {
3195             lineno=tree->lineno;
3196             werror (W_SHIFT_CHANGED,
3197                     (tree->opval.op == LEFT_OP ? "left" : "right"));
3198             tree->type = EX_VALUE;
3199             tree->left = tree->right = NULL;
3200             tree->opval.val = constVal ("0");
3201             TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3202             return tree;
3203           }
3204         }
3205       LRVAL (tree) = RRVAL (tree) = 1;
3206       TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3207       if (IS_LITERAL (TTYPE (tree)))
3208         SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3209       return tree;
3210
3211       /*------------------------------------------------------------------*/
3212       /*----------------------------*/
3213       /*         casting            */
3214       /*----------------------------*/
3215     case CAST:                  /* change the type   */
3216       /* cannot cast to an aggregate type */
3217       if (IS_AGGREGATE (LTYPE (tree)))
3218         {
3219           werror (E_CAST_ILLEGAL);
3220           goto errorTreeReturn;
3221         }
3222
3223       /* make sure the type is complete and sane */
3224       checkTypeSanity(LETYPE(tree), "(cast)");
3225
3226 #if 0
3227       /* if the right is a literal replace the tree */
3228       if (IS_LITERAL (RETYPE (tree))) {
3229               if (!IS_PTR (LTYPE (tree))) {
3230                       tree->type = EX_VALUE;
3231                       tree->opval.val =
3232                               valCastLiteral (LTYPE (tree),
3233                                               floatFromVal (valFromType (RETYPE (tree))));
3234                       tree->left = NULL;
3235                       tree->right = NULL;
3236                       TTYPE (tree) = tree->opval.val->type;
3237                       tree->values.literalFromCast = 1;
3238               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3239                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3240                       sym_link *rest = LTYPE(tree)->next;
3241                       werror(W_LITERAL_GENERIC);
3242                       TTYPE(tree) = newLink(DECLARATOR);
3243                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3244                       TTYPE(tree)->next = rest;
3245                       tree->left->opval.lnk = TTYPE(tree);
3246                       LRVAL (tree) = 1;
3247               } else {
3248                       TTYPE (tree) = LTYPE (tree);
3249                       LRVAL (tree) = 1;
3250               }
3251       } else {
3252               TTYPE (tree) = LTYPE (tree);
3253               LRVAL (tree) = 1;
3254       }
3255 #else
3256 #if 0 // this is already checked, now this could be explicit
3257       /* if pointer to struct then check names */
3258       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3259           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3260           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3261         {
3262           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3263                  SPEC_STRUCT(LETYPE(tree))->tag);
3264         }
3265 #endif
3266       if (IS_ADDRESS_OF_OP(tree->right)
3267           && IS_AST_SYM_VALUE (tree->right->left)
3268           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3269
3270         tree->type = EX_VALUE;
3271         tree->opval.val =
3272           valCastLiteral (LTYPE (tree),
3273                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3274         TTYPE (tree) = tree->opval.val->type;
3275         TETYPE (tree) = getSpec (TTYPE (tree));
3276         tree->left = NULL;
3277         tree->right = NULL;
3278         tree->values.literalFromCast = 1;
3279         return tree;
3280       }
3281
3282       /* handle offsetof macro:            */
3283       /* #define offsetof(TYPE, MEMBER) \  */
3284       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3285       if (IS_ADDRESS_OF_OP(tree->right)
3286           && IS_AST_OP (tree->right->left)
3287           && tree->right->left->opval.op == PTR_OP
3288           && IS_AST_OP (tree->right->left->left)
3289           && tree->right->left->left->opval.op == CAST
3290           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3291
3292         symbol *element = getStructElement (
3293           SPEC_STRUCT (LETYPE(tree->right->left)),
3294           AST_SYMBOL(tree->right->left->right)
3295         );
3296
3297         if (element) {
3298           tree->type = EX_VALUE;
3299           tree->opval.val = valCastLiteral (
3300             LTYPE (tree),
3301             element->offset
3302             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3303           );
3304
3305           TTYPE (tree) = tree->opval.val->type;
3306           TETYPE (tree) = getSpec (TTYPE (tree));
3307           tree->left = NULL;
3308           tree->right = NULL;
3309           return tree;
3310         }
3311       }
3312
3313       /* if the right is a literal replace the tree */
3314       if (IS_LITERAL (RETYPE (tree))) {
3315         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3316           /* rewrite      (type *)litaddr
3317              as           &temp
3318              and define   type at litaddr temp
3319              (but only if type's storage class is not generic)
3320           */
3321           ast *newTree = newNode ('&', NULL, NULL);
3322           symbol *sym;
3323
3324           TTYPE (newTree) = LTYPE (tree);
3325           TETYPE (newTree) = getSpec(LTYPE (tree));
3326
3327           /* define a global symbol at the casted address*/
3328           sym = newSymbol(genSymName (0), 0);
3329           sym->type = LTYPE (tree)->next;
3330           if (!sym->type)
3331             sym->type = newLink (V_VOID);
3332           sym->etype = getSpec(sym->type);
3333           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3334           sym->lineDef = tree->lineno;
3335           sym->cdef = 1;
3336           sym->isref = 1;
3337           SPEC_STAT (sym->etype) = 1;
3338           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3339           SPEC_ABSA(sym->etype) = 1;
3340           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3341           allocGlobal (sym);
3342
3343           newTree->left = newAst_VALUE(symbolVal(sym));
3344           newTree->left->lineno = tree->lineno;
3345           LTYPE (newTree) = sym->type;
3346           LETYPE (newTree) = sym->etype;
3347           LLVAL (newTree) = 1;
3348           LRVAL (newTree) = 0;
3349           TLVAL (newTree) = 1;
3350           return newTree;
3351         }
3352         if (!IS_PTR (LTYPE (tree))) {
3353           tree->type = EX_VALUE;
3354           tree->opval.val =
3355           valCastLiteral (LTYPE (tree),
3356                           floatFromVal (valFromType (RTYPE (tree))));
3357           TTYPE (tree) = tree->opval.val->type;
3358           tree->left = NULL;
3359           tree->right = NULL;
3360           tree->values.literalFromCast = 1;
3361           TETYPE (tree) = getSpec (TTYPE (tree));
3362           return tree;
3363         }
3364       }
3365       TTYPE (tree) = LTYPE (tree);
3366       LRVAL (tree) = 1;
3367
3368 #endif
3369       TETYPE (tree) = getSpec (TTYPE (tree));
3370
3371       return tree;
3372
3373       /*------------------------------------------------------------------*/
3374       /*----------------------------*/
3375       /*       logical &&, ||       */
3376       /*----------------------------*/
3377     case AND_OP:
3378     case OR_OP:
3379       /* each must me arithmetic type or be a pointer */
3380       if (!IS_PTR (LTYPE (tree)) &&
3381           !IS_ARRAY (LTYPE (tree)) &&
3382           !IS_INTEGRAL (LTYPE (tree)))
3383         {
3384           werror (E_COMPARE_OP);
3385           goto errorTreeReturn;
3386         }
3387
3388       if (!IS_PTR (RTYPE (tree)) &&
3389           !IS_ARRAY (RTYPE (tree)) &&
3390           !IS_INTEGRAL (RTYPE (tree)))
3391         {
3392           werror (E_COMPARE_OP);
3393           goto errorTreeReturn;
3394         }
3395       /* if they are both literal then */
3396       /* rewrite the tree */
3397       if (IS_LITERAL (RTYPE (tree)) &&
3398           IS_LITERAL (LTYPE (tree)))
3399         {
3400           tree->type = EX_VALUE;
3401           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
3402                                            valFromType (RTYPE (tree)),
3403                                            tree->opval.op);
3404           tree->right = tree->left = NULL;
3405           TETYPE (tree) = getSpec (TTYPE (tree) =
3406                                    tree->opval.val->type);
3407           return tree;
3408         }
3409       LRVAL (tree) = RRVAL (tree) = 1;
3410       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3411       return tree;
3412
3413       /*------------------------------------------------------------------*/
3414       /*----------------------------*/
3415       /*     comparison operators   */
3416       /*----------------------------*/
3417     case '>':
3418     case '<':
3419     case LE_OP:
3420     case GE_OP:
3421     case EQ_OP:
3422     case NE_OP:
3423       {
3424         ast *lt = optimizeCompare (tree);
3425
3426         if (tree != lt)
3427           return lt;
3428       }
3429
3430       /* if they are pointers they must be castable */
3431       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3432         {
3433           if (tree->opval.op==EQ_OP &&
3434               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3435             // we cannot cast a gptr to a !gptr: switch the leaves
3436             struct ast *s=tree->left;
3437             tree->left=tree->right;
3438             tree->right=s;
3439           }
3440           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3441             {
3442               werror (E_COMPARE_OP);
3443               fprintf (stderr, "comparing type ");
3444               printTypeChain (LTYPE (tree), stderr);
3445               fprintf (stderr, "to type ");
3446               printTypeChain (RTYPE (tree), stderr);
3447               fprintf (stderr, "\n");
3448               goto errorTreeReturn;
3449             }
3450         }
3451       /* else they should be promotable to one another */
3452       else
3453         {
3454           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3455                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3456
3457             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3458               {
3459                 werror (E_COMPARE_OP);
3460                 fprintf (stderr, "comparing type ");
3461                 printTypeChain (LTYPE (tree), stderr);
3462                 fprintf (stderr, "to type ");
3463                 printTypeChain (RTYPE (tree), stderr);
3464                 fprintf (stderr, "\n");
3465                 goto errorTreeReturn;
3466               }
3467         }
3468       /* if unsigned value < 0  then always false */
3469       /* if (unsigned value) > 0 then (unsigned value) */
3470       if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree))  &&
3471           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
3472         {
3473           if (tree->opval.op == '<')
3474             {
3475               return tree->right;
3476             }
3477           if (tree->opval.op == '>')
3478             {
3479               return tree->left;
3480             }
3481         }
3482       /* if they are both literal then */
3483       /* rewrite the tree */
3484       if (IS_LITERAL (RTYPE (tree)) &&
3485           IS_LITERAL (LTYPE (tree)))
3486         {
3487           tree->type = EX_VALUE;
3488           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3489                                         valFromType (RETYPE (tree)),
3490                                         tree->opval.op);
3491           tree->right = tree->left = NULL;
3492           TETYPE (tree) = getSpec (TTYPE (tree) =
3493                                    tree->opval.val->type);
3494           return tree;
3495         }
3496       LRVAL (tree) = RRVAL (tree) = 1;
3497       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3498       return tree;
3499
3500       /*------------------------------------------------------------------*/
3501       /*----------------------------*/
3502       /*             sizeof         */
3503       /*----------------------------*/
3504     case SIZEOF:                /* evaluate wihout code generation */
3505       /* change the type to a integer */
3506       tree->type = EX_VALUE;
3507       SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
3508       tree->opval.val = constVal (buffer);
3509       tree->right = tree->left = NULL;
3510       TETYPE (tree) = getSpec (TTYPE (tree) =
3511                                tree->opval.val->type);
3512       return tree;
3513
3514       /*------------------------------------------------------------------*/
3515       /*----------------------------*/
3516       /*             typeof         */
3517       /*----------------------------*/
3518     case TYPEOF:
3519         /* return typeof enum value */
3520         tree->type = EX_VALUE;
3521         {
3522             int typeofv = 0;
3523             if (IS_SPEC(tree->right->ftype)) {
3524                 switch (SPEC_NOUN(tree->right->ftype)) {
3525                 case V_INT:
3526                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3527                     else typeofv = TYPEOF_INT;
3528                     break;
3529                 case V_FLOAT:
3530                     typeofv = TYPEOF_FLOAT;
3531                     break;
3532                 case V_CHAR:
3533                     typeofv = TYPEOF_CHAR;
3534                     break;
3535                 case V_VOID:
3536                     typeofv = TYPEOF_VOID;
3537                     break;
3538                 case V_STRUCT:
3539                     typeofv = TYPEOF_STRUCT;
3540                     break;
3541                 case V_BITFIELD:
3542                     typeofv = TYPEOF_BITFIELD;
3543                     break;
3544                 case V_BIT:
3545                     typeofv = TYPEOF_BIT;
3546                     break;
3547                 case V_SBIT:
3548                     typeofv = TYPEOF_SBIT;
3549                     break;
3550                 default:
3551                     break;
3552                 }
3553             } else {
3554                 switch (DCL_TYPE(tree->right->ftype)) {
3555                 case POINTER:
3556                     typeofv = TYPEOF_POINTER;
3557                     break;
3558                 case FPOINTER:
3559                     typeofv = TYPEOF_FPOINTER;
3560                     break;
3561                 case CPOINTER:
3562                     typeofv = TYPEOF_CPOINTER;
3563                     break;
3564                 case GPOINTER:
3565                     typeofv = TYPEOF_GPOINTER;
3566                     break;
3567                 case PPOINTER:
3568                     typeofv = TYPEOF_PPOINTER;
3569                     break;
3570                 case IPOINTER:
3571                     typeofv = TYPEOF_IPOINTER;
3572                     break;
3573                 case ARRAY:
3574                     typeofv = TYPEOF_ARRAY;
3575                     break;
3576                 case FUNCTION:
3577                     typeofv = TYPEOF_FUNCTION;
3578                     break;
3579                 default:
3580                     break;
3581                 }
3582             }
3583             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3584             tree->opval.val = constVal (buffer);
3585             tree->right = tree->left = NULL;
3586             TETYPE (tree) = getSpec (TTYPE (tree) =
3587                                      tree->opval.val->type);
3588         }
3589         return tree;
3590       /*------------------------------------------------------------------*/
3591       /*----------------------------*/
3592       /* conditional operator  '?'  */
3593       /*----------------------------*/
3594     case '?':
3595       /* the type is value of the colon operator (on the right) */
3596       assert(IS_COLON_OP(tree->right));
3597       /* if already known then replace the tree : optimizer will do it
3598          but faster to do it here */
3599       if (IS_LITERAL (LTYPE(tree))) {     
3600           if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) {
3601               return decorateType(tree->right->left) ;
3602           } else {
3603               return decorateType(tree->right->right) ;
3604           }
3605       } else {
3606           tree->right = decorateType(tree->right);
3607           TTYPE (tree) = RTYPE(tree);
3608           TETYPE (tree) = getSpec (TTYPE (tree));
3609       }
3610       return tree;
3611
3612     case ':':
3613       /* if they don't match we have a problem */
3614       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3615         {
3616           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3617           goto errorTreeReturn;
3618         }
3619
3620       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
3621       TETYPE (tree) = getSpec (TTYPE (tree));
3622       return tree;
3623
3624
3625 #if 0 // assignment operators are converted by the parser
3626       /*------------------------------------------------------------------*/
3627       /*----------------------------*/
3628       /*    assignment operators    */
3629       /*----------------------------*/
3630     case MUL_ASSIGN:
3631     case DIV_ASSIGN:
3632       /* for these it must be both must be integral */
3633       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3634           !IS_ARITHMETIC (RTYPE (tree)))
3635         {
3636           werror (E_OPS_INTEGRAL);
3637           goto errorTreeReturn;
3638         }
3639       RRVAL (tree) = 1;
3640       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3641
3642       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3643         werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3644
3645       if (LRVAL (tree))
3646         {
3647           werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3648           goto errorTreeReturn;
3649         }
3650       LLVAL (tree) = 1;
3651
3652       return tree;
3653
3654     case AND_ASSIGN:
3655     case OR_ASSIGN:
3656     case XOR_ASSIGN:
3657     case RIGHT_ASSIGN:
3658     case LEFT_ASSIGN:
3659       /* for these it must be both must be integral */
3660       if (!IS_INTEGRAL (LTYPE (tree)) ||
3661           !IS_INTEGRAL (RTYPE (tree)))
3662         {
3663           werror (E_OPS_INTEGRAL);
3664           goto errorTreeReturn;
3665         }
3666       RRVAL (tree) = 1;
3667       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3668
3669       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3670         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3671
3672       if (LRVAL (tree))
3673         {
3674           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3675           goto errorTreeReturn;
3676         }
3677       LLVAL (tree) = 1;
3678
3679       return tree;
3680
3681       /*------------------------------------------------------------------*/
3682       /*----------------------------*/
3683       /*    -= operator             */
3684       /*----------------------------*/
3685     case SUB_ASSIGN:
3686       if (!(IS_PTR (LTYPE (tree)) ||
3687             IS_ARITHMETIC (LTYPE (tree))))
3688         {
3689           werror (E_PLUS_INVALID, "-=");
3690           goto errorTreeReturn;
3691         }
3692
3693       if (!(IS_PTR (RTYPE (tree)) ||
3694             IS_ARITHMETIC (RTYPE (tree))))
3695         {
3696           werror (E_PLUS_INVALID, "-=");
3697           goto errorTreeReturn;
3698         }
3699       RRVAL (tree) = 1;
3700       TETYPE (tree) = getSpec (TTYPE (tree) =
3701                                computeType (LTYPE (tree),
3702                                             RTYPE (tree),
3703                                             FALSE));
3704
3705       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3706         werror (E_CODE_WRITE, "-=");
3707
3708       if (LRVAL (tree))
3709         {
3710           werror (E_LVALUE_REQUIRED, "-=");
3711           goto errorTreeReturn;
3712         }
3713       LLVAL (tree) = 1;
3714
3715       return tree;
3716
3717       /*------------------------------------------------------------------*/
3718       /*----------------------------*/
3719       /*          += operator       */
3720       /*----------------------------*/
3721     case ADD_ASSIGN:
3722       /* this is not a unary operation */
3723       /* if both pointers then problem */
3724       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3725         {
3726           werror (E_PTR_PLUS_PTR);
3727           goto errorTreeReturn;
3728         }
3729
3730       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
3731         {
3732           werror (E_PLUS_INVALID, "+=");
3733           goto errorTreeReturn;
3734         }
3735
3736       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
3737         {
3738           werror (E_PLUS_INVALID, "+=");
3739           goto errorTreeReturn;
3740         }
3741       RRVAL (tree) = 1;
3742       TETYPE (tree) = getSpec (TTYPE (tree) =
3743                                computeType (LTYPE (tree),
3744                                             RTYPE (tree),
3745                                             FALSE));
3746
3747       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3748         werror (E_CODE_WRITE, "+=");
3749
3750       if (LRVAL (tree))
3751         {
3752           werror (E_LVALUE_REQUIRED, "+=");
3753           goto errorTreeReturn;
3754         }
3755
3756       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
3757       tree->opval.op = '=';
3758
3759       return tree;
3760 #endif
3761
3762       /*------------------------------------------------------------------*/
3763       /*----------------------------*/
3764       /*      straight assignemnt   */
3765       /*----------------------------*/
3766     case '=':
3767       /* cannot be an aggregate */
3768       if (IS_AGGREGATE (LTYPE (tree)))
3769         {
3770           werror (E_AGGR_ASSIGN);
3771           goto errorTreeReturn;
3772         }
3773
3774       /* they should either match or be castable */
3775       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3776         {
3777           werror (E_TYPE_MISMATCH, "assignment", " ");
3778           printFromToType(RTYPE(tree),LTYPE(tree));
3779         }
3780
3781       /* if the left side of the tree is of type void
3782          then report error */
3783       if (IS_VOID (LTYPE (tree)))
3784         {
3785           werror (E_CAST_ZERO);
3786           printFromToType(RTYPE(tree), LTYPE(tree));
3787         }
3788
3789       TETYPE (tree) = getSpec (TTYPE (tree) =
3790                                LTYPE (tree));
3791       RRVAL (tree) = 1;
3792       LLVAL (tree) = 1;
3793       if (!tree->initMode ) {
3794         if (IS_CONSTANT(LTYPE(tree)))
3795           werror (E_CODE_WRITE, "=");
3796       }
3797       if (LRVAL (tree))
3798         {
3799           werror (E_LVALUE_REQUIRED, "=");
3800           goto errorTreeReturn;
3801         }
3802
3803       return tree;
3804
3805       /*------------------------------------------------------------------*/
3806       /*----------------------------*/
3807       /*      comma operator        */
3808       /*----------------------------*/
3809     case ',':
3810       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
3811       return tree;
3812
3813       /*------------------------------------------------------------------*/
3814       /*----------------------------*/
3815       /*       function call        */
3816       /*----------------------------*/
3817     case CALL:
3818       parmNumber = 1;
3819
3820       if (processParms (tree->left,
3821                         FUNC_ARGS(tree->left->ftype),
3822                         tree->right, &parmNumber, TRUE)) {
3823         goto errorTreeReturn;
3824       }
3825
3826       if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && 
3827           !IFFUNC_ISBUILTIN(LTYPE(tree)))
3828         {
3829           reverseParms (tree->right);
3830         }
3831
3832       if (IS_CODEPTR(LTYPE(tree))) {
3833         TTYPE(tree) = LTYPE(tree)->next->next;
3834       } else {
3835         TTYPE(tree) = LTYPE(tree)->next;
3836       }
3837       TETYPE (tree) = getSpec (TTYPE (tree));
3838       return tree;
3839
3840       /*------------------------------------------------------------------*/
3841       /*----------------------------*/
3842       /*     return statement       */
3843       /*----------------------------*/
3844     case RETURN:
3845       if (!tree->right)
3846         goto voidcheck;
3847
3848       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
3849         {
3850           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
3851           printFromToType (RTYPE(tree), currFunc->type->next);
3852           goto errorTreeReturn;
3853         }
3854
3855       if (IS_VOID (currFunc->type->next)
3856           && tree->right &&
3857           !IS_VOID (RTYPE (tree)))
3858         {
3859           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
3860           goto errorTreeReturn;
3861         }
3862
3863       /* if there is going to be a casing required then add it */
3864       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
3865         {
3866           tree->right =
3867             decorateType (newNode (CAST,
3868                            newAst_LINK (copyLinkChain (currFunc->type->next)),
3869                                    tree->right));
3870         }
3871
3872       RRVAL (tree) = 1;
3873       return tree;
3874
3875     voidcheck:
3876
3877       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
3878         {
3879           werror (W_VOID_FUNC, currFunc->name);
3880           goto errorTreeReturn;
3881         }
3882
3883       TTYPE (tree) = TETYPE (tree) = NULL;
3884       return tree;
3885
3886       /*------------------------------------------------------------------*/
3887       /*----------------------------*/
3888       /*     switch statement       */
3889       /*----------------------------*/
3890     case SWITCH:
3891       /* the switch value must be an integer */
3892       if (!IS_INTEGRAL (LTYPE (tree)))
3893         {
3894           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
3895           goto errorTreeReturn;
3896         }
3897       LRVAL (tree) = 1;
3898       TTYPE (tree) = TETYPE (tree) = NULL;
3899       return tree;
3900
3901       /*------------------------------------------------------------------*/
3902       /*----------------------------*/
3903       /* ifx Statement              */
3904       /*----------------------------*/
3905     case IFX:
3906       tree->left = backPatchLabels (tree->left,
3907                                     tree->trueLabel,
3908                                     tree->falseLabel);
3909       TTYPE (tree) = TETYPE (tree) = NULL;
3910       return tree;
3911
3912       /*------------------------------------------------------------------*/
3913       /*----------------------------*/
3914       /* for Statement              */
3915       /*----------------------------*/
3916     case FOR:
3917
3918       decorateType (resolveSymbols (AST_FOR (tree, initExpr)));
3919       decorateType (resolveSymbols (AST_FOR (tree, condExpr)));
3920       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)));
3921
3922       /* if the for loop is reversible then
3923          reverse it otherwise do what we normally
3924          do */
3925       {
3926         symbol *sym;
3927         ast *init, *end;
3928
3929         if (isLoopReversible (tree, &sym, &init, &end))
3930           return reverseLoop (tree, sym, init, end);
3931         else
3932           return decorateType (createFor (AST_FOR (tree, trueLabel),
3933                                           AST_FOR (tree, continueLabel),
3934                                           AST_FOR (tree, falseLabel),
3935                                           AST_FOR (tree, condLabel),
3936                                           AST_FOR (tree, initExpr),
3937                                           AST_FOR (tree, condExpr),
3938                                           AST_FOR (tree, loopExpr),
3939                                           tree->left));
3940       }
3941     default:
3942       TTYPE (tree) = TETYPE (tree) = NULL;
3943       return tree;
3944     }
3945
3946   /* some error found this tree will be killed */
3947 errorTreeReturn:
3948   TTYPE (tree) = TETYPE (tree) = newCharLink ();
3949   tree->opval.op = NULLOP;
3950   tree->isError = 1;
3951
3952   return tree;
3953 }
3954
3955 /*-----------------------------------------------------------------*/
3956 /* sizeofOp - processes size of operation                          */
3957 /*-----------------------------------------------------------------*/
3958 value *
3959 sizeofOp (sym_link * type)
3960 {
3961   char buff[10];
3962
3963   /* make sure the type is complete and sane */
3964   checkTypeSanity(type, "(sizeof)");
3965
3966   /* get the size and convert it to character  */
3967   SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
3968
3969   /* now convert into value  */
3970   return constVal (buff);
3971 }
3972
3973
3974 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
3975 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
3976 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
3977 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
3978 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
3979 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
3980 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
3981
3982 /*-----------------------------------------------------------------*/
3983 /* backPatchLabels - change and or not operators to flow control    */
3984 /*-----------------------------------------------------------------*/
3985 ast *
3986 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
3987 {
3988
3989   if (!tree)
3990     return NULL;
3991
3992   if (!(IS_ANDORNOT (tree)))
3993     return tree;
3994
3995   /* if this an and */
3996   if (IS_AND (tree))
3997     {
3998       static int localLbl = 0;
3999       symbol *localLabel;
4000
4001       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4002       localLabel = newSymbol (buffer, NestLevel);
4003
4004       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4005
4006       /* if left is already a IFX then just change the if true label in that */
4007       if (!IS_IFX (tree->left))
4008         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4009
4010       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4011       /* right is a IFX then just join */
4012       if (IS_IFX (tree->right))
4013         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4014
4015       tree->right = createLabel (localLabel, tree->right);
4016       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4017
4018       return newNode (NULLOP, tree->left, tree->right);
4019     }
4020
4021   /* if this is an or operation */
4022   if (IS_OR (tree))
4023     {
4024       static int localLbl = 0;
4025       symbol *localLabel;
4026
4027       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4028       localLabel = newSymbol (buffer, NestLevel);
4029
4030       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4031
4032       /* if left is already a IFX then just change the if true label in that */
4033       if (!IS_IFX (tree->left))
4034         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4035
4036       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4037       /* right is a IFX then just join */
4038       if (IS_IFX (tree->right))
4039         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4040
4041       tree->right = createLabel (localLabel, tree->right);
4042       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4043
4044       return newNode (NULLOP, tree->left, tree->right);
4045     }
4046
4047   /* change not */
4048   if (IS_NOT (tree))
4049     {
4050       int wasnot = IS_NOT (tree->left);
4051       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4052
4053       /* if the left is already a IFX */
4054       if (!IS_IFX (tree->left))
4055         tree->left = newNode (IFX, tree->left, NULL);
4056
4057       if (wasnot)
4058         {
4059           tree->left->trueLabel = trueLabel;
4060           tree->left->falseLabel = falseLabel;
4061         }
4062       else
4063         {
4064           tree->left->trueLabel = falseLabel;
4065           tree->left->falseLabel = trueLabel;
4066         }
4067       return tree->left;
4068     }
4069
4070   if (IS_IFX (tree))
4071     {
4072       tree->trueLabel = trueLabel;
4073       tree->falseLabel = falseLabel;
4074     }
4075
4076   return tree;
4077 }
4078
4079
4080 /*-----------------------------------------------------------------*/
4081 /* createBlock - create expression tree for block                  */
4082 /*-----------------------------------------------------------------*/
4083 ast *
4084 createBlock (symbol * decl, ast * body)
4085 {
4086   ast *ex;
4087
4088   /* if the block has nothing */
4089   if (!body && !decl)
4090     return NULL;
4091
4092   ex = newNode (BLOCK, NULL, body);
4093   ex->values.sym = decl;
4094   
4095   ex->right = ex->right;
4096   ex->level++;
4097   ex->lineno = 0;
4098   return ex;
4099 }
4100
4101 /*-----------------------------------------------------------------*/
4102 /* createLabel - creates the expression tree for labels            */
4103 /*-----------------------------------------------------------------*/
4104 ast *
4105 createLabel (symbol * label, ast * stmnt)
4106 {
4107   symbol *csym;
4108   char name[SDCC_NAME_MAX + 1];
4109   ast *rValue;
4110
4111   /* must create fresh symbol if the symbol name  */
4112   /* exists in the symbol table, since there can  */
4113   /* be a variable with the same name as the labl */
4114   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4115       (csym->level == label->level))
4116     label = newSymbol (label->name, label->level);
4117
4118   /* change the name before putting it in add _ */
4119   SNPRINTF(name, sizeof(name), "%s", label->name);
4120
4121   /* put the label in the LabelSymbol table    */
4122   /* but first check if a label of the same    */
4123   /* name exists                               */
4124   if ((csym = findSym (LabelTab, NULL, name)))
4125     werror (E_DUPLICATE_LABEL, label->name);
4126   else
4127     addSym (LabelTab, label, name, label->level, 0, 0);
4128
4129   label->islbl = 1;
4130   label->key = labelKey++;
4131   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4132   rValue->lineno = 0;
4133
4134   return rValue;
4135 }
4136
4137 /*-----------------------------------------------------------------*/
4138 /* createCase - generates the parsetree for a case statement       */
4139 /*-----------------------------------------------------------------*/
4140 ast *
4141 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4142 {
4143   char caseLbl[SDCC_NAME_MAX + 1];
4144   ast *rexpr;
4145   value *val;
4146
4147   /* if the switch statement does not exist */
4148   /* then case is out of context            */
4149   if (!swStat)
4150     {
4151       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4152       return NULL;
4153     }
4154
4155   caseVal = decorateType (resolveSymbols (caseVal));
4156   /* if not a constant then error  */
4157   if (!IS_LITERAL (caseVal->ftype))
4158     {
4159       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4160       return NULL;
4161     }
4162
4163   /* if not a integer than error */
4164   if (!IS_INTEGRAL (caseVal->ftype))
4165     {
4166       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4167       return NULL;
4168     }
4169
4170   /* find the end of the switch values chain   */
4171   if (!(val = swStat->values.switchVals.swVals))
4172     swStat->values.switchVals.swVals = caseVal->opval.val;
4173   else
4174     {
4175       /* also order the cases according to value */
4176       value *pval = NULL;
4177       int cVal = (int) floatFromVal (caseVal->opval.val);
4178       while (val && (int) floatFromVal (val) < cVal)
4179         {
4180           pval = val;
4181           val = val->next;
4182         }
4183
4184       /* if we reached the end then */
4185       if (!val)
4186         {
4187           pval->next = caseVal->opval.val;
4188         }
4189       else if ((int) floatFromVal (val) == cVal)
4190         {
4191           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4192                     "case");
4193           return NULL;
4194         }
4195       else
4196         {
4197           /* we found a value greater than */
4198           /* the current value we must add this */
4199           /* before the value */
4200           caseVal->opval.val->next = val;
4201
4202           /* if this was the first in chain */
4203           if (swStat->values.switchVals.swVals == val)
4204             swStat->values.switchVals.swVals =
4205               caseVal->opval.val;
4206           else
4207             pval->next = caseVal->opval.val;
4208         }
4209
4210     }
4211
4212   /* create the case label   */
4213   SNPRINTF(caseLbl, sizeof(caseLbl), 
4214            "_case_%d_%d",
4215            swStat->values.switchVals.swNum,
4216            (int) floatFromVal (caseVal->opval.val));
4217
4218   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4219   rexpr->lineno = 0;
4220   return rexpr;
4221 }
4222
4223 /*-----------------------------------------------------------------*/
4224 /* createDefault - creates the parse tree for the default statement */
4225 /*-----------------------------------------------------------------*/
4226 ast *
4227 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4228 {
4229   char defLbl[SDCC_NAME_MAX + 1];
4230
4231   /* if the switch statement does not exist */
4232   /* then case is out of context            */
4233   if (!swStat)
4234     {
4235       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4236       return NULL;
4237     }
4238
4239   if (swStat->values.switchVals.swDefault)
4240     {
4241       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4242                 "default");
4243       return NULL;
4244     }
4245
4246   /* turn on the default flag   */
4247   swStat->values.switchVals.swDefault = 1;
4248
4249   /* create the label  */
4250   SNPRINTF (defLbl, sizeof(defLbl),
4251             "_default_%d", swStat->values.switchVals.swNum);
4252   return createLabel (newSymbol (defLbl, 0), stmnt);
4253 }
4254
4255 /*-----------------------------------------------------------------*/
4256 /* createIf - creates the parsetree for the if statement           */
4257 /*-----------------------------------------------------------------*/
4258 ast *
4259 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4260 {
4261   static int Lblnum = 0;
4262   ast *ifTree;
4263   symbol *ifTrue, *ifFalse, *ifEnd;
4264
4265   /* if neither exists */
4266   if (!elseBody && !ifBody) {
4267     // if there are no side effects (i++, j() etc)
4268     if (!hasSEFcalls(condAst)) {
4269       return condAst;
4270     }
4271   }
4272
4273   /* create the labels */
4274   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4275   ifFalse = newSymbol (buffer, NestLevel);
4276   /* if no else body then end == false */
4277   if (!elseBody)
4278     ifEnd = ifFalse;
4279   else
4280     {
4281       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4282       ifEnd = newSymbol (buffer, NestLevel);
4283     }
4284
4285   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4286   ifTrue = newSymbol (buffer, NestLevel);
4287
4288   Lblnum++;
4289
4290   /* attach the ifTrue label to the top of it body */
4291   ifBody = createLabel (ifTrue, ifBody);
4292   /* attach a goto end to the ifBody if else is present */
4293   if (elseBody)
4294     {
4295       ifBody = newNode (NULLOP, ifBody,
4296                         newNode (GOTO,
4297                                  newAst_VALUE (symbolVal (ifEnd)),
4298                                  NULL));
4299       /* put the elseLabel on the else body */
4300       elseBody = createLabel (ifFalse, elseBody);
4301       /* out the end at the end of the body */
4302       elseBody = newNode (NULLOP,
4303                           elseBody,
4304                           createLabel (ifEnd, NULL));
4305     }
4306   else
4307     {
4308       ifBody = newNode (NULLOP, ifBody,
4309                         createLabel (ifFalse, NULL));
4310     }
4311   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4312   if (IS_IFX (condAst))
4313     ifTree = condAst;
4314   else
4315     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4316
4317   return newNode (NULLOP, ifTree,
4318                   newNode (NULLOP, ifBody, elseBody));
4319
4320 }
4321
4322 /*-----------------------------------------------------------------*/
4323 /* createDo - creates parse tree for do                            */
4324 /*        _dobody_n:                                               */
4325 /*            statements                                           */
4326 /*        _docontinue_n:                                           */
4327 /*            condition_expression +-> trueLabel -> _dobody_n      */
4328 /*                                 |                               */
4329 /*                                 +-> falseLabel-> _dobreak_n     */
4330 /*        _dobreak_n:                                              */
4331 /*-----------------------------------------------------------------*/
4332 ast *
4333 createDo (symbol * trueLabel, symbol * continueLabel,
4334           symbol * falseLabel, ast * condAst, ast * doBody)
4335 {
4336   ast *doTree;
4337
4338
4339   /* if the body does not exist then it is simple */
4340   if (!doBody)
4341     {
4342       condAst = backPatchLabels (condAst, continueLabel, NULL);
4343       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4344                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4345       doTree->trueLabel = continueLabel;
4346       doTree->falseLabel = NULL;
4347       return doTree;
4348     }
4349
4350   /* otherwise we have a body */
4351   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4352
4353   /* attach the body label to the top */
4354   doBody = createLabel (trueLabel, doBody);
4355   /* attach the continue label to end of body */
4356   doBody = newNode (NULLOP, doBody,
4357                     createLabel (continueLabel, NULL));
4358
4359   /* now put the break label at the end */
4360   if (IS_IFX (condAst))
4361     doTree = condAst;
4362   else
4363     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4364
4365   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4366
4367   /* putting it together */
4368   return newNode (NULLOP, doBody, doTree);
4369 }
4370
4371 /*-----------------------------------------------------------------*/
4372 /* createFor - creates parse tree for 'for' statement              */
4373 /*        initExpr                                                 */
4374 /*   _forcond_n:                                                   */
4375 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4376 /*                  |                                              */
4377 /*                  +-> falseLabel-> _forbreak_n                   */
4378 /*   _forbody_n:                                                   */
4379 /*        statements                                               */
4380 /*   _forcontinue_n:                                               */
4381 /*        loopExpr                                                 */
4382 /*        goto _forcond_n ;                                        */
4383 /*   _forbreak_n:                                                  */
4384 /*-----------------------------------------------------------------*/
4385 ast *
4386 createFor (symbol * trueLabel, symbol * continueLabel,
4387            symbol * falseLabel, symbol * condLabel,
4388            ast * initExpr, ast * condExpr, ast * loopExpr,
4389            ast * forBody)
4390 {
4391   ast *forTree;
4392
4393   /* if loopexpression not present then we can generate it */
4394   /* the same way as a while */
4395   if (!loopExpr)
4396     return newNode (NULLOP, initExpr,
4397                     createWhile (trueLabel, continueLabel,
4398                                  falseLabel, condExpr, forBody));
4399   /* vanilla for statement */
4400   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4401
4402   if (condExpr && !IS_IFX (condExpr))
4403     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4404
4405
4406   /* attach condition label to condition */
4407   condExpr = createLabel (condLabel, condExpr);
4408
4409   /* attach body label to body */
4410   forBody = createLabel (trueLabel, forBody);
4411
4412   /* attach continue to forLoop expression & attach */
4413   /* goto the forcond @ and of loopExpression       */
4414   loopExpr = createLabel (continueLabel,
4415                           newNode (NULLOP,
4416                                    loopExpr,
4417                                    newNode (GOTO,
4418                                        newAst_VALUE (symbolVal (condLabel)),
4419                                             NULL)));
4420   /* now start putting them together */
4421   forTree = newNode (NULLOP, initExpr, condExpr);
4422   forTree = newNode (NULLOP, forTree, forBody);
4423   forTree = newNode (NULLOP, forTree, loopExpr);
4424   /* finally add the break label */
4425   forTree = newNode (NULLOP, forTree,
4426                      createLabel (falseLabel, NULL));
4427   return forTree;
4428 }
4429
4430 /*-----------------------------------------------------------------*/
4431 /* createWhile - creates parse tree for while statement            */
4432 /*               the while statement will be created as follows    */
4433 /*                                                                 */
4434 /*      _while_continue_n:                                         */
4435 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4436 /*                                 |                               */
4437 /*                                 +-> falseLabel -> _while_break_n */
4438 /*      _while_body_n:                                             */
4439 /*            statements                                           */
4440 /*            goto _while_continue_n                               */
4441 /*      _while_break_n:                                            */
4442 /*-----------------------------------------------------------------*/
4443 ast *
4444 createWhile (symbol * trueLabel, symbol * continueLabel,
4445              symbol * falseLabel, ast * condExpr, ast * whileBody)
4446 {
4447   ast *whileTree;
4448
4449   /* put the continue label */
4450   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4451   condExpr = createLabel (continueLabel, condExpr);
4452   condExpr->lineno = 0;
4453
4454   /* put the body label in front of the body */
4455   whileBody = createLabel (trueLabel, whileBody);
4456   whileBody->lineno = 0;
4457   /* put a jump to continue at the end of the body */
4458   /* and put break label at the end of the body */
4459   whileBody = newNode (NULLOP,
4460                        whileBody,
4461                        newNode (GOTO,
4462                                 newAst_VALUE (symbolVal (continueLabel)),
4463                                 createLabel (falseLabel, NULL)));
4464
4465   /* put it all together */
4466   if (IS_IFX (condExpr))
4467     whileTree = condExpr;
4468   else
4469     {
4470       whileTree = newNode (IFX, condExpr, NULL);
4471       /* put the true & false labels in place */
4472       whileTree->trueLabel = trueLabel;
4473       whileTree->falseLabel = falseLabel;
4474     }
4475
4476   return newNode (NULLOP, whileTree, whileBody);
4477 }
4478
4479 /*-----------------------------------------------------------------*/
4480 /* optimizeGetHbit - get highest order bit of the expression       */
4481 /*-----------------------------------------------------------------*/
4482 ast *
4483 optimizeGetHbit (ast * tree)
4484 {
4485   int i, j;
4486   /* if this is not a bit and */
4487   if (!IS_BITAND (tree))
4488     return tree;
4489
4490   /* will look for tree of the form
4491      ( expr >> ((sizeof expr) -1) ) & 1 */
4492   if (!IS_AST_LIT_VALUE (tree->right))
4493     return tree;
4494
4495   if (AST_LIT_VALUE (tree->right) != 1)
4496     return tree;
4497
4498   if (!IS_RIGHT_OP (tree->left))
4499     return tree;
4500
4501   if (!IS_AST_LIT_VALUE (tree->left->right))
4502     return tree;
4503
4504   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4505       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4506     return tree;
4507       
4508   /* make sure the port supports GETHBIT */
4509   if (port->hasExtBitOp
4510       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4511     return tree;
4512
4513   return decorateType (newNode (GETHBIT, tree->left->left, NULL));
4514
4515 }
4516
4517 /*-----------------------------------------------------------------*/
4518 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4519 /*-----------------------------------------------------------------*/
4520 ast *
4521 optimizeRRCRLC (ast * root)
4522 {
4523   /* will look for trees of the form
4524      (?expr << 1) | (?expr >> 7) or
4525      (?expr >> 7) | (?expr << 1) will make that
4526      into a RLC : operation ..
4527      Will also look for
4528      (?expr >> 1) | (?expr << 7) or
4529      (?expr << 7) | (?expr >> 1) will make that
4530      into a RRC operation
4531      note : by 7 I mean (number of bits required to hold the
4532      variable -1 ) */
4533   /* if the root operations is not a | operation the not */
4534   if (!IS_BITOR (root))
4535     return root;
4536
4537   /* I have to think of a better way to match patterns this sucks */
4538   /* that aside let start looking for the first case : I use a the
4539      negative check a lot to improve the efficiency */
4540   /* (?expr << 1) | (?expr >> 7) */
4541   if (IS_LEFT_OP (root->left) &&
4542       IS_RIGHT_OP (root->right))
4543     {
4544
4545       if (!SPEC_USIGN (TETYPE (root->left->left)))
4546         return root;
4547
4548       if (!IS_AST_LIT_VALUE (root->left->right) ||
4549           !IS_AST_LIT_VALUE (root->right->right))
4550         goto tryNext0;
4551
4552       /* make sure it is the same expression */
4553       if (!isAstEqual (root->left->left,
4554                        root->right->left))
4555         goto tryNext0;
4556
4557       if (AST_LIT_VALUE (root->left->right) != 1)
4558         goto tryNext0;
4559
4560       if (AST_LIT_VALUE (root->right->right) !=
4561           (getSize (TTYPE (root->left->left)) * 8 - 1))
4562         goto tryNext0;
4563
4564       /* make sure the port supports RLC */
4565       if (port->hasExtBitOp
4566           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4567         return root;
4568
4569       /* whew got the first case : create the AST */
4570       return newNode (RLC, root->left->left, NULL);
4571     }
4572
4573 tryNext0:
4574   /* check for second case */
4575   /* (?expr >> 7) | (?expr << 1) */
4576   if (IS_LEFT_OP (root->right) &&
4577       IS_RIGHT_OP (root->left))
4578     {
4579
4580       if (!SPEC_USIGN (TETYPE (root->left->left)))
4581         return root;
4582
4583       if (!IS_AST_LIT_VALUE (root->left->right) ||
4584           !IS_AST_LIT_VALUE (root->right->right))
4585         goto tryNext1;
4586
4587       /* make sure it is the same symbol */
4588       if (!isAstEqual (root->left->left,
4589                        root->right->left))
4590         goto tryNext1;
4591
4592       if (AST_LIT_VALUE (root->right->right) != 1)
4593         goto tryNext1;
4594
4595       if (AST_LIT_VALUE (root->left->right) !=
4596           (getSize (TTYPE (root->left->left)) * 8 - 1))
4597         goto tryNext1;
4598
4599       /* make sure the port supports RLC */
4600       if (port->hasExtBitOp
4601           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4602         return root;
4603
4604       /* whew got the first case : create the AST */
4605       return newNode (RLC, root->left->left, NULL);
4606
4607     }
4608
4609 tryNext1:
4610   /* third case for RRC */
4611   /*  (?symbol >> 1) | (?symbol << 7) */
4612   if (IS_LEFT_OP (root->right) &&
4613       IS_RIGHT_OP (root->left))
4614     {
4615
4616       if (!SPEC_USIGN (TETYPE (root->left->left)))
4617         return root;
4618
4619       if (!IS_AST_LIT_VALUE (root->left->right) ||
4620           !IS_AST_LIT_VALUE (root->right->right))
4621         goto tryNext2;
4622
4623       /* make sure it is the same symbol */
4624       if (!isAstEqual (root->left->left,
4625                        root->right->left))
4626         goto tryNext2;
4627
4628       if (AST_LIT_VALUE (root->left->right) != 1)
4629         goto tryNext2;
4630
4631       if (AST_LIT_VALUE (root->right->right) !=
4632           (getSize (TTYPE (root->left->left)) * 8 - 1))
4633         goto tryNext2;
4634
4635       /* make sure the port supports RRC */
4636       if (port->hasExtBitOp
4637           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4638         return root;
4639
4640       /* whew got the first case : create the AST */
4641       return newNode (RRC, root->left->left, NULL);
4642
4643     }
4644 tryNext2:
4645   /* fourth and last case for now */
4646   /* (?symbol << 7) | (?symbol >> 1) */
4647   if (IS_RIGHT_OP (root->right) &&
4648       IS_LEFT_OP (root->left))
4649     {
4650
4651       if (!SPEC_USIGN (TETYPE (root->left->left)))
4652         return root;
4653
4654       if (!IS_AST_LIT_VALUE (root->left->right) ||
4655           !IS_AST_LIT_VALUE (root->right->right))
4656         return root;
4657
4658       /* make sure it is the same symbol */
4659       if (!isAstEqual (root->left->left,
4660                        root->right->left))
4661         return root;
4662
4663       if (AST_LIT_VALUE (root->right->right) != 1)
4664         return root;
4665
4666       if (AST_LIT_VALUE (root->left->right) !=
4667           (getSize (TTYPE (root->left->left)) * 8 - 1))
4668         return root;
4669
4670       /* make sure the port supports RRC */
4671       if (port->hasExtBitOp
4672           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4673         return root;
4674
4675       /* whew got the first case : create the AST */
4676       return newNode (RRC, root->left->left, NULL);
4677
4678     }
4679
4680   /* not found return root */
4681   return root;
4682 }
4683
4684 /*-----------------------------------------------------------------*/
4685 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
4686 /*-----------------------------------------------------------------*/
4687 ast *
4688 optimizeSWAP (ast * root)
4689 {
4690   /* will look for trees of the form
4691      (?expr << 4) | (?expr >> 4) or
4692      (?expr >> 4) | (?expr << 4) will make that
4693      into a SWAP : operation ..
4694      note : by 4 I mean (number of bits required to hold the
4695      variable /2 ) */
4696   /* if the root operations is not a | operation the not */
4697   if (!IS_BITOR (root))
4698     return root;
4699
4700   /* (?expr << 4) | (?expr >> 4) */
4701   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
4702       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
4703     {
4704
4705       if (!SPEC_USIGN (TETYPE (root->left->left)))
4706         return root;
4707
4708       if (!IS_AST_LIT_VALUE (root->left->right) ||
4709           !IS_AST_LIT_VALUE (root->right->right))
4710         return root;
4711
4712       /* make sure it is the same expression */
4713       if (!isAstEqual (root->left->left,
4714                        root->right->left))
4715         return root;
4716
4717       if (AST_LIT_VALUE (root->left->right) !=
4718           (getSize (TTYPE (root->left->left)) * 4))
4719         return root;
4720
4721       if (AST_LIT_VALUE (root->right->right) !=
4722           (getSize (TTYPE (root->left->left)) * 4))
4723         return root;
4724
4725       /* make sure the port supports SWAP */
4726       if (port->hasExtBitOp
4727           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
4728         return root;
4729
4730       /* found it : create the AST */
4731       return newNode (SWAP, root->left->left, NULL);
4732     }
4733
4734
4735   /* not found return root */
4736   return root;
4737 }
4738
4739 /*-----------------------------------------------------------------*/
4740 /* optimizeCompare - otimizes compares for bit variables     */
4741 /*-----------------------------------------------------------------*/
4742 static ast *
4743 optimizeCompare (ast * root)
4744 {
4745   ast *optExpr = NULL;
4746   value *vleft;
4747   value *vright;
4748   unsigned int litValue;
4749
4750   /* if nothing then return nothing */
4751   if (!root)
4752     return NULL;
4753
4754   /* if not a compare op then do leaves */
4755   if (!IS_COMPARE_OP (root))
4756     {
4757       root->left = optimizeCompare (root->left);
4758       root->right = optimizeCompare (root->right);
4759       return root;
4760     }
4761
4762   /* if left & right are the same then depending
4763      of the operation do */
4764   if (isAstEqual (root->left, root->right))
4765     {
4766       switch (root->opval.op)
4767         {
4768         case '>':
4769         case '<':
4770         case NE_OP:
4771           optExpr = newAst_VALUE (constVal ("0"));
4772           break;
4773         case GE_OP:
4774         case LE_OP:
4775         case EQ_OP:
4776           optExpr = newAst_VALUE (constVal ("1"));
4777           break;
4778         }
4779
4780       return decorateType (optExpr);
4781     }
4782
4783   vleft = (root->left->type == EX_VALUE ?
4784            root->left->opval.val : NULL);
4785
4786   vright = (root->right->type == EX_VALUE ?
4787             root->right->opval.val : NULL);
4788
4789   /* if left is a BITVAR in BITSPACE */
4790   /* and right is a LITERAL then opt- */
4791   /* imize else do nothing       */
4792   if (vleft && vright &&
4793       IS_BITVAR (vleft->etype) &&
4794       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
4795       IS_LITERAL (vright->etype))
4796     {
4797
4798       /* if right side > 1 then comparison may never succeed */
4799       if ((litValue = (int) floatFromVal (vright)) > 1)
4800         {
4801           werror (W_BAD_COMPARE);
4802           goto noOptimize;
4803         }
4804
4805       if (litValue)
4806         {
4807           switch (root->opval.op)
4808             {
4809             case '>':           /* bit value greater than 1 cannot be */
4810               werror (W_BAD_COMPARE);
4811               goto noOptimize;
4812               break;
4813
4814             case '<':           /* bit value < 1 means 0 */
4815             case NE_OP:
4816               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
4817               break;
4818
4819             case LE_OP: /* bit value <= 1 means no check */
4820               optExpr = newAst_VALUE (vright);
4821               break;
4822
4823             case GE_OP: /* bit value >= 1 means only check for = */
4824             case EQ_OP:
4825               optExpr = newAst_VALUE (vleft);
4826               break;
4827             }
4828         }
4829       else
4830         {                       /* literal is zero */
4831           switch (root->opval.op)
4832             {
4833             case '<':           /* bit value < 0 cannot be */
4834               werror (W_BAD_COMPARE);
4835               goto noOptimize;
4836               break;
4837
4838             case '>':           /* bit value > 0 means 1 */
4839             case NE_OP:
4840               optExpr = newAst_VALUE (vleft);
4841               break;
4842
4843             case LE_OP: /* bit value <= 0 means no check */
4844             case GE_OP: /* bit value >= 0 means no check */
4845               werror (W_BAD_COMPARE);
4846               goto noOptimize;
4847               break;
4848
4849             case EQ_OP: /* bit == 0 means ! of bit */
4850               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
4851               break;
4852             }
4853         }
4854       return decorateType (resolveSymbols (optExpr));
4855     }                           /* end-of-if of BITVAR */
4856
4857 noOptimize:
4858   return root;
4859 }
4860 /*-----------------------------------------------------------------*/
4861 /* addSymToBlock : adds the symbol to the first block we find      */
4862 /*-----------------------------------------------------------------*/
4863 void 
4864 addSymToBlock (symbol * sym, ast * tree)
4865 {
4866   /* reached end of tree or a leaf */
4867   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
4868     return;
4869
4870   /* found a block */
4871   if (IS_AST_OP (tree) &&
4872       tree->opval.op == BLOCK)
4873     {
4874
4875       symbol *lsym = copySymbol (sym);
4876
4877       lsym->next = AST_VALUES (tree, sym);
4878       AST_VALUES (tree, sym) = lsym;
4879       return;
4880     }
4881
4882   addSymToBlock (sym, tree->left);
4883   addSymToBlock (sym, tree->right);
4884 }
4885
4886 /*-----------------------------------------------------------------*/
4887 /* processRegParms - do processing for register parameters         */
4888 /*-----------------------------------------------------------------*/
4889 static void 
4890 processRegParms (value * args, ast * body)
4891 {
4892   while (args)
4893     {
4894       if (IS_REGPARM (args->etype))
4895         addSymToBlock (args->sym, body);
4896       args = args->next;
4897     }
4898 }
4899
4900 /*-----------------------------------------------------------------*/
4901 /* resetParmKey - resets the operandkeys for the symbols           */
4902 /*-----------------------------------------------------------------*/
4903 DEFSETFUNC (resetParmKey)
4904 {
4905   symbol *sym = item;
4906
4907   sym->key = 0;
4908   sym->defs = NULL;
4909   sym->uses = NULL;
4910   sym->remat = 0;
4911   return 1;
4912 }
4913
4914 /*-----------------------------------------------------------------*/
4915 /* createFunction - This is the key node that calls the iCode for  */
4916 /*                  generating the code for a function. Note code  */
4917 /*                  is generated function by function, later when  */
4918 /*                  add inter-procedural analysis this will change */
4919 /*-----------------------------------------------------------------*/
4920 ast *
4921 createFunction (symbol * name, ast * body)
4922 {
4923   ast *ex;
4924   symbol *csym;
4925   int stack = 0;
4926   sym_link *fetype;
4927   iCode *piCode = NULL;
4928
4929   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
4930     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
4931
4932   /* if check function return 0 then some problem */
4933   if (checkFunction (name, NULL) == 0)
4934     return NULL;
4935
4936   /* create a dummy block if none exists */
4937   if (!body)
4938     body = newNode (BLOCK, NULL, NULL);
4939
4940   noLineno++;
4941
4942   /* check if the function name already in the symbol table */
4943   if ((csym = findSym (SymbolTab, NULL, name->name)))
4944     {
4945       name = csym;
4946       /* special case for compiler defined functions
4947          we need to add the name to the publics list : this
4948          actually means we are now compiling the compiler
4949          support routine */
4950       if (name->cdef)
4951         {
4952           addSet (&publics, name);
4953         }
4954     }
4955   else
4956     {
4957       addSymChain (name);
4958       allocVariables (name);
4959     }
4960   name->lastLine = mylineno;
4961   currFunc = name;
4962
4963   /* set the stack pointer */
4964   /* PENDING: check this for the mcs51 */
4965   stackPtr = -port->stack.direction * port->stack.call_overhead;
4966   if (IFFUNC_ISISR (name->type))
4967     stackPtr -= port->stack.direction * port->stack.isr_overhead;
4968   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
4969     stackPtr -= port->stack.direction * port->stack.reent_overhead;
4970
4971   xstackPtr = -port->stack.direction * port->stack.call_overhead;
4972
4973   fetype = getSpec (name->type);        /* get the specifier for the function */
4974   /* if this is a reentrant function then */
4975   if (IFFUNC_ISREENT (name->type))
4976     reentrant++;
4977
4978   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
4979
4980   /* do processing for parameters that are passed in registers */
4981   processRegParms (FUNC_ARGS(name->type), body);
4982
4983   /* set the stack pointer */
4984   stackPtr = 0;
4985   xstackPtr = -1;
4986
4987   /* allocate & autoinit the block variables */
4988   processBlockVars (body, &stack, ALLOCATE);
4989
4990   /* save the stack information */
4991   if (options.useXstack)
4992     name->xstack = SPEC_STAK (fetype) = stack;
4993   else
4994     name->stack = SPEC_STAK (fetype) = stack;
4995
4996   /* name needs to be mangled */
4997   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
4998
4999   body = resolveSymbols (body); /* resolve the symbols */
5000   body = decorateType (body);   /* propagateType & do semantic checks */
5001
5002   ex = newAst_VALUE (symbolVal (name)); /* create name */
5003   ex = newNode (FUNCTION, ex, body);
5004   ex->values.args = FUNC_ARGS(name->type);
5005   ex->decorated=1;
5006   if (options.dump_tree) PA(ex);
5007   if (fatalError)
5008     {
5009       werror (E_FUNC_NO_CODE, name->name);
5010       goto skipall;
5011     }
5012
5013   /* create the node & generate intermediate code */
5014   GcurMemmap = code;
5015   codeOutFile = code->oFile;
5016   piCode = iCodeFromAst (ex);
5017
5018   if (fatalError)
5019     {
5020       werror (E_FUNC_NO_CODE, name->name);
5021       goto skipall;
5022     }
5023
5024   eBBlockFromiCode (piCode);
5025
5026   /* if there are any statics then do them */
5027   if (staticAutos)
5028     {
5029       GcurMemmap = statsg;
5030       codeOutFile = statsg->oFile;
5031       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos))));
5032       staticAutos = NULL;
5033     }
5034
5035 skipall:
5036
5037   /* dealloc the block variables */
5038   processBlockVars (body, &stack, DEALLOCATE);
5039   outputDebugStackSymbols();
5040   /* deallocate paramaters */
5041   deallocParms (FUNC_ARGS(name->type));
5042
5043   if (IFFUNC_ISREENT (name->type))
5044     reentrant--;
5045
5046   /* we are done freeup memory & cleanup */
5047   noLineno--;
5048   if (port->reset_labelKey) labelKey = 1;
5049   name->key = 0;
5050   FUNC_HASBODY(name->type) = 1;
5051   addSet (&operKeyReset, name);
5052   applyToSet (operKeyReset, resetParmKey);
5053
5054   if (options.debug)
5055     cdbStructBlock(1);
5056
5057   cleanUpLevel (LabelTab, 0);
5058   cleanUpBlock (StructTab, 1);
5059   cleanUpBlock (TypedefTab, 1);
5060
5061   xstack->syms = NULL;
5062   istack->syms = NULL;
5063   return NULL;
5064 }
5065
5066
5067 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5068 /*-----------------------------------------------------------------*/
5069 /* ast_print : prints the ast (for debugging purposes)             */
5070 /*-----------------------------------------------------------------*/
5071
5072 void ast_print (ast * tree, FILE *outfile, int indent)
5073 {
5074
5075         if (!tree) return ;
5076
5077         /* can print only decorated trees */
5078         if (!tree->decorated) return;
5079
5080         /* if any child is an error | this one is an error do nothing */
5081         if (tree->isError ||
5082             (tree->left && tree->left->isError) ||
5083             (tree->right && tree->right->isError)) {
5084                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5085         }
5086
5087
5088         /* print the line          */
5089         /* if not block & function */
5090         if (tree->type == EX_OP &&
5091             (tree->opval.op != FUNCTION &&
5092              tree->opval.op != BLOCK &&
5093              tree->opval.op != NULLOP)) {
5094         }
5095
5096         if (tree->opval.op == FUNCTION) {
5097                 int arg=0;
5098                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5099                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5100                         tree->left->opval.val->name, tree);
5101                 printTypeChain (tree->left->opval.val->type->next,outfile);
5102                 fprintf(outfile,") args (");
5103                 do {
5104                   if (arg) {
5105                     fprintf (outfile, ", ");
5106                   }
5107                   printTypeChain (args ? args->type : NULL, outfile);
5108                   arg++;
5109                   args= args ? args->next : NULL;
5110                 } while (args);
5111                 fprintf(outfile,")\n");
5112                 ast_print(tree->left,outfile,indent);
5113                 ast_print(tree->right,outfile,indent);
5114                 return ;
5115         }
5116         if (tree->opval.op == BLOCK) {
5117                 symbol *decls = tree->values.sym;
5118                 INDENT(indent,outfile);
5119                 fprintf(outfile,"{\n");
5120                 while (decls) {
5121                         INDENT(indent+2,outfile);
5122                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5123                                 decls->name, decls);
5124                         printTypeChain(decls->type,outfile);
5125                         fprintf(outfile,")\n");
5126
5127                         decls = decls->next;
5128                 }
5129                 ast_print(tree->right,outfile,indent+2);
5130                 INDENT(indent,outfile);
5131                 fprintf(outfile,"}\n");
5132                 return;
5133         }
5134         if (tree->opval.op == NULLOP) {
5135                 ast_print(tree->left,outfile,indent);
5136                 ast_print(tree->right,outfile,indent);
5137                 return ;
5138         }
5139         INDENT(indent,outfile);
5140
5141         /*------------------------------------------------------------------*/
5142         /*----------------------------*/
5143         /*   leaf has been reached    */
5144         /*----------------------------*/
5145         /* if this is of type value */
5146         /* just get the type        */
5147         if (tree->type == EX_VALUE) {
5148
5149                 if (IS_LITERAL (tree->opval.val->etype)) {
5150                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5151                         if (SPEC_USIGN (tree->opval.val->etype))
5152                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5153                         else
5154                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5155                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5156                                                       floatFromVal(tree->opval.val));
5157                 } else if (tree->opval.val->sym) {
5158                         /* if the undefined flag is set then give error message */
5159                         if (tree->opval.val->sym->undefined) {
5160                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5161                         } else {
5162                                 fprintf(outfile,"SYMBOL ");
5163                         }
5164                         fprintf(outfile,"(%s=%p)",
5165                                 tree->opval.val->sym->name,tree);
5166                 }
5167                 if (tree->ftype) {
5168                         fprintf(outfile," type (");
5169                         printTypeChain(tree->ftype,outfile);
5170                         fprintf(outfile,")\n");
5171                 } else {
5172                         fprintf(outfile,"\n");
5173                 }
5174                 return ;
5175         }
5176
5177         /* if type link for the case of cast */
5178         if (tree->type == EX_LINK) {
5179                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5180                 printTypeChain(tree->opval.lnk,outfile);
5181                 fprintf(outfile,")\n");
5182                 return ;
5183         }
5184
5185
5186         /* depending on type of operator do */
5187
5188         switch (tree->opval.op) {
5189                 /*------------------------------------------------------------------*/
5190                 /*----------------------------*/
5191                 /*        array node          */
5192                 /*----------------------------*/
5193         case '[':
5194                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5195                 printTypeChain(tree->ftype,outfile);
5196                 fprintf(outfile,")\n");
5197                 ast_print(tree->left,outfile,indent+2);
5198                 ast_print(tree->right,outfile,indent+2);
5199                 return;
5200
5201                 /*------------------------------------------------------------------*/
5202                 /*----------------------------*/
5203                 /*      struct/union          */
5204                 /*----------------------------*/
5205         case '.':
5206                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5207                 printTypeChain(tree->ftype,outfile);
5208                 fprintf(outfile,")\n");
5209                 ast_print(tree->left,outfile,indent+2);
5210                 ast_print(tree->right,outfile,indent+2);
5211                 return ;
5212
5213                 /*------------------------------------------------------------------*/
5214                 /*----------------------------*/
5215                 /*    struct/union pointer    */
5216                 /*----------------------------*/
5217         case PTR_OP:
5218                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5219                 printTypeChain(tree->ftype,outfile);
5220                 fprintf(outfile,")\n");
5221                 ast_print(tree->left,outfile,indent+2);
5222                 ast_print(tree->right,outfile,indent+2);
5223                 return ;
5224
5225                 /*------------------------------------------------------------------*/
5226                 /*----------------------------*/
5227                 /*  ++/-- operation           */
5228                 /*----------------------------*/
5229         case INC_OP:
5230                 if (tree->left)
5231                   fprintf(outfile,"post-");
5232                 else
5233                   fprintf(outfile,"pre-");
5234                 fprintf(outfile,"INC_OP (%p) type (",tree);
5235                 printTypeChain(tree->ftype,outfile);
5236                 fprintf(outfile,")\n");
5237                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5238                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5239                 return ;
5240
5241         case DEC_OP:
5242                 if (tree->left)
5243                   fprintf(outfile,"post-");
5244                 else
5245                   fprintf(outfile,"pre-");
5246                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5247                 printTypeChain(tree->ftype,outfile);
5248                 fprintf(outfile,")\n");
5249                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5250                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5251                 return ;
5252
5253                 /*------------------------------------------------------------------*/
5254                 /*----------------------------*/
5255                 /*  bitwise and               */
5256                 /*----------------------------*/
5257         case '&':
5258                 if (tree->right) {
5259                         fprintf(outfile,"& (%p) type (",tree);
5260                         printTypeChain(tree->ftype,outfile);
5261                         fprintf(outfile,")\n");
5262                         ast_print(tree->left,outfile,indent+2);
5263                         ast_print(tree->right,outfile,indent+2);
5264                 } else {
5265                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5266                         printTypeChain(tree->ftype,outfile);
5267                         fprintf(outfile,")\n");
5268                         ast_print(tree->left,outfile,indent+2);
5269                         ast_print(tree->right,outfile,indent+2);
5270                 }
5271                 return ;
5272                 /*----------------------------*/
5273                 /*  bitwise or                */
5274                 /*----------------------------*/
5275         case '|':
5276                 fprintf(outfile,"OR (%p) type (",tree);
5277                 printTypeChain(tree->ftype,outfile);
5278                 fprintf(outfile,")\n");
5279                 ast_print(tree->left,outfile,indent+2);
5280                 ast_print(tree->right,outfile,indent+2);
5281                 return ;
5282                 /*------------------------------------------------------------------*/
5283                 /*----------------------------*/
5284                 /*  bitwise xor               */
5285                 /*----------------------------*/
5286         case '^':
5287                 fprintf(outfile,"XOR (%p) type (",tree);
5288                 printTypeChain(tree->ftype,outfile);
5289                 fprintf(outfile,")\n");
5290                 ast_print(tree->left,outfile,indent+2);
5291                 ast_print(tree->right,outfile,indent+2);
5292                 return ;
5293
5294                 /*------------------------------------------------------------------*/
5295                 /*----------------------------*/
5296                 /*  division                  */
5297                 /*----------------------------*/
5298         case '/':
5299                 fprintf(outfile,"DIV (%p) type (",tree);
5300                 printTypeChain(tree->ftype,outfile);
5301                 fprintf(outfile,")\n");
5302                 ast_print(tree->left,outfile,indent+2);
5303                 ast_print(tree->right,outfile,indent+2);
5304                 return ;
5305                 /*------------------------------------------------------------------*/
5306                 /*----------------------------*/
5307                 /*            modulus         */
5308                 /*----------------------------*/
5309         case '%':
5310                 fprintf(outfile,"MOD (%p) type (",tree);
5311                 printTypeChain(tree->ftype,outfile);
5312                 fprintf(outfile,")\n");
5313                 ast_print(tree->left,outfile,indent+2);
5314                 ast_print(tree->right,outfile,indent+2);
5315                 return ;
5316
5317                 /*------------------------------------------------------------------*/
5318                 /*----------------------------*/
5319                 /*  address dereference       */
5320                 /*----------------------------*/
5321         case '*':                       /* can be unary  : if right is null then unary operation */
5322                 if (!tree->right) {
5323                         fprintf(outfile,"DEREF (%p) type (",tree);
5324                         printTypeChain(tree->ftype,outfile);
5325                         fprintf(outfile,")\n");
5326                         ast_print(tree->left,outfile,indent+2);
5327                         return ;
5328                 }                       
5329                 /*------------------------------------------------------------------*/
5330                 /*----------------------------*/
5331                 /*      multiplication        */
5332                 /*----------------------------*/                
5333                 fprintf(outfile,"MULT (%p) type (",tree);
5334                 printTypeChain(tree->ftype,outfile);
5335                 fprintf(outfile,")\n");
5336                 ast_print(tree->left,outfile,indent+2);
5337                 ast_print(tree->right,outfile,indent+2);
5338                 return ;
5339
5340
5341                 /*------------------------------------------------------------------*/
5342                 /*----------------------------*/
5343                 /*    unary '+' operator      */
5344                 /*----------------------------*/
5345         case '+':
5346                 /* if unary plus */
5347                 if (!tree->right) {
5348                         fprintf(outfile,"UPLUS (%p) type (",tree);
5349                         printTypeChain(tree->ftype,outfile);
5350                         fprintf(outfile,")\n");
5351                         ast_print(tree->left,outfile,indent+2);
5352                 } else {
5353                         /*------------------------------------------------------------------*/
5354                         /*----------------------------*/
5355                         /*      addition              */
5356                         /*----------------------------*/
5357                         fprintf(outfile,"ADD (%p) type (",tree);
5358                         printTypeChain(tree->ftype,outfile);
5359                         fprintf(outfile,")\n");
5360                         ast_print(tree->left,outfile,indent+2);
5361                         ast_print(tree->right,outfile,indent+2);
5362                 }
5363                 return;
5364                 /*------------------------------------------------------------------*/
5365                 /*----------------------------*/
5366                 /*      unary '-'             */
5367                 /*----------------------------*/
5368         case '-':                       /* can be unary   */
5369                 if (!tree->right) {
5370                         fprintf(outfile,"UMINUS (%p) type (",tree);
5371                         printTypeChain(tree->ftype,outfile);
5372                         fprintf(outfile,")\n");
5373                         ast_print(tree->left,outfile,indent+2);
5374                 } else {
5375                         /*------------------------------------------------------------------*/
5376                         /*----------------------------*/
5377                         /*      subtraction           */
5378                         /*----------------------------*/
5379                         fprintf(outfile,"SUB (%p) type (",tree);
5380                         printTypeChain(tree->ftype,outfile);
5381                         fprintf(outfile,")\n");
5382                         ast_print(tree->left,outfile,indent+2);
5383                         ast_print(tree->right,outfile,indent+2);
5384                 }
5385                 return;
5386                 /*------------------------------------------------------------------*/
5387                 /*----------------------------*/
5388                 /*    compliment              */
5389                 /*----------------------------*/
5390         case '~':
5391                 fprintf(outfile,"COMPL (%p) type (",tree);
5392                 printTypeChain(tree->ftype,outfile);
5393                 fprintf(outfile,")\n");
5394                 ast_print(tree->left,outfile,indent+2);
5395                 return ;
5396                 /*------------------------------------------------------------------*/
5397                 /*----------------------------*/
5398                 /*           not              */
5399                 /*----------------------------*/
5400         case '!':
5401                 fprintf(outfile,"NOT (%p) type (",tree);
5402                 printTypeChain(tree->ftype,outfile);
5403                 fprintf(outfile,")\n");
5404                 ast_print(tree->left,outfile,indent+2);
5405                 return ;
5406                 /*------------------------------------------------------------------*/
5407                 /*----------------------------*/
5408                 /*           shift            */
5409                 /*----------------------------*/
5410         case RRC:
5411                 fprintf(outfile,"RRC (%p) type (",tree);
5412                 printTypeChain(tree->ftype,outfile);
5413                 fprintf(outfile,")\n");
5414                 ast_print(tree->left,outfile,indent+2);
5415                 return ;
5416
5417         case RLC:
5418                 fprintf(outfile,"RLC (%p) type (",tree);
5419                 printTypeChain(tree->ftype,outfile);
5420                 fprintf(outfile,")\n");
5421                 ast_print(tree->left,outfile,indent+2);
5422                 return ;
5423         case SWAP:
5424                 fprintf(outfile,"SWAP (%p) type (",tree);
5425                 printTypeChain(tree->ftype,outfile);
5426                 fprintf(outfile,")\n");
5427                 ast_print(tree->left,outfile,indent+2);
5428                 return ;
5429         case GETHBIT:
5430                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5431                 printTypeChain(tree->ftype,outfile);
5432                 fprintf(outfile,")\n");
5433                 ast_print(tree->left,outfile,indent+2);
5434                 return ;
5435         case LEFT_OP:
5436                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5437                 printTypeChain(tree->ftype,outfile);
5438                 fprintf(outfile,")\n");
5439                 ast_print(tree->left,outfile,indent+2);
5440                 ast_print(tree->right,outfile,indent+2);
5441                 return ;
5442         case RIGHT_OP:
5443                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5444                 printTypeChain(tree->ftype,outfile);
5445                 fprintf(outfile,")\n");
5446                 ast_print(tree->left,outfile,indent+2);
5447                 ast_print(tree->right,outfile,indent+2);
5448                 return ;
5449                 /*------------------------------------------------------------------*/
5450                 /*----------------------------*/
5451                 /*         casting            */
5452                 /*----------------------------*/
5453         case CAST:                      /* change the type   */
5454                 fprintf(outfile,"CAST (%p) from type (",tree);
5455                 printTypeChain(tree->right->ftype,outfile);
5456                 fprintf(outfile,") to type (");
5457                 printTypeChain(tree->ftype,outfile);
5458                 fprintf(outfile,")\n");
5459                 ast_print(tree->right,outfile,indent+2);
5460                 return ;
5461                 
5462         case AND_OP:
5463                 fprintf(outfile,"ANDAND (%p) type (",tree);
5464                 printTypeChain(tree->ftype,outfile);
5465                 fprintf(outfile,")\n");
5466                 ast_print(tree->left,outfile,indent+2);
5467                 ast_print(tree->right,outfile,indent+2);
5468                 return ;
5469         case OR_OP:
5470                 fprintf(outfile,"OROR (%p) type (",tree);
5471                 printTypeChain(tree->ftype,outfile);
5472                 fprintf(outfile,")\n");
5473                 ast_print(tree->left,outfile,indent+2);
5474                 ast_print(tree->right,outfile,indent+2);
5475                 return ;
5476                 
5477                 /*------------------------------------------------------------------*/
5478                 /*----------------------------*/
5479                 /*     comparison operators   */
5480                 /*----------------------------*/
5481         case '>':
5482                 fprintf(outfile,"GT(>) (%p) type (",tree);
5483                 printTypeChain(tree->ftype,outfile);
5484                 fprintf(outfile,")\n");
5485                 ast_print(tree->left,outfile,indent+2);
5486                 ast_print(tree->right,outfile,indent+2);
5487                 return ;
5488         case '<':
5489                 fprintf(outfile,"LT(<) (%p) type (",tree);
5490                 printTypeChain(tree->ftype,outfile);
5491                 fprintf(outfile,")\n");
5492                 ast_print(tree->left,outfile,indent+2);
5493                 ast_print(tree->right,outfile,indent+2);
5494                 return ;
5495         case LE_OP:
5496                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5497                 printTypeChain(tree->ftype,outfile);
5498                 fprintf(outfile,")\n");
5499                 ast_print(tree->left,outfile,indent+2);
5500                 ast_print(tree->right,outfile,indent+2);
5501                 return ;
5502         case GE_OP:
5503                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5504                 printTypeChain(tree->ftype,outfile);
5505                 fprintf(outfile,")\n");
5506                 ast_print(tree->left,outfile,indent+2);
5507                 ast_print(tree->right,outfile,indent+2);
5508                 return ;
5509         case EQ_OP:
5510                 fprintf(outfile,"EQ(==) (%p) type (",tree);
5511                 printTypeChain(tree->ftype,outfile);
5512                 fprintf(outfile,")\n");
5513                 ast_print(tree->left,outfile,indent+2);
5514                 ast_print(tree->right,outfile,indent+2);
5515                 return ;
5516         case NE_OP:
5517                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5518                 printTypeChain(tree->ftype,outfile);
5519                 fprintf(outfile,")\n");
5520                 ast_print(tree->left,outfile,indent+2);
5521                 ast_print(tree->right,outfile,indent+2);
5522                 /*------------------------------------------------------------------*/
5523                 /*----------------------------*/
5524                 /*             sizeof         */
5525                 /*----------------------------*/
5526         case SIZEOF:            /* evaluate wihout code generation */
5527                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5528                 return ;
5529
5530                 /*------------------------------------------------------------------*/
5531                 /*----------------------------*/
5532                 /* conditional operator  '?'  */
5533                 /*----------------------------*/
5534         case '?':
5535                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5536                 printTypeChain(tree->ftype,outfile);
5537                 fprintf(outfile,")\n");
5538                 ast_print(tree->left,outfile,indent+2);
5539                 ast_print(tree->right,outfile,indent+2);
5540                 return;
5541
5542         case ':':
5543                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5544                 printTypeChain(tree->ftype,outfile);
5545                 fprintf(outfile,")\n");
5546                 ast_print(tree->left,outfile,indent+2);
5547                 ast_print(tree->right,outfile,indent+2);
5548                 return ;
5549                 
5550                 /*------------------------------------------------------------------*/
5551                 /*----------------------------*/
5552                 /*    assignment operators    */
5553                 /*----------------------------*/
5554         case MUL_ASSIGN:
5555                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5556                 printTypeChain(tree->ftype,outfile);
5557                 fprintf(outfile,")\n");
5558                 ast_print(tree->left,outfile,indent+2);
5559                 ast_print(tree->right,outfile,indent+2);
5560                 return;
5561         case DIV_ASSIGN:
5562                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5563                 printTypeChain(tree->ftype,outfile);
5564                 fprintf(outfile,")\n");
5565                 ast_print(tree->left,outfile,indent+2);
5566                 ast_print(tree->right,outfile,indent+2);
5567                 return;
5568         case AND_ASSIGN:
5569                 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
5570                 printTypeChain(tree->ftype,outfile);
5571                 fprintf(outfile,")\n");
5572                 ast_print(tree->left,outfile,indent+2);
5573                 ast_print(tree->right,outfile,indent+2);
5574                 return;
5575         case OR_ASSIGN:
5576                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5577                 printTypeChain(tree->ftype,outfile);
5578                 fprintf(outfile,")\n");
5579                 ast_print(tree->left,outfile,indent+2);
5580                 ast_print(tree->right,outfile,indent+2);
5581                 return;
5582         case XOR_ASSIGN:
5583                 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
5584                 printTypeChain(tree->ftype,outfile);
5585                 fprintf(outfile,")\n");
5586                 ast_print(tree->left,outfile,indent+2);
5587                 ast_print(tree->right,outfile,indent+2);
5588                 return;
5589         case RIGHT_ASSIGN:
5590                 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
5591                 printTypeChain(tree->ftype,outfile);
5592                 fprintf(outfile,")\n");
5593                 ast_print(tree->left,outfile,indent+2);
5594                 ast_print(tree->right,outfile,indent+2);
5595                 return;
5596         case LEFT_ASSIGN:
5597                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5598                 printTypeChain(tree->ftype,outfile);
5599                 fprintf(outfile,")\n");
5600                 ast_print(tree->left,outfile,indent+2);
5601                 ast_print(tree->right,outfile,indent+2);
5602                 return;
5603                 /*------------------------------------------------------------------*/
5604                 /*----------------------------*/
5605                 /*    -= operator             */
5606                 /*----------------------------*/
5607         case SUB_ASSIGN:
5608                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5609                 printTypeChain(tree->ftype,outfile);
5610                 fprintf(outfile,")\n");
5611                 ast_print(tree->left,outfile,indent+2);
5612                 ast_print(tree->right,outfile,indent+2);
5613                 return;
5614                 /*------------------------------------------------------------------*/
5615                 /*----------------------------*/
5616                 /*          += operator       */
5617                 /*----------------------------*/
5618         case ADD_ASSIGN:
5619                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5620                 printTypeChain(tree->ftype,outfile);
5621                 fprintf(outfile,")\n");
5622                 ast_print(tree->left,outfile,indent+2);
5623                 ast_print(tree->right,outfile,indent+2);
5624                 return;
5625                 /*------------------------------------------------------------------*/
5626                 /*----------------------------*/
5627                 /*      straight assignemnt   */
5628                 /*----------------------------*/
5629         case '=':
5630                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5631                 printTypeChain(tree->ftype,outfile);
5632                 fprintf(outfile,")\n");
5633                 ast_print(tree->left,outfile,indent+2);
5634                 ast_print(tree->right,outfile,indent+2);
5635                 return;     
5636                 /*------------------------------------------------------------------*/
5637                 /*----------------------------*/
5638                 /*      comma operator        */
5639                 /*----------------------------*/
5640         case ',':
5641                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
5642                 printTypeChain(tree->ftype,outfile);
5643                 fprintf(outfile,")\n");
5644                 ast_print(tree->left,outfile,indent+2);
5645                 ast_print(tree->right,outfile,indent+2);
5646                 return;
5647                 /*------------------------------------------------------------------*/
5648                 /*----------------------------*/
5649                 /*       function call        */
5650                 /*----------------------------*/
5651         case CALL:
5652         case PCALL:
5653                 fprintf(outfile,"CALL (%p) type (",tree);
5654                 printTypeChain(tree->ftype,outfile);
5655                 fprintf(outfile,")\n");
5656                 ast_print(tree->left,outfile,indent+2);
5657                 ast_print(tree->right,outfile,indent+2);
5658                 return;
5659         case PARAM:
5660                 fprintf(outfile,"PARMS\n");
5661                 ast_print(tree->left,outfile,indent+2);
5662                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
5663                         ast_print(tree->right,outfile,indent+2);
5664                 }
5665                 return ;
5666                 /*------------------------------------------------------------------*/
5667                 /*----------------------------*/
5668                 /*     return statement       */
5669                 /*----------------------------*/
5670         case RETURN:
5671                 fprintf(outfile,"RETURN (%p) type (",tree);
5672                 if (tree->right) {
5673                     printTypeChain(tree->right->ftype,outfile);
5674                 }
5675                 fprintf(outfile,")\n");
5676                 ast_print(tree->right,outfile,indent+2);
5677                 return ;
5678                 /*------------------------------------------------------------------*/
5679                 /*----------------------------*/
5680                 /*     label statement        */
5681                 /*----------------------------*/
5682         case LABEL :
5683                 fprintf(outfile,"LABEL (%p)\n",tree);
5684                 ast_print(tree->left,outfile,indent+2);
5685                 ast_print(tree->right,outfile,indent);
5686                 return;
5687                 /*------------------------------------------------------------------*/
5688                 /*----------------------------*/
5689                 /*     switch statement       */
5690                 /*----------------------------*/
5691         case SWITCH:
5692                 {
5693                         value *val;
5694                         fprintf(outfile,"SWITCH (%p) ",tree);
5695                         ast_print(tree->left,outfile,0);
5696                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
5697                                 INDENT(indent+2,outfile);
5698                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
5699                                         (int) floatFromVal(val),
5700                                         tree->values.switchVals.swNum,
5701                                         (int) floatFromVal(val));
5702                         }
5703                         ast_print(tree->right,outfile,indent);
5704                 }
5705                 return ;
5706                 /*------------------------------------------------------------------*/
5707                 /*----------------------------*/
5708                 /* ifx Statement              */
5709                 /*----------------------------*/
5710         case IFX:
5711                 fprintf(outfile,"IF (%p) \n",tree);
5712                 ast_print(tree->left,outfile,indent+2);
5713                 if (tree->trueLabel) {
5714                         INDENT(indent+2,outfile);
5715                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
5716                 }
5717                 if (tree->falseLabel) {
5718                         INDENT(indent+2,outfile);
5719                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
5720                 }
5721                 ast_print(tree->right,outfile,indent+2);
5722                 return ;
5723                 /*----------------------------*/
5724                 /* goto Statement              */
5725                 /*----------------------------*/
5726         case GOTO:
5727                 fprintf(outfile,"GOTO (%p) \n",tree);
5728                 ast_print(tree->left,outfile,indent+2);
5729                 fprintf(outfile,"\n");
5730                 return ;
5731                 /*------------------------------------------------------------------*/
5732                 /*----------------------------*/
5733                 /* for Statement              */
5734                 /*----------------------------*/
5735         case FOR:
5736                 fprintf(outfile,"FOR (%p) \n",tree);
5737                 if (AST_FOR( tree, initExpr)) {
5738                         INDENT(indent+2,outfile);
5739                         fprintf(outfile,"INIT EXPR ");
5740                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
5741                 }
5742                 if (AST_FOR( tree, condExpr)) {
5743                         INDENT(indent+2,outfile);
5744                         fprintf(outfile,"COND EXPR ");
5745                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
5746                 }
5747                 if (AST_FOR( tree, loopExpr)) {
5748                         INDENT(indent+2,outfile);
5749                         fprintf(outfile,"LOOP EXPR ");
5750                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
5751                 }
5752                 fprintf(outfile,"FOR LOOP BODY \n");
5753                 ast_print(tree->left,outfile,indent+2);
5754                 return ;
5755         case CRITICAL:
5756                 fprintf(outfile,"CRITICAL (%p) \n",tree);
5757                 ast_print(tree->left,outfile,indent+2);
5758         default:
5759             return ;
5760         }
5761 }
5762
5763 void PA(ast *t)
5764 {
5765         ast_print(t,stdout,0);
5766 }
5767
5768
5769
5770 /*-----------------------------------------------------------------*/
5771 /* astErrors : returns non-zero if errors present in tree          */
5772 /*-----------------------------------------------------------------*/
5773 int astErrors(ast *t)
5774 {
5775   int errors=0;
5776   
5777   if (t)
5778     {
5779       if (t->isError)
5780         errors++;
5781   
5782       if (t->type == EX_VALUE
5783           && t->opval.val->sym
5784           && t->opval.val->sym->undefined)
5785         errors++;
5786
5787       errors += astErrors(t->left);
5788       errors += astErrors(t->right);
5789     }
5790     
5791   return errors;
5792 }