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