d0ba0c9b26fbabd151b9d0e13e3657df77f0574f
[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         break;
2172       case FPOINTER:
2173         SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2174         break;
2175       case CPOINTER:
2176         SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2177         break;
2178       case GPOINTER:
2179         break;
2180       case PPOINTER:
2181         SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2182         break;
2183       case IPOINTER:
2184         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2185         break;
2186       case EEPPOINTER:
2187         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2188         break;
2189       case UPOINTER:
2190       case ARRAY:
2191       case FUNCTION:
2192         break;
2193       }
2194       
2195       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2196           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2197         {
2198             /* If defined    struct type at addr var
2199                then rewrite  (&struct var)->member
2200                as            temp
2201                and define    membertype at (addr+offsetof(struct var,member)) temp
2202             */
2203             symbol *sym;
2204             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2205                                                 AST_SYMBOL(tree->right));
2206
2207             sym = newSymbol(genSymName (0), 0);
2208             sym->type = TTYPE (tree);
2209             sym->etype = getSpec(sym->type);
2210             sym->lineDef = tree->lineno;
2211             sym->cdef = 1;
2212             sym->isref = 1;
2213             SPEC_STAT (sym->etype) = 1;
2214             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2215                                      + element->offset;
2216             SPEC_ABSA(sym->etype) = 1;
2217             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2218             allocGlobal (sym);
2219             
2220             AST_VALUE (tree) = symbolVal(sym);
2221             TLVAL (tree) = 1;
2222             TRVAL (tree) = 0;
2223             tree->type = EX_VALUE;
2224             tree->left = NULL;
2225             tree->right = NULL;
2226         }
2227
2228       return tree;
2229
2230       /*------------------------------------------------------------------*/
2231       /*----------------------------*/
2232       /*  ++/-- operation           */
2233       /*----------------------------*/
2234     case INC_OP:
2235     case DEC_OP:
2236       {
2237         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2238         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2239         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2240           werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2241
2242         if (tree->right)
2243           RLVAL (tree) = 1;
2244         else
2245           LLVAL (tree) = 1;
2246         return tree;
2247       }
2248
2249       /*------------------------------------------------------------------*/
2250       /*----------------------------*/
2251       /*  bitwise and               */
2252       /*----------------------------*/
2253     case '&':                   /* can be unary   */
2254       /* if right is NULL then unary operation  */
2255       if (tree->right)          /* not an unary operation */
2256         {
2257
2258           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2259             {
2260               werror (E_BITWISE_OP);
2261               werror (W_CONTINUE, "left & right types are ");
2262               printTypeChain (LTYPE (tree), stderr);
2263               fprintf (stderr, ",");
2264               printTypeChain (RTYPE (tree), stderr);
2265               fprintf (stderr, "\n");
2266               goto errorTreeReturn;
2267             }
2268
2269           /* if they are both literal */
2270           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2271             {
2272               tree->type = EX_VALUE;
2273               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2274                                           valFromType (RETYPE (tree)), '&');
2275
2276               tree->right = tree->left = NULL;
2277               TETYPE (tree) = tree->opval.val->etype;
2278               TTYPE (tree) = tree->opval.val->type;
2279               return tree;
2280             }
2281
2282           /* see if this is a GETHBIT operation if yes
2283              then return that */
2284           {
2285             ast *otree = optimizeGetHbit (tree);
2286
2287             if (otree != tree)
2288               return decorateType (otree);
2289           }
2290
2291           TTYPE (tree) =
2292             computeType (LTYPE (tree), RTYPE (tree));
2293           TETYPE (tree) = getSpec (TTYPE (tree));
2294
2295           /* if left is a literal exchange left & right */
2296           if (IS_LITERAL (LTYPE (tree)))
2297             {
2298               ast *tTree = tree->left;
2299               tree->left = tree->right;
2300               tree->right = tTree;
2301             }
2302
2303           /* if right is a literal and */
2304           /* we can find a 2nd literal in a and-tree then */
2305           /* rearrange the tree */
2306           if (IS_LITERAL (RTYPE (tree)))
2307             {
2308               ast *parent;
2309               ast *litTree = searchLitOp (tree, &parent, "&");
2310               if (litTree)
2311                 {
2312                   ast *tTree = litTree->left;
2313                   litTree->left = tree->right;
2314                   tree->right = tTree;
2315                   /* both operands in tTree are literal now */
2316                   decorateType (parent);
2317                 }
2318             }
2319
2320           LRVAL (tree) = RRVAL (tree) = 1;
2321           return tree;
2322         }
2323
2324       /*------------------------------------------------------------------*/
2325       /*----------------------------*/
2326       /*  address of                */
2327       /*----------------------------*/
2328       p = newLink (DECLARATOR);
2329       /* if bit field then error */
2330       if (IS_BITVAR (tree->left->etype))
2331         {
2332           werror (E_ILLEGAL_ADDR, "address of bit variable");
2333           goto errorTreeReturn;
2334         }
2335
2336       if (SPEC_SCLS (tree->left->etype) == S_REGISTER)
2337         {
2338           werror (E_ILLEGAL_ADDR, "address of register variable");
2339           goto errorTreeReturn;
2340         }
2341
2342       if (IS_FUNC (LTYPE (tree)))
2343         {
2344           // this ought to be ignored
2345           return (tree->left);
2346         }
2347
2348       if (IS_LITERAL(LTYPE(tree)))
2349         {
2350           werror (E_ILLEGAL_ADDR, "address of literal");
2351           goto errorTreeReturn;
2352         }
2353
2354      if (LRVAL (tree))
2355         {
2356           werror (E_LVALUE_REQUIRED, "address of");
2357           goto errorTreeReturn;
2358         }
2359       if (SPEC_SCLS (tree->left->etype) == S_CODE)
2360         DCL_TYPE (p) = CPOINTER;
2361       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2362         DCL_TYPE (p) = FPOINTER;
2363       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2364         DCL_TYPE (p) = PPOINTER;
2365       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2366         DCL_TYPE (p) = IPOINTER;
2367       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2368         DCL_TYPE (p) = EEPPOINTER;
2369       else if (SPEC_OCLS(tree->left->etype))
2370           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2371       else
2372           DCL_TYPE (p) = POINTER;
2373
2374       if (IS_AST_SYM_VALUE (tree->left))
2375         {
2376           AST_SYMBOL (tree->left)->addrtaken = 1;
2377           AST_SYMBOL (tree->left)->allocreq = 1;
2378         }
2379
2380       p->next = LTYPE (tree);
2381       TTYPE (tree) = p;
2382       TETYPE (tree) = getSpec (TTYPE (tree));
2383       LLVAL (tree) = 1;
2384       TLVAL (tree) = 1;
2385
2386       #if 0
2387       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2388           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2389         {
2390           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2391                                       AST_SYMBOL(tree->left->right));
2392           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2393                                     valueFromLit(element->offset));
2394           tree->left = NULL;
2395           tree->right = NULL;
2396           tree->type = EX_VALUE;
2397           tree->values.literalFromCast = 1;
2398         }
2399       #endif
2400
2401       return tree;
2402
2403       /*------------------------------------------------------------------*/
2404       /*----------------------------*/
2405       /*  bitwise or                */
2406       /*----------------------------*/
2407     case '|':
2408       /* if the rewrite succeeds then don't go any furthur */
2409       {
2410         ast *wtree = optimizeRRCRLC (tree);
2411         if (wtree != tree)
2412           return decorateType (wtree);
2413         
2414         wtree = optimizeSWAP (tree);
2415         if (wtree != tree)
2416           return decorateType (wtree);
2417         
2418         // fall through
2419       }
2420
2421       /* if left is a literal exchange left & right */
2422       if (IS_LITERAL (LTYPE (tree)))
2423         {
2424           ast *tTree = tree->left;
2425           tree->left = tree->right;
2426           tree->right = tTree;
2427         }
2428
2429       /* if right is a literal and */
2430       /* we can find a 2nd literal in a or-tree then */
2431       /* rearrange the tree */
2432       if (IS_LITERAL (RTYPE (tree)))
2433         {
2434           ast *parent;
2435           ast *litTree = searchLitOp (tree, &parent, "|");
2436           if (litTree)
2437             {
2438               ast *tTree = litTree->left;
2439               litTree->left = tree->right;
2440               tree->right = tTree;
2441               /* both operands in tTree are literal now */
2442               decorateType (parent);
2443             }
2444         }
2445       /*------------------------------------------------------------------*/
2446       /*----------------------------*/
2447       /*  bitwise xor               */
2448       /*----------------------------*/
2449     case '^':
2450       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2451         {
2452           werror (E_BITWISE_OP);
2453           werror (W_CONTINUE, "left & right types are ");
2454           printTypeChain (LTYPE (tree), stderr);
2455           fprintf (stderr, ",");
2456           printTypeChain (RTYPE (tree), stderr);
2457           fprintf (stderr, "\n");
2458           goto errorTreeReturn;
2459         }
2460
2461       /* if they are both literal then */
2462       /* rewrite the tree */
2463       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2464         {
2465           tree->type = EX_VALUE;
2466           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2467                                         valFromType (RETYPE (tree)),
2468                                         tree->opval.op);
2469           tree->right = tree->left = NULL;
2470           TETYPE (tree) = tree->opval.val->etype;
2471           TTYPE (tree) = tree->opval.val->type;
2472           return tree;
2473         }
2474
2475       /* if left is a literal exchange left & right */
2476       if (IS_LITERAL (LTYPE (tree)))
2477         {
2478           ast *tTree = tree->left;
2479           tree->left = tree->right;
2480           tree->right = tTree;
2481         }
2482
2483       /* if right is a literal and */
2484       /* we can find a 2nd literal in a xor-tree then */
2485       /* rearrange the tree */
2486       if (IS_LITERAL (RTYPE (tree)))
2487         {
2488           ast *parent;
2489           ast *litTree = searchLitOp (tree, &parent, "^");
2490           if (litTree)
2491             {
2492               ast *tTree = litTree->left;
2493               litTree->left = tree->right;
2494               tree->right = tTree;
2495               /* both operands in litTree are literal now */
2496               decorateType (parent);
2497             }
2498         }
2499
2500       LRVAL (tree) = RRVAL (tree) = 1;
2501       TETYPE (tree) = getSpec (TTYPE (tree) =
2502                                computeType (LTYPE (tree),
2503                                             RTYPE (tree)));
2504
2505       /*------------------------------------------------------------------*/
2506       /*----------------------------*/
2507       /*  division                  */
2508       /*----------------------------*/
2509     case '/':
2510       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2511         {
2512           werror (E_INVALID_OP, "divide");
2513           goto errorTreeReturn;
2514         }
2515       /* if they are both literal then */
2516       /* rewrite the tree */
2517       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2518         {
2519           tree->type = EX_VALUE;
2520           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
2521                                     valFromType (RETYPE (tree)));
2522           tree->right = tree->left = NULL;
2523           TETYPE (tree) = getSpec (TTYPE (tree) =
2524                                    tree->opval.val->type);
2525           return tree;
2526         }
2527
2528       LRVAL (tree) = RRVAL (tree) = 1;
2529       TETYPE (tree) = getSpec (TTYPE (tree) =
2530                                computeType (LTYPE (tree),
2531                                             RTYPE (tree)));
2532
2533       /* if right is a literal and */
2534       /* left is also a division by a literal then */
2535       /* rearrange the tree */
2536       if (IS_LITERAL (RTYPE (tree))
2537           /* avoid infinite loop */
2538           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
2539         {
2540           ast *parent;
2541           ast *litTree = searchLitOp (tree, &parent, "/");
2542           if (litTree)
2543             {
2544               if (IS_LITERAL (RTYPE (litTree)))
2545                 {
2546                   /* foo_div */
2547                   litTree->right = newNode ('*', litTree->right, tree->right);
2548                   litTree->right->lineno = tree->lineno;
2549
2550                   tree->right->opval.val = constVal ("1");
2551                   decorateType (parent);
2552                 }
2553               else
2554                 {
2555                   /* litTree->left is literal: no gcse possible.
2556                      We can't call decorateType(parent), because
2557                      this would cause an infinit loop. */
2558                   parent->decorated = 1;
2559                   decorateType (litTree);
2560                 }
2561             }
2562         }
2563
2564       return tree;
2565
2566       /*------------------------------------------------------------------*/
2567       /*----------------------------*/
2568       /*            modulus         */
2569       /*----------------------------*/
2570     case '%':
2571       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2572         {
2573           werror (E_BITWISE_OP);
2574           werror (W_CONTINUE, "left & right types are ");
2575           printTypeChain (LTYPE (tree), stderr);
2576           fprintf (stderr, ",");
2577           printTypeChain (RTYPE (tree), stderr);
2578           fprintf (stderr, "\n");
2579           goto errorTreeReturn;
2580         }
2581       /* if they are both literal then */
2582       /* rewrite the tree */
2583       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2584         {
2585           tree->type = EX_VALUE;
2586           tree->opval.val = valMod (valFromType (LETYPE (tree)),
2587                                     valFromType (RETYPE (tree)));
2588           tree->right = tree->left = NULL;
2589           TETYPE (tree) = getSpec (TTYPE (tree) =
2590                                    tree->opval.val->type);
2591           return tree;
2592         }
2593       LRVAL (tree) = RRVAL (tree) = 1;
2594       TETYPE (tree) = getSpec (TTYPE (tree) =
2595                                computeType (LTYPE (tree),
2596                                             RTYPE (tree)));
2597       return tree;
2598
2599       /*------------------------------------------------------------------*/
2600       /*----------------------------*/
2601       /*  address dereference       */
2602       /*----------------------------*/
2603     case '*':                   /* can be unary  : if right is null then unary operation */
2604       if (!tree->right)
2605         {
2606           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2607             {
2608               werror (E_PTR_REQD);
2609               goto errorTreeReturn;
2610             }
2611
2612           if (LRVAL (tree))
2613             {
2614               werror (E_LVALUE_REQUIRED, "pointer deref");
2615               goto errorTreeReturn;
2616             }
2617           if (IS_ADDRESS_OF_OP(tree->left))
2618             {
2619               /* replace *&obj with obj */
2620               return tree->left->left;
2621             }
2622           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
2623           TETYPE (tree) = getSpec (TTYPE (tree));
2624           return tree;
2625         }
2626
2627       /*------------------------------------------------------------------*/
2628       /*----------------------------*/
2629       /*      multiplication        */
2630       /*----------------------------*/
2631       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2632         {
2633           werror (E_INVALID_OP, "multiplication");
2634           goto errorTreeReturn;
2635         }
2636
2637       /* if they are both literal then */
2638       /* rewrite the tree */
2639       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2640         {
2641           tree->type = EX_VALUE;
2642           tree->opval.val = valMult (valFromType (LETYPE (tree)),
2643                                      valFromType (RETYPE (tree)));
2644           tree->right = tree->left = NULL;
2645           TETYPE (tree) = getSpec (TTYPE (tree) =
2646                                    tree->opval.val->type);
2647           return tree;
2648         }
2649
2650       /* if left is a literal exchange left & right */
2651       if (IS_LITERAL (LTYPE (tree)))
2652         {
2653           ast *tTree = tree->left;
2654           tree->left = tree->right;
2655           tree->right = tTree;
2656         }
2657
2658       /* if right is a literal and */
2659       /* we can find a 2nd literal in a mul-tree then */
2660       /* rearrange the tree */
2661       if (IS_LITERAL (RTYPE (tree)))
2662         {
2663           ast *parent;
2664           ast *litTree = searchLitOp (tree, &parent, "*");
2665           if (litTree)
2666             {
2667               ast *tTree = litTree->left;
2668               litTree->left = tree->right;
2669               tree->right = tTree;
2670               /* both operands in litTree are literal now */
2671               decorateType (parent);
2672             }
2673         }
2674
2675       LRVAL (tree) = RRVAL (tree) = 1;
2676       TETYPE (tree) = getSpec (TTYPE (tree) =
2677                                computeType (LTYPE (tree),
2678                                             RTYPE (tree)));
2679
2680       /* promote result to int if left & right are char
2681          this will facilitate hardware multiplies 8bit x 8bit = 16bit */
2682       if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
2683         SPEC_NOUN(TETYPE(tree)) = V_INT;
2684       }
2685
2686       return tree;
2687
2688       /*------------------------------------------------------------------*/
2689       /*----------------------------*/
2690       /*    unary '+' operator      */
2691       /*----------------------------*/
2692     case '+':
2693       /* if unary plus */
2694       if (!tree->right)
2695         {
2696           if (!IS_INTEGRAL (LTYPE (tree)))
2697             {
2698               werror (E_UNARY_OP, '+');
2699               goto errorTreeReturn;
2700             }
2701
2702           /* if left is a literal then do it */
2703           if (IS_LITERAL (LTYPE (tree)))
2704             {
2705               tree->type = EX_VALUE;
2706               tree->opval.val = valFromType (LETYPE (tree));
2707               tree->left = NULL;
2708               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2709               return tree;
2710             }
2711           LRVAL (tree) = 1;
2712           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
2713           return tree;
2714         }
2715
2716       /*------------------------------------------------------------------*/
2717       /*----------------------------*/
2718       /*      addition              */
2719       /*----------------------------*/
2720
2721       /* this is not a unary operation */
2722       /* if both pointers then problem */
2723       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
2724           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
2725         {
2726           werror (E_PTR_PLUS_PTR);
2727           goto errorTreeReturn;
2728         }
2729
2730       if (!IS_ARITHMETIC (LTYPE (tree)) &&
2731           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2732         {
2733           werror (E_PLUS_INVALID, "+");
2734           goto errorTreeReturn;
2735         }
2736
2737       if (!IS_ARITHMETIC (RTYPE (tree)) &&
2738           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
2739         {
2740           werror (E_PLUS_INVALID, "+");
2741           goto errorTreeReturn;
2742         }
2743       /* if they are both literal then */
2744       /* rewrite the tree */
2745       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2746         {
2747           tree->type = EX_VALUE;
2748           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
2749                                      valFromType (RETYPE (tree)));
2750           tree->right = tree->left = NULL;
2751           TETYPE (tree) = getSpec (TTYPE (tree) =
2752                                    tree->opval.val->type);
2753           return tree;
2754         }
2755
2756       /* if the right is a pointer or left is a literal
2757          xchange left & right */
2758       if (IS_ARRAY (RTYPE (tree)) ||
2759           IS_PTR (RTYPE (tree)) ||
2760           IS_LITERAL (LTYPE (tree)))
2761         {
2762           ast *tTree = tree->left;
2763           tree->left = tree->right;
2764           tree->right = tTree;
2765         }
2766
2767       /* if right is a literal and */
2768       /* left is also an addition/subtraction with a literal then */
2769       /* rearrange the tree */
2770       if (IS_LITERAL (RTYPE (tree)))
2771         {
2772           ast *litTree, *parent;
2773           litTree = searchLitOp (tree, &parent, "+-");
2774           if (litTree)
2775             {
2776               if (litTree->opval.op == '+')
2777                 {
2778                   /* foo_aa */
2779                   ast *tTree = litTree->left;
2780                   litTree->left = tree->right;
2781                   tree->right = tree->left;
2782                   tree->left = tTree;
2783                 }
2784               else if (litTree->opval.op == '-')
2785                 {
2786                   if (IS_LITERAL (RTYPE (litTree)))
2787                     {
2788                       /* foo_asr */
2789                       ast *tTree = litTree->left;
2790                       litTree->left = tree->right;
2791                       tree->right = tTree;
2792                     }
2793                   else
2794                     {
2795                       /* foo_asl */
2796                       ast *tTree = litTree->right;
2797                       litTree->right = tree->right;
2798                       tree->right = tTree;
2799                       litTree->opval.op = '+';
2800                       tree->opval.op = '-';
2801                     }
2802                 }
2803               decorateType (parent);
2804             }
2805         }
2806
2807       LRVAL (tree) = RRVAL (tree) = 1;
2808       /* if the left is a pointer */
2809       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
2810         TETYPE (tree) = getSpec (TTYPE (tree) =
2811                                  LTYPE (tree));
2812       else
2813         TETYPE (tree) = getSpec (TTYPE (tree) =
2814                                  computeType (LTYPE (tree),
2815                                               RTYPE (tree)));
2816       return tree;
2817
2818       /*------------------------------------------------------------------*/
2819       /*----------------------------*/
2820       /*      unary '-'             */
2821       /*----------------------------*/
2822     case '-':                   /* can be unary   */
2823       /* if right is null then unary */
2824       if (!tree->right)
2825         {
2826
2827           if (!IS_ARITHMETIC (LTYPE (tree)))
2828             {
2829               werror (E_UNARY_OP, tree->opval.op);
2830               goto errorTreeReturn;
2831             }
2832
2833           /* if left is a literal then do it */
2834           if (IS_LITERAL (LTYPE (tree)))
2835             {
2836               tree->type = EX_VALUE;
2837               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
2838               tree->left = NULL;
2839               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2840               SPEC_USIGN(TETYPE(tree)) = 0;
2841               return tree;
2842             }
2843           LRVAL (tree) = 1;
2844           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
2845           return tree;
2846         }
2847
2848       /*------------------------------------------------------------------*/
2849       /*----------------------------*/
2850       /*    subtraction             */
2851       /*----------------------------*/
2852
2853       if (!(IS_PTR (LTYPE (tree)) ||
2854             IS_ARRAY (LTYPE (tree)) ||
2855             IS_ARITHMETIC (LTYPE (tree))))
2856         {
2857           werror (E_PLUS_INVALID, "-");
2858           goto errorTreeReturn;
2859         }
2860
2861       if (!(IS_PTR (RTYPE (tree)) ||
2862             IS_ARRAY (RTYPE (tree)) ||
2863             IS_ARITHMETIC (RTYPE (tree))))
2864         {
2865           werror (E_PLUS_INVALID, "-");
2866           goto errorTreeReturn;
2867         }
2868
2869       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
2870           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
2871             IS_INTEGRAL (RTYPE (tree))))
2872         {
2873           werror (E_PLUS_INVALID, "-");
2874           goto errorTreeReturn;
2875         }
2876
2877       /* if they are both literal then */
2878       /* rewrite the tree */
2879       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2880         {
2881           tree->type = EX_VALUE;
2882           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
2883                                       valFromType (RETYPE (tree)));
2884           tree->right = tree->left = NULL;
2885           TETYPE (tree) = getSpec (TTYPE (tree) =
2886                                    tree->opval.val->type);
2887           return tree;
2888         }
2889
2890       /* if the left & right are equal then zero */
2891       if (isAstEqual (tree->left, tree->right))
2892         {
2893           tree->type = EX_VALUE;
2894           tree->left = tree->right = NULL;
2895           tree->opval.val = constVal ("0");
2896           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2897           return tree;
2898         }
2899
2900       /* if both of them are pointers or arrays then */
2901       /* the result is going to be an integer        */
2902       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
2903           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
2904         TETYPE (tree) = TTYPE (tree) = newIntLink ();
2905       else
2906         /* if only the left is a pointer */
2907         /* then result is a pointer      */
2908       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
2909         TETYPE (tree) = getSpec (TTYPE (tree) =
2910                                  LTYPE (tree));
2911       else
2912         TETYPE (tree) = getSpec (TTYPE (tree) =
2913                                  computeType (LTYPE (tree),
2914                                               RTYPE (tree)));
2915
2916       LRVAL (tree) = RRVAL (tree) = 1;
2917
2918       /* if right is a literal and */
2919       /* left is also an addition/subtraction with a literal then */
2920       /* rearrange the tree */
2921       if (IS_LITERAL (RTYPE (tree))
2922           /* avoid infinite loop */
2923           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
2924         {
2925           ast *litTree, *litParent;
2926           litTree = searchLitOp (tree, &litParent, "+-");
2927           if (litTree)
2928             {
2929               if (litTree->opval.op == '+')
2930                 {
2931                   /* foo_sa */
2932                   litTree->right = newNode ('-', litTree->right, tree->right);
2933                   litTree->right->lineno = tree->lineno;
2934
2935                   tree->right->opval.val = constVal ("0");
2936                 }
2937               else if (litTree->opval.op == '-')
2938                 {
2939                   if (IS_LITERAL (RTYPE (litTree)))
2940                     {
2941                       /* foo_ssr */
2942                       litTree->right = newNode ('+', tree->right, litTree->right);
2943                       litTree->right->lineno = tree->lineno;
2944
2945                       tree->right->opval.val = constVal ("0");
2946                     }
2947                   else
2948                     {
2949                       /* foo_ssl */
2950                       ast *tTree = litTree->right;
2951                       litTree->right = tree->right;
2952                       tree->right = tTree;
2953                     }
2954                 }
2955               decorateType (litParent);
2956             }
2957         }
2958       return tree;
2959
2960       /*------------------------------------------------------------------*/
2961       /*----------------------------*/
2962       /*    complement              */
2963       /*----------------------------*/
2964     case '~':
2965       /* can be only integral type */
2966       if (!IS_INTEGRAL (LTYPE (tree)))
2967         {
2968           werror (E_UNARY_OP, tree->opval.op);
2969           goto errorTreeReturn;
2970         }
2971
2972       /* if left is a literal then do it */
2973       if (IS_LITERAL (LTYPE (tree)))
2974         {
2975           tree->type = EX_VALUE;
2976           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
2977           tree->left = NULL;
2978           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2979           return tree;
2980         }
2981       LRVAL (tree) = 1;
2982       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
2983       return tree;
2984
2985       /*------------------------------------------------------------------*/
2986       /*----------------------------*/
2987       /*           not              */
2988       /*----------------------------*/
2989     case '!':
2990       /* can be pointer */
2991       if (!IS_ARITHMETIC (LTYPE (tree)) &&
2992           !IS_PTR (LTYPE (tree)) &&
2993           !IS_ARRAY (LTYPE (tree)))
2994         {
2995           werror (E_UNARY_OP, tree->opval.op);
2996           goto errorTreeReturn;
2997         }
2998
2999       /* if left is a literal then do it */
3000       if (IS_LITERAL (LTYPE (tree)))
3001         {
3002           tree->type = EX_VALUE;
3003           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3004           tree->left = NULL;
3005           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3006           return tree;
3007         }
3008       LRVAL (tree) = 1;
3009       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3010       return tree;
3011
3012       /*------------------------------------------------------------------*/
3013       /*----------------------------*/
3014       /*           shift            */
3015       /*----------------------------*/
3016     case RRC:
3017     case RLC:
3018     case SWAP:
3019       TTYPE (tree) = LTYPE (tree);
3020       TETYPE (tree) = LETYPE (tree);
3021       return tree;
3022
3023     case GETHBIT:
3024       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3025       return tree;
3026
3027     case LEFT_OP:
3028     case RIGHT_OP:
3029       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3030         {
3031           werror (E_SHIFT_OP_INVALID);
3032           werror (W_CONTINUE, "left & right types are ");
3033           printTypeChain (LTYPE (tree), stderr);
3034           fprintf (stderr, ",");
3035           printTypeChain (RTYPE (tree), stderr);
3036           fprintf (stderr, "\n");
3037           goto errorTreeReturn;
3038         }
3039
3040       /* if they are both literal then */
3041       /* rewrite the tree */
3042       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3043         {
3044           tree->type = EX_VALUE;
3045           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3046                                       valFromType (RETYPE (tree)),
3047                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3048           tree->right = tree->left = NULL;
3049           TETYPE (tree) = getSpec (TTYPE (tree) =
3050                                    tree->opval.val->type);
3051           return tree;
3052         }
3053
3054       /* if only the right side is a literal & we are
3055          shifting more than size of the left operand then zero */
3056       if (IS_LITERAL (RTYPE (tree)) &&
3057           ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
3058           (getSize (LTYPE (tree)) * 8))
3059         {
3060           if (tree->opval.op==LEFT_OP ||
3061               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) {
3062             lineno=tree->lineno;
3063             werror (W_SHIFT_CHANGED,
3064                     (tree->opval.op == LEFT_OP ? "left" : "right"));
3065             tree->type = EX_VALUE;
3066             tree->left = tree->right = NULL;
3067             tree->opval.val = constVal ("0");
3068             TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3069             return tree;
3070           }
3071         }
3072       LRVAL (tree) = RRVAL (tree) = 1;
3073       TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3074       if (IS_LITERAL (TTYPE (tree)))
3075         SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3076       return tree;
3077
3078       /*------------------------------------------------------------------*/
3079       /*----------------------------*/
3080       /*         casting            */
3081       /*----------------------------*/
3082     case CAST:                  /* change the type   */
3083       /* cannot cast to an aggregate type */
3084       if (IS_AGGREGATE (LTYPE (tree)))
3085         {
3086           werror (E_CAST_ILLEGAL);
3087           goto errorTreeReturn;
3088         }
3089
3090       /* make sure the type is complete and sane */
3091       checkTypeSanity(LETYPE(tree), "(cast)");
3092
3093 #if 0
3094       /* if the right is a literal replace the tree */
3095       if (IS_LITERAL (RETYPE (tree))) {
3096               if (!IS_PTR (LTYPE (tree))) {
3097                       tree->type = EX_VALUE;
3098                       tree->opval.val =
3099                               valCastLiteral (LTYPE (tree),
3100                                               floatFromVal (valFromType (RETYPE (tree))));
3101                       tree->left = NULL;
3102                       tree->right = NULL;
3103                       TTYPE (tree) = tree->opval.val->type;
3104                       tree->values.literalFromCast = 1;
3105               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3106                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3107                       sym_link *rest = LTYPE(tree)->next;
3108                       werror(W_LITERAL_GENERIC);
3109                       TTYPE(tree) = newLink(DECLARATOR);
3110                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3111                       TTYPE(tree)->next = rest;
3112                       tree->left->opval.lnk = TTYPE(tree);
3113                       LRVAL (tree) = 1;
3114               } else {
3115                       TTYPE (tree) = LTYPE (tree);
3116                       LRVAL (tree) = 1;
3117               }
3118       } else {
3119               TTYPE (tree) = LTYPE (tree);
3120               LRVAL (tree) = 1;
3121       }
3122 #else
3123 #if 0 // this is already checked, now this could be explicit
3124       /* if pointer to struct then check names */
3125       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3126           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3127           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3128         {
3129           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3130                  SPEC_STRUCT(LETYPE(tree))->tag);
3131         }
3132 #endif
3133       if (IS_ADDRESS_OF_OP(tree->right)
3134           && IS_AST_SYM_VALUE (tree->right->left)
3135           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3136
3137         tree->type = EX_VALUE;
3138         tree->opval.val =
3139           valCastLiteral (LTYPE (tree),
3140                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3141         TTYPE (tree) = tree->opval.val->type;
3142         TETYPE (tree) = getSpec (TTYPE (tree));
3143         tree->left = NULL;
3144         tree->right = NULL;
3145         tree->values.literalFromCast = 1;
3146         return tree;
3147       }
3148
3149       /* handle offsetof macro:            */
3150       /* #define offsetof(TYPE, MEMBER) \  */
3151       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3152       if (IS_ADDRESS_OF_OP(tree->right)
3153           && IS_AST_OP (tree->right->left)
3154           && tree->right->left->opval.op == PTR_OP
3155           && IS_AST_OP (tree->right->left->left)
3156           && tree->right->left->left->opval.op == CAST
3157           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3158
3159         symbol *element = getStructElement (
3160           SPEC_STRUCT (LETYPE(tree->right->left)),
3161           AST_SYMBOL(tree->right->left->right)
3162         );
3163
3164         if (element) {
3165           tree->type = EX_VALUE;
3166           tree->opval.val = valCastLiteral (
3167             LTYPE (tree),
3168             element->offset
3169             + floatFromVal (valFromType (RETYPE (tree->right->left->left)))
3170           );
3171
3172           TTYPE (tree) = tree->opval.val->type;
3173           TETYPE (tree) = getSpec (TTYPE (tree));
3174           tree->left = NULL;
3175           tree->right = NULL;
3176           return tree;
3177         }
3178       }
3179
3180       /* if the right is a literal replace the tree */
3181       if (IS_LITERAL (RETYPE (tree))) {
3182         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3183           /* rewrite      (type *)litaddr
3184              as           &temp
3185              and define   type at litaddr temp
3186              (but only if type's storage class is not generic)
3187           */
3188           ast *newTree = newNode ('&', NULL, NULL);
3189           symbol *sym;
3190
3191           TTYPE (newTree) = LTYPE (tree);
3192           TETYPE (newTree) = getSpec(LTYPE (tree));
3193
3194           /* define a global symbol at the casted address*/
3195           sym = newSymbol(genSymName (0), 0);
3196           sym->type = LTYPE (tree)->next;
3197           if (!sym->type)
3198             sym->type = newLink (V_VOID);
3199           sym->etype = getSpec(sym->type);
3200           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3201           sym->lineDef = tree->lineno;
3202           sym->cdef = 1;
3203           sym->isref = 1;
3204           SPEC_STAT (sym->etype) = 1;
3205           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RETYPE (tree)));
3206           SPEC_ABSA(sym->etype) = 1;
3207           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3208           allocGlobal (sym);
3209
3210           newTree->left = newAst_VALUE(symbolVal(sym));
3211           newTree->left->lineno = tree->lineno;
3212           LTYPE (newTree) = sym->type;
3213           LETYPE (newTree) = sym->etype;
3214           LLVAL (newTree) = 1;
3215           LRVAL (newTree) = 0;
3216           TLVAL (newTree) = 1;
3217           return newTree;
3218         }
3219         if (!IS_PTR (LTYPE (tree))) {
3220           tree->type = EX_VALUE;
3221           tree->opval.val =
3222           valCastLiteral (LTYPE (tree),
3223                           floatFromVal (valFromType (RETYPE (tree))));
3224           TTYPE (tree) = tree->opval.val->type;
3225           tree->left = NULL;
3226           tree->right = NULL;
3227           tree->values.literalFromCast = 1;
3228           TETYPE (tree) = getSpec (TTYPE (tree));
3229           return tree;
3230         }
3231       }
3232       TTYPE (tree) = LTYPE (tree);
3233       LRVAL (tree) = 1;
3234
3235 #endif
3236       TETYPE (tree) = getSpec (TTYPE (tree));
3237
3238       return tree;
3239
3240       /*------------------------------------------------------------------*/
3241       /*----------------------------*/
3242       /*       logical &&, ||       */
3243       /*----------------------------*/
3244     case AND_OP:
3245     case OR_OP:
3246       /* each must me arithmetic type or be a pointer */
3247       if (!IS_PTR (LTYPE (tree)) &&
3248           !IS_ARRAY (LTYPE (tree)) &&
3249           !IS_INTEGRAL (LTYPE (tree)))
3250         {
3251           werror (E_COMPARE_OP);
3252           goto errorTreeReturn;
3253         }
3254
3255       if (!IS_PTR (RTYPE (tree)) &&
3256           !IS_ARRAY (RTYPE (tree)) &&
3257           !IS_INTEGRAL (RTYPE (tree)))
3258         {
3259           werror (E_COMPARE_OP);
3260           goto errorTreeReturn;
3261         }
3262       /* if they are both literal then */
3263       /* rewrite the tree */
3264       if (IS_LITERAL (RTYPE (tree)) &&
3265           IS_LITERAL (LTYPE (tree)))
3266         {
3267           tree->type = EX_VALUE;
3268           tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)),
3269                                            valFromType (RETYPE (tree)),
3270                                            tree->opval.op);
3271           tree->right = tree->left = NULL;
3272           TETYPE (tree) = getSpec (TTYPE (tree) =
3273                                    tree->opval.val->type);
3274           return tree;
3275         }
3276       LRVAL (tree) = RRVAL (tree) = 1;
3277       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3278       return tree;
3279
3280       /*------------------------------------------------------------------*/
3281       /*----------------------------*/
3282       /*     comparison operators   */
3283       /*----------------------------*/
3284     case '>':
3285     case '<':
3286     case LE_OP:
3287     case GE_OP:
3288     case EQ_OP:
3289     case NE_OP:
3290       {
3291         ast *lt = optimizeCompare (tree);
3292
3293         if (tree != lt)
3294           return lt;
3295       }
3296
3297       /* if they are pointers they must be castable */
3298       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3299         {
3300           if (tree->opval.op==EQ_OP &&
3301               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3302             // we cannot cast a gptr to a !gptr: switch the leaves
3303             struct ast *s=tree->left;
3304             tree->left=tree->right;
3305             tree->right=s;
3306           }
3307           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3308             {
3309               werror (E_COMPARE_OP);
3310               fprintf (stderr, "comparring type ");
3311               printTypeChain (LTYPE (tree), stderr);
3312               fprintf (stderr, "to type ");
3313               printTypeChain (RTYPE (tree), stderr);
3314               fprintf (stderr, "\n");
3315               goto errorTreeReturn;
3316             }
3317         }
3318       /* else they should be promotable to one another */
3319       else
3320         {
3321           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3322                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3323
3324             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3325               {
3326                 werror (E_COMPARE_OP);
3327                 fprintf (stderr, "comparing type ");
3328                 printTypeChain (LTYPE (tree), stderr);
3329                 fprintf (stderr, "to type ");
3330                 printTypeChain (RTYPE (tree), stderr);
3331                 fprintf (stderr, "\n");
3332                 goto errorTreeReturn;
3333               }
3334         }
3335       /* if unsigned value < 0  then always false */
3336       /* if (unsigned value) > 0 then (unsigned value) */
3337       if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree))  && 
3338           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) {
3339
3340           if (tree->opval.op == '<') {
3341               return tree->right;
3342           }
3343           if (tree->opval.op == '>') {
3344               return tree->left;
3345           }
3346       }
3347       /* if they are both literal then */
3348       /* rewrite the tree */
3349       if (IS_LITERAL (RTYPE (tree)) &&
3350           IS_LITERAL (LTYPE (tree)))
3351         {
3352           tree->type = EX_VALUE;
3353           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3354                                         valFromType (RETYPE (tree)),
3355                                         tree->opval.op);
3356           tree->right = tree->left = NULL;
3357           TETYPE (tree) = getSpec (TTYPE (tree) =
3358                                    tree->opval.val->type);
3359           return tree;
3360         }
3361       LRVAL (tree) = RRVAL (tree) = 1;
3362       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3363       return tree;
3364
3365       /*------------------------------------------------------------------*/
3366       /*----------------------------*/
3367       /*             sizeof         */
3368       /*----------------------------*/
3369     case SIZEOF:                /* evaluate wihout code generation */
3370       /* change the type to a integer */
3371       tree->type = EX_VALUE;
3372       SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
3373       tree->opval.val = constVal (buffer);
3374       tree->right = tree->left = NULL;
3375       TETYPE (tree) = getSpec (TTYPE (tree) =
3376                                tree->opval.val->type);
3377       return tree;
3378
3379       /*------------------------------------------------------------------*/
3380       /*----------------------------*/
3381       /*             typeof         */
3382       /*----------------------------*/
3383     case TYPEOF:
3384         /* return typeof enum value */
3385         tree->type = EX_VALUE;
3386         {
3387             int typeofv = 0;
3388             if (IS_SPEC(tree->right->ftype)) {
3389                 switch (SPEC_NOUN(tree->right->ftype)) {
3390                 case V_INT:
3391                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3392                     else typeofv = TYPEOF_INT;
3393                     break;
3394                 case V_FLOAT:
3395                     typeofv = TYPEOF_FLOAT;
3396                     break;
3397                 case V_CHAR:
3398                     typeofv = TYPEOF_CHAR;
3399                     break;
3400                 case V_VOID:
3401                     typeofv = TYPEOF_VOID;
3402                     break;
3403                 case V_STRUCT:
3404                     typeofv = TYPEOF_STRUCT;
3405                     break;
3406                 case V_BITFIELD:
3407                     typeofv = TYPEOF_BITFIELD;
3408                     break;
3409                 case V_BIT:
3410                     typeofv = TYPEOF_BIT;
3411                     break;
3412                 case V_SBIT:
3413                     typeofv = TYPEOF_SBIT;
3414                     break;
3415                 default:
3416                     break;
3417                 }
3418             } else {
3419                 switch (DCL_TYPE(tree->right->ftype)) {
3420                 case POINTER:
3421                     typeofv = TYPEOF_POINTER;
3422                     break;
3423                 case FPOINTER:
3424                     typeofv = TYPEOF_FPOINTER;
3425                     break;
3426                 case CPOINTER:
3427                     typeofv = TYPEOF_CPOINTER;
3428                     break;
3429                 case GPOINTER:
3430                     typeofv = TYPEOF_GPOINTER;
3431                     break;
3432                 case PPOINTER:
3433                     typeofv = TYPEOF_PPOINTER;
3434                     break;
3435                 case IPOINTER:
3436                     typeofv = TYPEOF_IPOINTER;
3437                     break;
3438                 case ARRAY:
3439                     typeofv = TYPEOF_ARRAY;
3440                     break;
3441                 case FUNCTION:
3442                     typeofv = TYPEOF_FUNCTION;
3443                     break;
3444                 default:
3445                     break;
3446                 }
3447             }
3448             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3449             tree->opval.val = constVal (buffer);
3450             tree->right = tree->left = NULL;
3451             TETYPE (tree) = getSpec (TTYPE (tree) =
3452                                      tree->opval.val->type);
3453         }
3454         return tree;
3455       /*------------------------------------------------------------------*/
3456       /*----------------------------*/
3457       /* conditional operator  '?'  */
3458       /*----------------------------*/
3459     case '?':
3460       /* the type is value of the colon operator (on the right) */
3461       assert(IS_COLON_OP(tree->right));
3462       /* if already known then replace the tree : optimizer will do it
3463          but faster to do it here */
3464       if (IS_LITERAL (LTYPE(tree))) {     
3465           if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) {
3466               return decorateType(tree->right->left) ;
3467           } else {
3468               return decorateType(tree->right->right) ;
3469           }
3470       } else {
3471           tree->right = decorateType(tree->right);
3472           TTYPE (tree) = RTYPE(tree);
3473           TETYPE (tree) = getSpec (TTYPE (tree));
3474       }
3475       return tree;
3476
3477     case ':':
3478       /* if they don't match we have a problem */
3479       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3480         {
3481           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3482           goto errorTreeReturn;
3483         }
3484
3485       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree));
3486       TETYPE (tree) = getSpec (TTYPE (tree));
3487       return tree;
3488
3489
3490 #if 0 // assignment operators are converted by the parser
3491       /*------------------------------------------------------------------*/
3492       /*----------------------------*/
3493       /*    assignment operators    */
3494       /*----------------------------*/
3495     case MUL_ASSIGN:
3496     case DIV_ASSIGN:
3497       /* for these it must be both must be integral */
3498       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3499           !IS_ARITHMETIC (RTYPE (tree)))
3500         {
3501           werror (E_OPS_INTEGRAL);
3502           goto errorTreeReturn;
3503         }
3504       RRVAL (tree) = 1;
3505       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3506
3507       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3508         werror (E_CODE_WRITE, *tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3509
3510       if (LRVAL (tree))
3511         {
3512           werror (E_LVALUE_REQUIRED, *tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3513           goto errorTreeReturn;
3514         }
3515       LLVAL (tree) = 1;
3516
3517       return tree;
3518
3519     case AND_ASSIGN:
3520     case OR_ASSIGN:
3521     case XOR_ASSIGN:
3522     case RIGHT_ASSIGN:
3523     case LEFT_ASSIGN:
3524       /* for these it must be both must be integral */
3525       if (!IS_INTEGRAL (LTYPE (tree)) ||
3526           !IS_INTEGRAL (RTYPE (tree)))
3527         {
3528           werror (E_OPS_INTEGRAL);
3529           goto errorTreeReturn;
3530         }
3531       RRVAL (tree) = 1;
3532       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3533
3534       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3535         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3536
3537       if (LRVAL (tree))
3538         {
3539           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3540           goto errorTreeReturn;
3541         }
3542       LLVAL (tree) = 1;
3543
3544       return tree;
3545
3546       /*------------------------------------------------------------------*/
3547       /*----------------------------*/
3548       /*    -= operator             */
3549       /*----------------------------*/
3550     case SUB_ASSIGN:
3551       if (!(IS_PTR (LTYPE (tree)) ||
3552             IS_ARITHMETIC (LTYPE (tree))))
3553         {
3554           werror (E_PLUS_INVALID, "-=");
3555           goto errorTreeReturn;
3556         }
3557
3558       if (!(IS_PTR (RTYPE (tree)) ||
3559             IS_ARITHMETIC (RTYPE (tree))))
3560         {
3561           werror (E_PLUS_INVALID, "-=");
3562           goto errorTreeReturn;
3563         }
3564       RRVAL (tree) = 1;
3565       TETYPE (tree) = getSpec (TTYPE (tree) =
3566                                computeType (LTYPE (tree),
3567                                             RTYPE (tree)));
3568
3569       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3570         werror (E_CODE_WRITE, "-=");
3571
3572       if (LRVAL (tree))
3573         {
3574           werror (E_LVALUE_REQUIRED, "-=");
3575           goto errorTreeReturn;
3576         }
3577       LLVAL (tree) = 1;
3578
3579       return tree;
3580
3581       /*------------------------------------------------------------------*/
3582       /*----------------------------*/
3583       /*          += operator       */
3584       /*----------------------------*/
3585     case ADD_ASSIGN:
3586       /* this is not a unary operation */
3587       /* if both pointers then problem */
3588       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3589         {
3590           werror (E_PTR_PLUS_PTR);
3591           goto errorTreeReturn;
3592         }
3593
3594       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
3595         {
3596           werror (E_PLUS_INVALID, "+=");
3597           goto errorTreeReturn;
3598         }
3599
3600       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
3601         {
3602           werror (E_PLUS_INVALID, "+=");
3603           goto errorTreeReturn;
3604         }
3605       RRVAL (tree) = 1;
3606       TETYPE (tree) = getSpec (TTYPE (tree) =
3607                                computeType (LTYPE (tree),
3608                                             RTYPE (tree)));
3609
3610       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3611         werror (E_CODE_WRITE, "+=");
3612
3613       if (LRVAL (tree))
3614         {
3615           werror (E_LVALUE_REQUIRED, "+=");
3616           goto errorTreeReturn;
3617         }
3618
3619       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
3620       tree->opval.op = '=';
3621
3622       return tree;
3623 #endif
3624
3625       /*------------------------------------------------------------------*/
3626       /*----------------------------*/
3627       /*      straight assignemnt   */
3628       /*----------------------------*/
3629     case '=':
3630       /* cannot be an aggregate */
3631       if (IS_AGGREGATE (LTYPE (tree)))
3632         {
3633           werror (E_AGGR_ASSIGN);
3634           goto errorTreeReturn;
3635         }
3636
3637       /* they should either match or be castable */
3638       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3639         {
3640           werror (E_TYPE_MISMATCH, "assignment", " ");
3641           printFromToType(RTYPE(tree),LTYPE(tree));
3642         }
3643
3644       /* if the left side of the tree is of type void
3645          then report error */
3646       if (IS_VOID (LTYPE (tree)))
3647         {
3648           werror (E_CAST_ZERO);
3649           printFromToType(RTYPE(tree), LTYPE(tree));
3650         }
3651
3652       TETYPE (tree) = getSpec (TTYPE (tree) =
3653                                LTYPE (tree));
3654       RRVAL (tree) = 1;
3655       LLVAL (tree) = 1;
3656       if (!tree->initMode ) {
3657         if (IS_CONSTANT(LTYPE(tree)))
3658           werror (E_CODE_WRITE, "=");
3659       }
3660       if (LRVAL (tree))
3661         {
3662           werror (E_LVALUE_REQUIRED, "=");
3663           goto errorTreeReturn;
3664         }
3665
3666       return tree;
3667
3668       /*------------------------------------------------------------------*/
3669       /*----------------------------*/
3670       /*      comma operator        */
3671       /*----------------------------*/
3672     case ',':
3673       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
3674       return tree;
3675
3676       /*------------------------------------------------------------------*/
3677       /*----------------------------*/
3678       /*       function call        */
3679       /*----------------------------*/
3680     case CALL:
3681       parmNumber = 1;
3682
3683       if (processParms (tree->left,
3684                         FUNC_ARGS(tree->left->ftype),
3685                         tree->right, &parmNumber, TRUE)) {
3686         goto errorTreeReturn;
3687       }
3688
3689       if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && 
3690           !IFFUNC_ISBUILTIN(LTYPE(tree)))
3691         {
3692           reverseParms (tree->right);
3693         }
3694
3695       if (IS_CODEPTR(LTYPE(tree))) {
3696         TTYPE(tree) = LTYPE(tree)->next->next;
3697       } else {
3698         TTYPE(tree) = LTYPE(tree)->next;
3699       }
3700       TETYPE (tree) = getSpec (TTYPE (tree));
3701       return tree;
3702
3703       /*------------------------------------------------------------------*/
3704       /*----------------------------*/
3705       /*     return statement       */
3706       /*----------------------------*/
3707     case RETURN:
3708       if (!tree->right)
3709         goto voidcheck;
3710
3711       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
3712         {
3713           werror (W_RETURN_MISMATCH);
3714           printFromToType (RTYPE(tree), currFunc->type->next);
3715           goto errorTreeReturn;
3716         }
3717
3718       if (IS_VOID (currFunc->type->next)
3719           && tree->right &&
3720           !IS_VOID (RTYPE (tree)))
3721         {
3722           werror (E_FUNC_VOID);
3723           goto errorTreeReturn;
3724         }
3725
3726       /* if there is going to be a casing required then add it */
3727       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
3728         {
3729           tree->right =
3730             decorateType (newNode (CAST,
3731                            newAst_LINK (copyLinkChain (currFunc->type->next)),
3732                                    tree->right));
3733         }
3734
3735       RRVAL (tree) = 1;
3736       return tree;
3737
3738     voidcheck:
3739
3740       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
3741         {
3742           werror (W_VOID_FUNC, currFunc->name);
3743           goto errorTreeReturn;
3744         }
3745
3746       TTYPE (tree) = TETYPE (tree) = NULL;
3747       return tree;
3748
3749       /*------------------------------------------------------------------*/
3750       /*----------------------------*/
3751       /*     switch statement       */
3752       /*----------------------------*/
3753     case SWITCH:
3754       /* the switch value must be an integer */
3755       if (!IS_INTEGRAL (LTYPE (tree)))
3756         {
3757           werror (E_SWITCH_NON_INTEGER);
3758           goto errorTreeReturn;
3759         }
3760       LRVAL (tree) = 1;
3761       TTYPE (tree) = TETYPE (tree) = NULL;
3762       return tree;
3763
3764       /*------------------------------------------------------------------*/
3765       /*----------------------------*/
3766       /* ifx Statement              */
3767       /*----------------------------*/
3768     case IFX:
3769       tree->left = backPatchLabels (tree->left,
3770                                     tree->trueLabel,
3771                                     tree->falseLabel);
3772       TTYPE (tree) = TETYPE (tree) = NULL;
3773       return tree;
3774
3775       /*------------------------------------------------------------------*/
3776       /*----------------------------*/
3777       /* for Statement              */
3778       /*----------------------------*/
3779     case FOR:
3780
3781       decorateType (resolveSymbols (AST_FOR (tree, initExpr)));
3782       decorateType (resolveSymbols (AST_FOR (tree, condExpr)));
3783       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)));
3784
3785       /* if the for loop is reversible then
3786          reverse it otherwise do what we normally
3787          do */
3788       {
3789         symbol *sym;
3790         ast *init, *end;
3791
3792         if (isLoopReversible (tree, &sym, &init, &end))
3793           return reverseLoop (tree, sym, init, end);
3794         else
3795           return decorateType (createFor (AST_FOR (tree, trueLabel),
3796                                           AST_FOR (tree, continueLabel),
3797                                           AST_FOR (tree, falseLabel),
3798                                           AST_FOR (tree, condLabel),
3799                                           AST_FOR (tree, initExpr),
3800                                           AST_FOR (tree, condExpr),
3801                                           AST_FOR (tree, loopExpr),
3802                                           tree->left));
3803       }
3804     default:
3805       TTYPE (tree) = TETYPE (tree) = NULL;
3806       return tree;
3807     }
3808
3809   /* some error found this tree will be killed */
3810 errorTreeReturn:
3811   TTYPE (tree) = TETYPE (tree) = newCharLink ();
3812   tree->opval.op = NULLOP;
3813   tree->isError = 1;
3814
3815   return tree;
3816 }
3817
3818 /*-----------------------------------------------------------------*/
3819 /* sizeofOp - processes size of operation                          */
3820 /*-----------------------------------------------------------------*/
3821 value *
3822 sizeofOp (sym_link * type)
3823 {
3824   char buff[10];
3825
3826   /* make sure the type is complete and sane */
3827   checkTypeSanity(type, "(sizeof)");
3828
3829   /* get the size and convert it to character  */
3830   SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
3831
3832   /* now convert into value  */
3833   return constVal (buff);
3834 }
3835
3836
3837 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
3838 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
3839 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
3840 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
3841 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
3842 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
3843 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
3844
3845 /*-----------------------------------------------------------------*/
3846 /* backPatchLabels - change and or not operators to flow control    */
3847 /*-----------------------------------------------------------------*/
3848 ast *
3849 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
3850 {
3851
3852   if (!tree)
3853     return NULL;
3854
3855   if (!(IS_ANDORNOT (tree)))
3856     return tree;
3857
3858   /* if this an and */
3859   if (IS_AND (tree))
3860     {
3861       static int localLbl = 0;
3862       symbol *localLabel;
3863
3864       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
3865       localLabel = newSymbol (buffer, NestLevel);
3866
3867       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
3868
3869       /* if left is already a IFX then just change the if true label in that */
3870       if (!IS_IFX (tree->left))
3871         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
3872
3873       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
3874       /* right is a IFX then just join */
3875       if (IS_IFX (tree->right))
3876         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
3877
3878       tree->right = createLabel (localLabel, tree->right);
3879       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
3880
3881       return newNode (NULLOP, tree->left, tree->right);
3882     }
3883
3884   /* if this is an or operation */
3885   if (IS_OR (tree))
3886     {
3887       static int localLbl = 0;
3888       symbol *localLabel;
3889
3890       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
3891       localLabel = newSymbol (buffer, NestLevel);
3892
3893       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
3894
3895       /* if left is already a IFX then just change the if true label in that */
3896       if (!IS_IFX (tree->left))
3897         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
3898
3899       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
3900       /* right is a IFX then just join */
3901       if (IS_IFX (tree->right))
3902         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
3903
3904       tree->right = createLabel (localLabel, tree->right);
3905       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
3906
3907       return newNode (NULLOP, tree->left, tree->right);
3908     }
3909
3910   /* change not */
3911   if (IS_NOT (tree))
3912     {
3913       int wasnot = IS_NOT (tree->left);
3914       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
3915
3916       /* if the left is already a IFX */
3917       if (!IS_IFX (tree->left))
3918         tree->left = newNode (IFX, tree->left, NULL);
3919
3920       if (wasnot)
3921         {
3922           tree->left->trueLabel = trueLabel;
3923           tree->left->falseLabel = falseLabel;
3924         }
3925       else
3926         {
3927           tree->left->trueLabel = falseLabel;
3928           tree->left->falseLabel = trueLabel;
3929         }
3930       return tree->left;
3931     }
3932
3933   if (IS_IFX (tree))
3934     {
3935       tree->trueLabel = trueLabel;
3936       tree->falseLabel = falseLabel;
3937     }
3938
3939   return tree;
3940 }
3941
3942
3943 /*-----------------------------------------------------------------*/
3944 /* createBlock - create expression tree for block                  */
3945 /*-----------------------------------------------------------------*/
3946 ast *
3947 createBlock (symbol * decl, ast * body)
3948 {
3949   ast *ex;
3950
3951   /* if the block has nothing */
3952   if (!body && !decl)
3953     return NULL;
3954
3955   ex = newNode (BLOCK, NULL, body);
3956   ex->values.sym = decl;
3957   
3958   ex->right = ex->right;
3959   ex->level++;
3960   ex->lineno = 0;
3961   return ex;
3962 }
3963
3964 /*-----------------------------------------------------------------*/
3965 /* createLabel - creates the expression tree for labels            */
3966 /*-----------------------------------------------------------------*/
3967 ast *
3968 createLabel (symbol * label, ast * stmnt)
3969 {
3970   symbol *csym;
3971   char name[SDCC_NAME_MAX + 1];
3972   ast *rValue;
3973
3974   /* must create fresh symbol if the symbol name  */
3975   /* exists in the symbol table, since there can  */
3976   /* be a variable with the same name as the labl */
3977   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
3978       (csym->level == label->level))
3979     label = newSymbol (label->name, label->level);
3980
3981   /* change the name before putting it in add _ */
3982   SNPRINTF(name, sizeof(name), "%s", label->name);
3983
3984   /* put the label in the LabelSymbol table    */
3985   /* but first check if a label of the same    */
3986   /* name exists                               */
3987   if ((csym = findSym (LabelTab, NULL, name)))
3988     werror (E_DUPLICATE_LABEL, label->name);
3989   else
3990     addSym (LabelTab, label, name, label->level, 0, 0);
3991
3992   label->islbl = 1;
3993   label->key = labelKey++;
3994   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
3995   rValue->lineno = 0;
3996
3997   return rValue;
3998 }
3999
4000 /*-----------------------------------------------------------------*/
4001 /* createCase - generates the parsetree for a case statement       */
4002 /*-----------------------------------------------------------------*/
4003 ast *
4004 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4005 {
4006   char caseLbl[SDCC_NAME_MAX + 1];
4007   ast *rexpr;
4008   value *val;
4009
4010   /* if the switch statement does not exist */
4011   /* then case is out of context            */
4012   if (!swStat)
4013     {
4014       werror (E_CASE_CONTEXT);
4015       return NULL;
4016     }
4017
4018   caseVal = decorateType (resolveSymbols (caseVal));
4019   /* if not a constant then error  */
4020   if (!IS_LITERAL (caseVal->ftype))
4021     {
4022       werror (E_CASE_CONSTANT);
4023       return NULL;
4024     }
4025
4026   /* if not a integer than error */
4027   if (!IS_INTEGRAL (caseVal->ftype))
4028     {
4029       werror (E_CASE_NON_INTEGER);
4030       return NULL;
4031     }
4032
4033   /* find the end of the switch values chain   */
4034   if (!(val = swStat->values.switchVals.swVals))
4035     swStat->values.switchVals.swVals = caseVal->opval.val;
4036   else
4037     {
4038       /* also order the cases according to value */
4039       value *pval = NULL;
4040       int cVal = (int) floatFromVal (caseVal->opval.val);
4041       while (val && (int) floatFromVal (val) < cVal)
4042         {
4043           pval = val;
4044           val = val->next;
4045         }
4046
4047       /* if we reached the end then */
4048       if (!val)
4049         {
4050           pval->next = caseVal->opval.val;
4051         }
4052       else
4053         {
4054           /* we found a value greater than */
4055           /* the current value we must add this */
4056           /* before the value */
4057           caseVal->opval.val->next = val;
4058
4059           /* if this was the first in chain */
4060           if (swStat->values.switchVals.swVals == val)
4061             swStat->values.switchVals.swVals =
4062               caseVal->opval.val;
4063           else
4064             pval->next = caseVal->opval.val;
4065         }
4066
4067     }
4068
4069   /* create the case label   */
4070   SNPRINTF(caseLbl, sizeof(caseLbl), 
4071            "_case_%d_%d",
4072            swStat->values.switchVals.swNum,
4073            (int) floatFromVal (caseVal->opval.val));
4074
4075   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4076   rexpr->lineno = 0;
4077   return rexpr;
4078 }
4079
4080 /*-----------------------------------------------------------------*/
4081 /* createDefault - creates the parse tree for the default statement */
4082 /*-----------------------------------------------------------------*/
4083 ast *
4084 createDefault (ast * swStat, ast * stmnt)
4085 {
4086   char defLbl[SDCC_NAME_MAX + 1];
4087
4088   /* if the switch statement does not exist */
4089   /* then case is out of context            */
4090   if (!swStat)
4091     {
4092       werror (E_CASE_CONTEXT);
4093       return NULL;
4094     }
4095
4096   /* turn on the default flag   */
4097   swStat->values.switchVals.swDefault = 1;
4098
4099   /* create the label  */
4100   SNPRINTF (defLbl, sizeof(defLbl),
4101             "_default_%d", swStat->values.switchVals.swNum);
4102   return createLabel (newSymbol (defLbl, 0), stmnt);
4103 }
4104
4105 /*-----------------------------------------------------------------*/
4106 /* createIf - creates the parsetree for the if statement           */
4107 /*-----------------------------------------------------------------*/
4108 ast *
4109 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4110 {
4111   static int Lblnum = 0;
4112   ast *ifTree;
4113   symbol *ifTrue, *ifFalse, *ifEnd;
4114
4115   /* if neither exists */
4116   if (!elseBody && !ifBody) {
4117     // if there are no side effects (i++, j() etc)
4118     if (!hasSEFcalls(condAst)) {
4119       return condAst;
4120     }
4121   }
4122
4123   /* create the labels */
4124   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4125   ifFalse = newSymbol (buffer, NestLevel);
4126   /* if no else body then end == false */
4127   if (!elseBody)
4128     ifEnd = ifFalse;
4129   else
4130     {
4131       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4132       ifEnd = newSymbol (buffer, NestLevel);
4133     }
4134
4135   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4136   ifTrue = newSymbol (buffer, NestLevel);
4137
4138   Lblnum++;
4139
4140   /* attach the ifTrue label to the top of it body */
4141   ifBody = createLabel (ifTrue, ifBody);
4142   /* attach a goto end to the ifBody if else is present */
4143   if (elseBody)
4144     {
4145       ifBody = newNode (NULLOP, ifBody,
4146                         newNode (GOTO,
4147                                  newAst_VALUE (symbolVal (ifEnd)),
4148                                  NULL));
4149       /* put the elseLabel on the else body */
4150       elseBody = createLabel (ifFalse, elseBody);
4151       /* out the end at the end of the body */
4152       elseBody = newNode (NULLOP,
4153                           elseBody,
4154                           createLabel (ifEnd, NULL));
4155     }
4156   else
4157     {
4158       ifBody = newNode (NULLOP, ifBody,
4159                         createLabel (ifFalse, NULL));
4160     }
4161   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4162   if (IS_IFX (condAst))
4163     ifTree = condAst;
4164   else
4165     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4166
4167   return newNode (NULLOP, ifTree,
4168                   newNode (NULLOP, ifBody, elseBody));
4169
4170 }
4171
4172 /*-----------------------------------------------------------------*/
4173 /* createDo - creates parse tree for do                            */
4174 /*        _dobody_n:                                               */
4175 /*            statements                                           */
4176 /*        _docontinue_n:                                           */
4177 /*            condition_expression +-> trueLabel -> _dobody_n      */
4178 /*                                 |                               */
4179 /*                                 +-> falseLabel-> _dobreak_n     */
4180 /*        _dobreak_n:                                              */
4181 /*-----------------------------------------------------------------*/
4182 ast *
4183 createDo (symbol * trueLabel, symbol * continueLabel,
4184           symbol * falseLabel, ast * condAst, ast * doBody)
4185 {
4186   ast *doTree;
4187
4188
4189   /* if the body does not exist then it is simple */
4190   if (!doBody)
4191     {
4192       condAst = backPatchLabels (condAst, continueLabel, NULL);
4193       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4194                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4195       doTree->trueLabel = continueLabel;
4196       doTree->falseLabel = NULL;
4197       return doTree;
4198     }
4199
4200   /* otherwise we have a body */
4201   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4202
4203   /* attach the body label to the top */
4204   doBody = createLabel (trueLabel, doBody);
4205   /* attach the continue label to end of body */
4206   doBody = newNode (NULLOP, doBody,
4207                     createLabel (continueLabel, NULL));
4208
4209   /* now put the break label at the end */
4210   if (IS_IFX (condAst))
4211     doTree = condAst;
4212   else
4213     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4214
4215   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4216
4217   /* putting it together */
4218   return newNode (NULLOP, doBody, doTree);
4219 }
4220
4221 /*-----------------------------------------------------------------*/
4222 /* createFor - creates parse tree for 'for' statement              */
4223 /*        initExpr                                                 */
4224 /*   _forcond_n:                                                   */
4225 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4226 /*                  |                                              */
4227 /*                  +-> falseLabel-> _forbreak_n                   */
4228 /*   _forbody_n:                                                   */
4229 /*        statements                                               */
4230 /*   _forcontinue_n:                                               */
4231 /*        loopExpr                                                 */
4232 /*        goto _forcond_n ;                                        */
4233 /*   _forbreak_n:                                                  */
4234 /*-----------------------------------------------------------------*/
4235 ast *
4236 createFor (symbol * trueLabel, symbol * continueLabel,
4237            symbol * falseLabel, symbol * condLabel,
4238            ast * initExpr, ast * condExpr, ast * loopExpr,
4239            ast * forBody)
4240 {
4241   ast *forTree;
4242
4243   /* if loopexpression not present then we can generate it */
4244   /* the same way as a while */
4245   if (!loopExpr)
4246     return newNode (NULLOP, initExpr,
4247                     createWhile (trueLabel, continueLabel,
4248                                  falseLabel, condExpr, forBody));
4249   /* vanilla for statement */
4250   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4251
4252   if (condExpr && !IS_IFX (condExpr))
4253     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4254
4255
4256   /* attach condition label to condition */
4257   condExpr = createLabel (condLabel, condExpr);
4258
4259   /* attach body label to body */
4260   forBody = createLabel (trueLabel, forBody);
4261
4262   /* attach continue to forLoop expression & attach */
4263   /* goto the forcond @ and of loopExpression       */
4264   loopExpr = createLabel (continueLabel,
4265                           newNode (NULLOP,
4266                                    loopExpr,
4267                                    newNode (GOTO,
4268                                        newAst_VALUE (symbolVal (condLabel)),
4269                                             NULL)));
4270   /* now start putting them together */
4271   forTree = newNode (NULLOP, initExpr, condExpr);
4272   forTree = newNode (NULLOP, forTree, forBody);
4273   forTree = newNode (NULLOP, forTree, loopExpr);
4274   /* finally add the break label */
4275   forTree = newNode (NULLOP, forTree,
4276                      createLabel (falseLabel, NULL));
4277   return forTree;
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* createWhile - creates parse tree for while statement            */
4282 /*               the while statement will be created as follows    */
4283 /*                                                                 */
4284 /*      _while_continue_n:                                         */
4285 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4286 /*                                 |                               */
4287 /*                                 +-> falseLabel -> _while_break_n */
4288 /*      _while_body_n:                                             */
4289 /*            statements                                           */
4290 /*            goto _while_continue_n                               */
4291 /*      _while_break_n:                                            */
4292 /*-----------------------------------------------------------------*/
4293 ast *
4294 createWhile (symbol * trueLabel, symbol * continueLabel,
4295              symbol * falseLabel, ast * condExpr, ast * whileBody)
4296 {
4297   ast *whileTree;
4298
4299   /* put the continue label */
4300   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4301   condExpr = createLabel (continueLabel, condExpr);
4302   condExpr->lineno = 0;
4303
4304   /* put the body label in front of the body */
4305   whileBody = createLabel (trueLabel, whileBody);
4306   whileBody->lineno = 0;
4307   /* put a jump to continue at the end of the body */
4308   /* and put break label at the end of the body */
4309   whileBody = newNode (NULLOP,
4310                        whileBody,
4311                        newNode (GOTO,
4312                                 newAst_VALUE (symbolVal (continueLabel)),
4313                                 createLabel (falseLabel, NULL)));
4314
4315   /* put it all together */
4316   if (IS_IFX (condExpr))
4317     whileTree = condExpr;
4318   else
4319     {
4320       whileTree = newNode (IFX, condExpr, NULL);
4321       /* put the true & false labels in place */
4322       whileTree->trueLabel = trueLabel;
4323       whileTree->falseLabel = falseLabel;
4324     }
4325
4326   return newNode (NULLOP, whileTree, whileBody);
4327 }
4328
4329 /*-----------------------------------------------------------------*/
4330 /* optimizeGetHbit - get highest order bit of the expression       */
4331 /*-----------------------------------------------------------------*/
4332 ast *
4333 optimizeGetHbit (ast * tree)
4334 {
4335   int i, j;
4336   /* if this is not a bit and */
4337   if (!IS_BITAND (tree))
4338     return tree;
4339
4340   /* will look for tree of the form
4341      ( expr >> ((sizeof expr) -1) ) & 1 */
4342   if (!IS_AST_LIT_VALUE (tree->right))
4343     return tree;
4344
4345   if (AST_LIT_VALUE (tree->right) != 1)
4346     return tree;
4347
4348   if (!IS_RIGHT_OP (tree->left))
4349     return tree;
4350
4351   if (!IS_AST_LIT_VALUE (tree->left->right))
4352     return tree;
4353
4354   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4355       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4356     return tree;
4357       
4358   /* make sure the port supports GETHBIT */
4359   if (port->hasExtBitOp
4360       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4361     return tree;
4362
4363   return decorateType (newNode (GETHBIT, tree->left->left, NULL));
4364
4365 }
4366
4367 /*-----------------------------------------------------------------*/
4368 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4369 /*-----------------------------------------------------------------*/
4370 ast *
4371 optimizeRRCRLC (ast * root)
4372 {
4373   /* will look for trees of the form
4374      (?expr << 1) | (?expr >> 7) or
4375      (?expr >> 7) | (?expr << 1) will make that
4376      into a RLC : operation ..
4377      Will also look for
4378      (?expr >> 1) | (?expr << 7) or
4379      (?expr << 7) | (?expr >> 1) will make that
4380      into a RRC operation
4381      note : by 7 I mean (number of bits required to hold the
4382      variable -1 ) */
4383   /* if the root operations is not a | operation the not */
4384   if (!IS_BITOR (root))
4385     return root;
4386
4387   /* I have to think of a better way to match patterns this sucks */
4388   /* that aside let start looking for the first case : I use a the
4389      negative check a lot to improve the efficiency */
4390   /* (?expr << 1) | (?expr >> 7) */
4391   if (IS_LEFT_OP (root->left) &&
4392       IS_RIGHT_OP (root->right))
4393     {
4394
4395       if (!SPEC_USIGN (TETYPE (root->left->left)))
4396         return root;
4397
4398       if (!IS_AST_LIT_VALUE (root->left->right) ||
4399           !IS_AST_LIT_VALUE (root->right->right))
4400         goto tryNext0;
4401
4402       /* make sure it is the same expression */
4403       if (!isAstEqual (root->left->left,
4404                        root->right->left))
4405         goto tryNext0;
4406
4407       if (AST_LIT_VALUE (root->left->right) != 1)
4408         goto tryNext0;
4409
4410       if (AST_LIT_VALUE (root->right->right) !=
4411           (getSize (TTYPE (root->left->left)) * 8 - 1))
4412         goto tryNext0;
4413
4414       /* make sure the port supports RLC */
4415       if (port->hasExtBitOp
4416           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4417         return root;
4418
4419       /* whew got the first case : create the AST */
4420       return newNode (RLC, root->left->left, NULL);
4421     }
4422
4423 tryNext0:
4424   /* check for second case */
4425   /* (?expr >> 7) | (?expr << 1) */
4426   if (IS_LEFT_OP (root->right) &&
4427       IS_RIGHT_OP (root->left))
4428     {
4429
4430       if (!SPEC_USIGN (TETYPE (root->left->left)))
4431         return root;
4432
4433       if (!IS_AST_LIT_VALUE (root->left->right) ||
4434           !IS_AST_LIT_VALUE (root->right->right))
4435         goto tryNext1;
4436
4437       /* make sure it is the same symbol */
4438       if (!isAstEqual (root->left->left,
4439                        root->right->left))
4440         goto tryNext1;
4441
4442       if (AST_LIT_VALUE (root->right->right) != 1)
4443         goto tryNext1;
4444
4445       if (AST_LIT_VALUE (root->left->right) !=
4446           (getSize (TTYPE (root->left->left)) * 8 - 1))
4447         goto tryNext1;
4448
4449       /* make sure the port supports RLC */
4450       if (port->hasExtBitOp
4451           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4452         return root;
4453
4454       /* whew got the first case : create the AST */
4455       return newNode (RLC, root->left->left, NULL);
4456
4457     }
4458
4459 tryNext1:
4460   /* third case for RRC */
4461   /*  (?symbol >> 1) | (?symbol << 7) */
4462   if (IS_LEFT_OP (root->right) &&
4463       IS_RIGHT_OP (root->left))
4464     {
4465
4466       if (!SPEC_USIGN (TETYPE (root->left->left)))
4467         return root;
4468
4469       if (!IS_AST_LIT_VALUE (root->left->right) ||
4470           !IS_AST_LIT_VALUE (root->right->right))
4471         goto tryNext2;
4472
4473       /* make sure it is the same symbol */
4474       if (!isAstEqual (root->left->left,
4475                        root->right->left))
4476         goto tryNext2;
4477
4478       if (AST_LIT_VALUE (root->left->right) != 1)
4479         goto tryNext2;
4480
4481       if (AST_LIT_VALUE (root->right->right) !=
4482           (getSize (TTYPE (root->left->left)) * 8 - 1))
4483         goto tryNext2;
4484
4485       /* make sure the port supports RRC */
4486       if (port->hasExtBitOp
4487           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4488         return root;
4489
4490       /* whew got the first case : create the AST */
4491       return newNode (RRC, root->left->left, NULL);
4492
4493     }
4494 tryNext2:
4495   /* fourth and last case for now */
4496   /* (?symbol << 7) | (?symbol >> 1) */
4497   if (IS_RIGHT_OP (root->right) &&
4498       IS_LEFT_OP (root->left))
4499     {
4500
4501       if (!SPEC_USIGN (TETYPE (root->left->left)))
4502         return root;
4503
4504       if (!IS_AST_LIT_VALUE (root->left->right) ||
4505           !IS_AST_LIT_VALUE (root->right->right))
4506         return root;
4507
4508       /* make sure it is the same symbol */
4509       if (!isAstEqual (root->left->left,
4510                        root->right->left))
4511         return root;
4512
4513       if (AST_LIT_VALUE (root->right->right) != 1)
4514         return root;
4515
4516       if (AST_LIT_VALUE (root->left->right) !=
4517           (getSize (TTYPE (root->left->left)) * 8 - 1))
4518         return root;
4519
4520       /* make sure the port supports RRC */
4521       if (port->hasExtBitOp
4522           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4523         return root;
4524
4525       /* whew got the first case : create the AST */
4526       return newNode (RRC, root->left->left, NULL);
4527
4528     }
4529
4530   /* not found return root */
4531   return root;
4532 }
4533
4534 /*-----------------------------------------------------------------*/
4535 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
4536 /*-----------------------------------------------------------------*/
4537 ast *
4538 optimizeSWAP (ast * root)
4539 {
4540   /* will look for trees of the form
4541      (?expr << 4) | (?expr >> 4) or
4542      (?expr >> 4) | (?expr << 4) will make that
4543      into a SWAP : operation ..
4544      note : by 4 I mean (number of bits required to hold the
4545      variable /2 ) */
4546   /* if the root operations is not a | operation the not */
4547   if (!IS_BITOR (root))
4548     return root;
4549
4550   /* (?expr << 4) | (?expr >> 4) */
4551   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
4552       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
4553     {
4554
4555       if (!SPEC_USIGN (TETYPE (root->left->left)))
4556         return root;
4557
4558       if (!IS_AST_LIT_VALUE (root->left->right) ||
4559           !IS_AST_LIT_VALUE (root->right->right))
4560         return root;
4561
4562       /* make sure it is the same expression */
4563       if (!isAstEqual (root->left->left,
4564                        root->right->left))
4565         return root;
4566
4567       if (AST_LIT_VALUE (root->left->right) !=
4568           (getSize (TTYPE (root->left->left)) * 4))
4569         return root;
4570
4571       if (AST_LIT_VALUE (root->right->right) !=
4572           (getSize (TTYPE (root->left->left)) * 4))
4573         return root;
4574
4575       /* make sure the port supports SWAP */
4576       if (port->hasExtBitOp
4577           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
4578         return root;
4579
4580       /* found it : create the AST */
4581       return newNode (SWAP, root->left->left, NULL);
4582     }
4583
4584
4585   /* not found return root */
4586   return root;
4587 }
4588
4589 /*-----------------------------------------------------------------*/
4590 /* optimizeCompare - otimizes compares for bit variables     */
4591 /*-----------------------------------------------------------------*/
4592 static ast *
4593 optimizeCompare (ast * root)
4594 {
4595   ast *optExpr = NULL;
4596   value *vleft;
4597   value *vright;
4598   unsigned int litValue;
4599
4600   /* if nothing then return nothing */
4601   if (!root)
4602     return NULL;
4603
4604   /* if not a compare op then do leaves */
4605   if (!IS_COMPARE_OP (root))
4606     {
4607       root->left = optimizeCompare (root->left);
4608       root->right = optimizeCompare (root->right);
4609       return root;
4610     }
4611
4612   /* if left & right are the same then depending
4613      of the operation do */
4614   if (isAstEqual (root->left, root->right))
4615     {
4616       switch (root->opval.op)
4617         {
4618         case '>':
4619         case '<':
4620         case NE_OP:
4621           optExpr = newAst_VALUE (constVal ("0"));
4622           break;
4623         case GE_OP:
4624         case LE_OP:
4625         case EQ_OP:
4626           optExpr = newAst_VALUE (constVal ("1"));
4627           break;
4628         }
4629
4630       return decorateType (optExpr);
4631     }
4632
4633   vleft = (root->left->type == EX_VALUE ?
4634            root->left->opval.val : NULL);
4635
4636   vright = (root->right->type == EX_VALUE ?
4637             root->right->opval.val : NULL);
4638
4639   /* if left is a BITVAR in BITSPACE */
4640   /* and right is a LITERAL then opt- */
4641   /* imize else do nothing       */
4642   if (vleft && vright &&
4643       IS_BITVAR (vleft->etype) &&
4644       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
4645       IS_LITERAL (vright->etype))
4646     {
4647
4648       /* if right side > 1 then comparison may never succeed */
4649       if ((litValue = (int) floatFromVal (vright)) > 1)
4650         {
4651           werror (W_BAD_COMPARE);
4652           goto noOptimize;
4653         }
4654
4655       if (litValue)
4656         {
4657           switch (root->opval.op)
4658             {
4659             case '>':           /* bit value greater than 1 cannot be */
4660               werror (W_BAD_COMPARE);
4661               goto noOptimize;
4662               break;
4663
4664             case '<':           /* bit value < 1 means 0 */
4665             case NE_OP:
4666               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
4667               break;
4668
4669             case LE_OP: /* bit value <= 1 means no check */
4670               optExpr = newAst_VALUE (vright);
4671               break;
4672
4673             case GE_OP: /* bit value >= 1 means only check for = */
4674             case EQ_OP:
4675               optExpr = newAst_VALUE (vleft);
4676               break;
4677             }
4678         }
4679       else
4680         {                       /* literal is zero */
4681           switch (root->opval.op)
4682             {
4683             case '<':           /* bit value < 0 cannot be */
4684               werror (W_BAD_COMPARE);
4685               goto noOptimize;
4686               break;
4687
4688             case '>':           /* bit value > 0 means 1 */
4689             case NE_OP:
4690               optExpr = newAst_VALUE (vleft);
4691               break;
4692
4693             case LE_OP: /* bit value <= 0 means no check */
4694             case GE_OP: /* bit value >= 0 means no check */
4695               werror (W_BAD_COMPARE);
4696               goto noOptimize;
4697               break;
4698
4699             case EQ_OP: /* bit == 0 means ! of bit */
4700               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
4701               break;
4702             }
4703         }
4704       return decorateType (resolveSymbols (optExpr));
4705     }                           /* end-of-if of BITVAR */
4706
4707 noOptimize:
4708   return root;
4709 }
4710 /*-----------------------------------------------------------------*/
4711 /* addSymToBlock : adds the symbol to the first block we find      */
4712 /*-----------------------------------------------------------------*/
4713 void 
4714 addSymToBlock (symbol * sym, ast * tree)
4715 {
4716   /* reached end of tree or a leaf */
4717   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
4718     return;
4719
4720   /* found a block */
4721   if (IS_AST_OP (tree) &&
4722       tree->opval.op == BLOCK)
4723     {
4724
4725       symbol *lsym = copySymbol (sym);
4726
4727       lsym->next = AST_VALUES (tree, sym);
4728       AST_VALUES (tree, sym) = lsym;
4729       return;
4730     }
4731
4732   addSymToBlock (sym, tree->left);
4733   addSymToBlock (sym, tree->right);
4734 }
4735
4736 /*-----------------------------------------------------------------*/
4737 /* processRegParms - do processing for register parameters         */
4738 /*-----------------------------------------------------------------*/
4739 static void 
4740 processRegParms (value * args, ast * body)
4741 {
4742   while (args)
4743     {
4744       if (IS_REGPARM (args->etype))
4745         addSymToBlock (args->sym, body);
4746       args = args->next;
4747     }
4748 }
4749
4750 /*-----------------------------------------------------------------*/
4751 /* resetParmKey - resets the operandkeys for the symbols           */
4752 /*-----------------------------------------------------------------*/
4753 DEFSETFUNC (resetParmKey)
4754 {
4755   symbol *sym = item;
4756
4757   sym->key = 0;
4758   sym->defs = NULL;
4759   sym->uses = NULL;
4760   sym->remat = 0;
4761   return 1;
4762 }
4763
4764 /*-----------------------------------------------------------------*/
4765 /* createFunction - This is the key node that calls the iCode for  */
4766 /*                  generating the code for a function. Note code  */
4767 /*                  is generated function by function, later when  */
4768 /*                  add inter-procedural analysis this will change */
4769 /*-----------------------------------------------------------------*/
4770 ast *
4771 createFunction (symbol * name, ast * body)
4772 {
4773   ast *ex;
4774   symbol *csym;
4775   int stack = 0;
4776   sym_link *fetype;
4777   iCode *piCode = NULL;
4778
4779   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
4780     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
4781
4782   /* if check function return 0 then some problem */
4783   if (checkFunction (name, NULL) == 0)
4784     return NULL;
4785
4786   /* create a dummy block if none exists */
4787   if (!body)
4788     body = newNode (BLOCK, NULL, NULL);
4789
4790   noLineno++;
4791
4792   /* check if the function name already in the symbol table */
4793   if ((csym = findSym (SymbolTab, NULL, name->name)))
4794     {
4795       name = csym;
4796       /* special case for compiler defined functions
4797          we need to add the name to the publics list : this
4798          actually means we are now compiling the compiler
4799          support routine */
4800       if (name->cdef)
4801         {
4802           addSet (&publics, name);
4803         }
4804     }
4805   else
4806     {
4807       addSymChain (name);
4808       allocVariables (name);
4809     }
4810   name->lastLine = mylineno;
4811   currFunc = name;
4812
4813   /* set the stack pointer */
4814   /* PENDING: check this for the mcs51 */
4815   stackPtr = -port->stack.direction * port->stack.call_overhead;
4816   if (IFFUNC_ISISR (name->type))
4817     stackPtr -= port->stack.direction * port->stack.isr_overhead;
4818   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
4819     stackPtr -= port->stack.direction * port->stack.reent_overhead;
4820
4821   xstackPtr = -port->stack.direction * port->stack.call_overhead;
4822
4823   fetype = getSpec (name->type);        /* get the specifier for the function */
4824   /* if this is a reentrant function then */
4825   if (IFFUNC_ISREENT (name->type))
4826     reentrant++;
4827
4828   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
4829
4830   /* do processing for parameters that are passed in registers */
4831   processRegParms (FUNC_ARGS(name->type), body);
4832
4833   /* set the stack pointer */
4834   stackPtr = 0;
4835   xstackPtr = -1;
4836
4837   /* allocate & autoinit the block variables */
4838   processBlockVars (body, &stack, ALLOCATE);
4839
4840   /* save the stack information */
4841   if (options.useXstack)
4842     name->xstack = SPEC_STAK (fetype) = stack;
4843   else
4844     name->stack = SPEC_STAK (fetype) = stack;
4845
4846   /* name needs to be mangled */
4847   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
4848
4849   body = resolveSymbols (body); /* resolve the symbols */
4850   body = decorateType (body);   /* propagateType & do semantic checks */
4851
4852   ex = newAst_VALUE (symbolVal (name)); /* create name */
4853   ex = newNode (FUNCTION, ex, body);
4854   ex->values.args = FUNC_ARGS(name->type);
4855   ex->decorated=1;
4856   if (options.dump_tree) PA(ex);
4857   if (fatalError)
4858     {
4859       werror (E_FUNC_NO_CODE, name->name);
4860       goto skipall;
4861     }
4862
4863   /* create the node & generate intermediate code */
4864   GcurMemmap = code;
4865   codeOutFile = code->oFile;
4866   piCode = iCodeFromAst (ex);
4867
4868   if (fatalError)
4869     {
4870       werror (E_FUNC_NO_CODE, name->name);
4871       goto skipall;
4872     }
4873
4874   eBBlockFromiCode (piCode);
4875
4876   /* if there are any statics then do them */
4877   if (staticAutos)
4878     {
4879       GcurMemmap = statsg;
4880       codeOutFile = statsg->oFile;
4881       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos))));
4882       staticAutos = NULL;
4883     }
4884
4885 skipall:
4886
4887   /* dealloc the block variables */
4888   processBlockVars (body, &stack, DEALLOCATE);
4889   outputDebugStackSymbols();
4890   /* deallocate paramaters */
4891   deallocParms (FUNC_ARGS(name->type));
4892
4893   if (IFFUNC_ISREENT (name->type))
4894     reentrant--;
4895
4896   /* we are done freeup memory & cleanup */
4897   noLineno--;
4898   if (port->reset_labelKey) labelKey = 1;
4899   name->key = 0;
4900   FUNC_HASBODY(name->type) = 1;
4901   addSet (&operKeyReset, name);
4902   applyToSet (operKeyReset, resetParmKey);
4903
4904   if (options.debug)
4905     cdbStructBlock(1);
4906
4907   cleanUpLevel (LabelTab, 0);
4908   cleanUpBlock (StructTab, 1);
4909   cleanUpBlock (TypedefTab, 1);
4910
4911   xstack->syms = NULL;
4912   istack->syms = NULL;
4913   return NULL;
4914 }
4915
4916
4917 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
4918 /*-----------------------------------------------------------------*/
4919 /* ast_print : prints the ast (for debugging purposes)             */
4920 /*-----------------------------------------------------------------*/
4921
4922 void ast_print (ast * tree, FILE *outfile, int indent)
4923 {
4924
4925         if (!tree) return ;
4926
4927         /* can print only decorated trees */
4928         if (!tree->decorated) return;
4929
4930         /* if any child is an error | this one is an error do nothing */
4931         if (tree->isError ||
4932             (tree->left && tree->left->isError) ||
4933             (tree->right && tree->right->isError)) {
4934                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
4935         }
4936
4937
4938         /* print the line          */
4939         /* if not block & function */
4940         if (tree->type == EX_OP &&
4941             (tree->opval.op != FUNCTION &&
4942              tree->opval.op != BLOCK &&
4943              tree->opval.op != NULLOP)) {
4944         }
4945
4946         if (tree->opval.op == FUNCTION) {
4947                 int arg=0;
4948                 value *args=FUNC_ARGS(tree->left->opval.val->type);
4949                 fprintf(outfile,"FUNCTION (%s=%p) type (",
4950                         tree->left->opval.val->name, tree);
4951                 printTypeChain (tree->left->opval.val->type->next,outfile);
4952                 fprintf(outfile,") args (");
4953                 do {
4954                   if (arg) {
4955                     fprintf (outfile, ", ");
4956                   }
4957                   printTypeChain (args ? args->type : NULL, outfile);
4958                   arg++;
4959                   args= args ? args->next : NULL;
4960                 } while (args);
4961                 fprintf(outfile,")\n");
4962                 ast_print(tree->left,outfile,indent);
4963                 ast_print(tree->right,outfile,indent);
4964                 return ;
4965         }
4966         if (tree->opval.op == BLOCK) {
4967                 symbol *decls = tree->values.sym;
4968                 INDENT(indent,outfile);
4969                 fprintf(outfile,"{\n");
4970                 while (decls) {
4971                         INDENT(indent+2,outfile);
4972                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
4973                                 decls->name, decls);
4974                         printTypeChain(decls->type,outfile);
4975                         fprintf(outfile,")\n");
4976
4977                         decls = decls->next;
4978                 }
4979                 ast_print(tree->right,outfile,indent+2);
4980                 INDENT(indent,outfile);
4981                 fprintf(outfile,"}\n");
4982                 return;
4983         }
4984         if (tree->opval.op == NULLOP) {
4985                 ast_print(tree->left,outfile,indent);
4986                 ast_print(tree->right,outfile,indent);
4987                 return ;
4988         }
4989         INDENT(indent,outfile);
4990
4991         /*------------------------------------------------------------------*/
4992         /*----------------------------*/
4993         /*   leaf has been reached    */
4994         /*----------------------------*/
4995         /* if this is of type value */
4996         /* just get the type        */
4997         if (tree->type == EX_VALUE) {
4998
4999                 if (IS_LITERAL (tree->opval.val->etype)) {
5000                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5001                         if (SPEC_USIGN (tree->opval.val->etype))
5002                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5003                         else
5004                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5005                         fprintf(outfile,", 0x%x, %g", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5006                                                       floatFromVal(tree->opval.val));
5007                 } else if (tree->opval.val->sym) {
5008                         /* if the undefined flag is set then give error message */
5009                         if (tree->opval.val->sym->undefined) {
5010                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5011                         } else {
5012                                 fprintf(outfile,"SYMBOL ");
5013                         }
5014                         fprintf(outfile,"(%s=%p)",
5015                                 tree->opval.val->sym->name,tree);
5016                 }
5017                 if (tree->ftype) {
5018                         fprintf(outfile," type (");
5019                         printTypeChain(tree->ftype,outfile);
5020                         fprintf(outfile,")\n");
5021                 } else {
5022                         fprintf(outfile,"\n");
5023                 }
5024                 return ;
5025         }
5026
5027         /* if type link for the case of cast */
5028         if (tree->type == EX_LINK) {
5029                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5030                 printTypeChain(tree->opval.lnk,outfile);
5031                 fprintf(outfile,")\n");
5032                 return ;
5033         }
5034
5035
5036         /* depending on type of operator do */
5037
5038         switch (tree->opval.op) {
5039                 /*------------------------------------------------------------------*/
5040                 /*----------------------------*/
5041                 /*        array node          */
5042                 /*----------------------------*/
5043         case '[':
5044                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5045                 printTypeChain(tree->ftype,outfile);
5046                 fprintf(outfile,")\n");
5047                 ast_print(tree->left,outfile,indent+2);
5048                 ast_print(tree->right,outfile,indent+2);
5049                 return;
5050
5051                 /*------------------------------------------------------------------*/
5052                 /*----------------------------*/
5053                 /*      struct/union          */
5054                 /*----------------------------*/
5055         case '.':
5056                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5057                 printTypeChain(tree->ftype,outfile);
5058                 fprintf(outfile,")\n");
5059                 ast_print(tree->left,outfile,indent+2);
5060                 ast_print(tree->right,outfile,indent+2);
5061                 return ;
5062
5063                 /*------------------------------------------------------------------*/
5064                 /*----------------------------*/
5065                 /*    struct/union pointer    */
5066                 /*----------------------------*/
5067         case PTR_OP:
5068                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5069                 printTypeChain(tree->ftype,outfile);
5070                 fprintf(outfile,")\n");
5071                 ast_print(tree->left,outfile,indent+2);
5072                 ast_print(tree->right,outfile,indent+2);
5073                 return ;
5074
5075                 /*------------------------------------------------------------------*/
5076                 /*----------------------------*/
5077                 /*  ++/-- operation           */
5078                 /*----------------------------*/
5079         case INC_OP:
5080                 if (tree->left)
5081                   fprintf(outfile,"post-");
5082                 else
5083                   fprintf(outfile,"pre-");
5084                 fprintf(outfile,"INC_OP (%p) type (",tree);
5085                 printTypeChain(tree->ftype,outfile);
5086                 fprintf(outfile,")\n");
5087                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5088                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5089                 return ;
5090
5091         case DEC_OP:
5092                 if (tree->left)
5093                   fprintf(outfile,"post-");
5094                 else
5095                   fprintf(outfile,"pre-");
5096                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5097                 printTypeChain(tree->ftype,outfile);
5098                 fprintf(outfile,")\n");
5099                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5100                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5101                 return ;
5102
5103                 /*------------------------------------------------------------------*/
5104                 /*----------------------------*/
5105                 /*  bitwise and               */
5106                 /*----------------------------*/
5107         case '&':
5108                 if (tree->right) {
5109                         fprintf(outfile,"& (%p) type (",tree);
5110                         printTypeChain(tree->ftype,outfile);
5111                         fprintf(outfile,")\n");
5112                         ast_print(tree->left,outfile,indent+2);
5113                         ast_print(tree->right,outfile,indent+2);
5114                 } else {
5115                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5116                         printTypeChain(tree->ftype,outfile);
5117                         fprintf(outfile,")\n");
5118                         ast_print(tree->left,outfile,indent+2);
5119                         ast_print(tree->right,outfile,indent+2);
5120                 }
5121                 return ;
5122                 /*----------------------------*/
5123                 /*  bitwise or                */
5124                 /*----------------------------*/
5125         case '|':
5126                 fprintf(outfile,"OR (%p) type (",tree);
5127                 printTypeChain(tree->ftype,outfile);
5128                 fprintf(outfile,")\n");
5129                 ast_print(tree->left,outfile,indent+2);
5130                 ast_print(tree->right,outfile,indent+2);
5131                 return ;
5132                 /*------------------------------------------------------------------*/
5133                 /*----------------------------*/
5134                 /*  bitwise xor               */
5135                 /*----------------------------*/
5136         case '^':
5137                 fprintf(outfile,"XOR (%p) type (",tree);
5138                 printTypeChain(tree->ftype,outfile);
5139                 fprintf(outfile,")\n");
5140                 ast_print(tree->left,outfile,indent+2);
5141                 ast_print(tree->right,outfile,indent+2);
5142                 return ;
5143
5144                 /*------------------------------------------------------------------*/
5145                 /*----------------------------*/
5146                 /*  division                  */
5147                 /*----------------------------*/
5148         case '/':
5149                 fprintf(outfile,"DIV (%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                 return ;
5155                 /*------------------------------------------------------------------*/
5156                 /*----------------------------*/
5157                 /*            modulus         */
5158                 /*----------------------------*/
5159         case '%':
5160                 fprintf(outfile,"MOD (%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                 /*----------------------------*/
5169                 /*  address dereference       */
5170                 /*----------------------------*/
5171         case '*':                       /* can be unary  : if right is null then unary operation */
5172                 if (!tree->right) {
5173                         fprintf(outfile,"DEREF (%p) type (",tree);
5174                         printTypeChain(tree->ftype,outfile);
5175                         fprintf(outfile,")\n");
5176                         ast_print(tree->left,outfile,indent+2);
5177                         return ;
5178                 }                       
5179                 /*------------------------------------------------------------------*/
5180                 /*----------------------------*/
5181                 /*      multiplication        */
5182                 /*----------------------------*/                
5183                 fprintf(outfile,"MULT (%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                 /*------------------------------------------------------------------*/
5192                 /*----------------------------*/
5193                 /*    unary '+' operator      */
5194                 /*----------------------------*/
5195         case '+':
5196                 /* if unary plus */
5197                 if (!tree->right) {
5198                         fprintf(outfile,"UPLUS (%p) type (",tree);
5199                         printTypeChain(tree->ftype,outfile);
5200                         fprintf(outfile,")\n");
5201                         ast_print(tree->left,outfile,indent+2);
5202                 } else {
5203                         /*------------------------------------------------------------------*/
5204                         /*----------------------------*/
5205                         /*      addition              */
5206                         /*----------------------------*/
5207                         fprintf(outfile,"ADD (%p) type (",tree);
5208                         printTypeChain(tree->ftype,outfile);
5209                         fprintf(outfile,")\n");
5210                         ast_print(tree->left,outfile,indent+2);
5211                         ast_print(tree->right,outfile,indent+2);
5212                 }
5213                 return;
5214                 /*------------------------------------------------------------------*/
5215                 /*----------------------------*/
5216                 /*      unary '-'             */
5217                 /*----------------------------*/
5218         case '-':                       /* can be unary   */
5219                 if (!tree->right) {
5220                         fprintf(outfile,"UMINUS (%p) type (",tree);
5221                         printTypeChain(tree->ftype,outfile);
5222                         fprintf(outfile,")\n");
5223                         ast_print(tree->left,outfile,indent+2);
5224                 } else {
5225                         /*------------------------------------------------------------------*/
5226                         /*----------------------------*/
5227                         /*      subtraction           */
5228                         /*----------------------------*/
5229                         fprintf(outfile,"SUB (%p) type (",tree);
5230                         printTypeChain(tree->ftype,outfile);
5231                         fprintf(outfile,")\n");
5232                         ast_print(tree->left,outfile,indent+2);
5233                         ast_print(tree->right,outfile,indent+2);
5234                 }
5235                 return;
5236                 /*------------------------------------------------------------------*/
5237                 /*----------------------------*/
5238                 /*    compliment              */
5239                 /*----------------------------*/
5240         case '~':
5241                 fprintf(outfile,"COMPL (%p) type (",tree);
5242                 printTypeChain(tree->ftype,outfile);
5243                 fprintf(outfile,")\n");
5244                 ast_print(tree->left,outfile,indent+2);
5245                 return ;
5246                 /*------------------------------------------------------------------*/
5247                 /*----------------------------*/
5248                 /*           not              */
5249                 /*----------------------------*/
5250         case '!':
5251                 fprintf(outfile,"NOT (%p) type (",tree);
5252                 printTypeChain(tree->ftype,outfile);
5253                 fprintf(outfile,")\n");
5254                 ast_print(tree->left,outfile,indent+2);
5255                 return ;
5256                 /*------------------------------------------------------------------*/
5257                 /*----------------------------*/
5258                 /*           shift            */
5259                 /*----------------------------*/
5260         case RRC:
5261                 fprintf(outfile,"RRC (%p) type (",tree);
5262                 printTypeChain(tree->ftype,outfile);
5263                 fprintf(outfile,")\n");
5264                 ast_print(tree->left,outfile,indent+2);
5265                 return ;
5266
5267         case RLC:
5268                 fprintf(outfile,"RLC (%p) type (",tree);
5269                 printTypeChain(tree->ftype,outfile);
5270                 fprintf(outfile,")\n");
5271                 ast_print(tree->left,outfile,indent+2);
5272                 return ;
5273         case SWAP:
5274                 fprintf(outfile,"SWAP (%p) type (",tree);
5275                 printTypeChain(tree->ftype,outfile);
5276                 fprintf(outfile,")\n");
5277                 ast_print(tree->left,outfile,indent+2);
5278                 return ;
5279         case GETHBIT:
5280                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5281                 printTypeChain(tree->ftype,outfile);
5282                 fprintf(outfile,")\n");
5283                 ast_print(tree->left,outfile,indent+2);
5284                 return ;
5285         case LEFT_OP:
5286                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5287                 printTypeChain(tree->ftype,outfile);
5288                 fprintf(outfile,")\n");
5289                 ast_print(tree->left,outfile,indent+2);
5290                 ast_print(tree->right,outfile,indent+2);
5291                 return ;
5292         case RIGHT_OP:
5293                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5294                 printTypeChain(tree->ftype,outfile);
5295                 fprintf(outfile,")\n");
5296                 ast_print(tree->left,outfile,indent+2);
5297                 ast_print(tree->right,outfile,indent+2);
5298                 return ;
5299                 /*------------------------------------------------------------------*/
5300                 /*----------------------------*/
5301                 /*         casting            */
5302                 /*----------------------------*/
5303         case CAST:                      /* change the type   */
5304                 fprintf(outfile,"CAST (%p) from type (",tree);
5305                 printTypeChain(tree->right->ftype,outfile);
5306                 fprintf(outfile,") to type (");
5307                 printTypeChain(tree->ftype,outfile);
5308                 fprintf(outfile,")\n");
5309                 ast_print(tree->right,outfile,indent+2);
5310                 return ;
5311                 
5312         case AND_OP:
5313                 fprintf(outfile,"ANDAND (%p) type (",tree);
5314                 printTypeChain(tree->ftype,outfile);
5315                 fprintf(outfile,")\n");
5316                 ast_print(tree->left,outfile,indent+2);
5317                 ast_print(tree->right,outfile,indent+2);
5318                 return ;
5319         case OR_OP:
5320                 fprintf(outfile,"OROR (%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                 
5327                 /*------------------------------------------------------------------*/
5328                 /*----------------------------*/
5329                 /*     comparison operators   */
5330                 /*----------------------------*/
5331         case '>':
5332                 fprintf(outfile,"GT(>) (%p) type (",tree);
5333                 printTypeChain(tree->ftype,outfile);
5334                 fprintf(outfile,")\n");
5335                 ast_print(tree->left,outfile,indent+2);
5336                 ast_print(tree->right,outfile,indent+2);
5337                 return ;
5338         case '<':
5339                 fprintf(outfile,"LT(<) (%p) type (",tree);
5340                 printTypeChain(tree->ftype,outfile);
5341                 fprintf(outfile,")\n");
5342                 ast_print(tree->left,outfile,indent+2);
5343                 ast_print(tree->right,outfile,indent+2);
5344                 return ;
5345         case LE_OP:
5346                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5347                 printTypeChain(tree->ftype,outfile);
5348                 fprintf(outfile,")\n");
5349                 ast_print(tree->left,outfile,indent+2);
5350                 ast_print(tree->right,outfile,indent+2);
5351                 return ;
5352         case GE_OP:
5353                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5354                 printTypeChain(tree->ftype,outfile);
5355                 fprintf(outfile,")\n");
5356                 ast_print(tree->left,outfile,indent+2);
5357                 ast_print(tree->right,outfile,indent+2);
5358                 return ;
5359         case EQ_OP:
5360                 fprintf(outfile,"EQ(==) (%p) type (",tree);
5361                 printTypeChain(tree->ftype,outfile);
5362                 fprintf(outfile,")\n");
5363                 ast_print(tree->left,outfile,indent+2);
5364                 ast_print(tree->right,outfile,indent+2);
5365                 return ;
5366         case NE_OP:
5367                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5368                 printTypeChain(tree->ftype,outfile);
5369                 fprintf(outfile,")\n");
5370                 ast_print(tree->left,outfile,indent+2);
5371                 ast_print(tree->right,outfile,indent+2);
5372                 /*------------------------------------------------------------------*/
5373                 /*----------------------------*/
5374                 /*             sizeof         */
5375                 /*----------------------------*/
5376         case SIZEOF:            /* evaluate wihout code generation */
5377                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5378                 return ;
5379
5380                 /*------------------------------------------------------------------*/
5381                 /*----------------------------*/
5382                 /* conditional operator  '?'  */
5383                 /*----------------------------*/
5384         case '?':
5385                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5386                 printTypeChain(tree->ftype,outfile);
5387                 fprintf(outfile,")\n");
5388                 ast_print(tree->left,outfile,indent+2);
5389                 ast_print(tree->right,outfile,indent+2);
5390                 return;
5391
5392         case ':':
5393                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5394                 printTypeChain(tree->ftype,outfile);
5395                 fprintf(outfile,")\n");
5396                 ast_print(tree->left,outfile,indent+2);
5397                 ast_print(tree->right,outfile,indent+2);
5398                 return ;
5399                 
5400                 /*------------------------------------------------------------------*/
5401                 /*----------------------------*/
5402                 /*    assignment operators    */
5403                 /*----------------------------*/
5404         case MUL_ASSIGN:
5405                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5406                 printTypeChain(tree->ftype,outfile);
5407                 fprintf(outfile,")\n");
5408                 ast_print(tree->left,outfile,indent+2);
5409                 ast_print(tree->right,outfile,indent+2);
5410                 return;
5411         case DIV_ASSIGN:
5412                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5413                 printTypeChain(tree->ftype,outfile);
5414                 fprintf(outfile,")\n");
5415                 ast_print(tree->left,outfile,indent+2);
5416                 ast_print(tree->right,outfile,indent+2);
5417                 return;
5418         case AND_ASSIGN:
5419                 fprintf(outfile,"ANDASS(&=) (%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         case OR_ASSIGN:
5426                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5427                 printTypeChain(tree->ftype,outfile);
5428                 fprintf(outfile,")\n");
5429                 ast_print(tree->left,outfile,indent+2);
5430                 ast_print(tree->right,outfile,indent+2);
5431                 return;
5432         case XOR_ASSIGN:
5433                 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
5434                 printTypeChain(tree->ftype,outfile);
5435                 fprintf(outfile,")\n");
5436                 ast_print(tree->left,outfile,indent+2);
5437                 ast_print(tree->right,outfile,indent+2);
5438                 return;
5439         case RIGHT_ASSIGN:
5440                 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
5441                 printTypeChain(tree->ftype,outfile);
5442                 fprintf(outfile,")\n");
5443                 ast_print(tree->left,outfile,indent+2);
5444                 ast_print(tree->right,outfile,indent+2);
5445                 return;
5446         case LEFT_ASSIGN:
5447                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5448                 printTypeChain(tree->ftype,outfile);
5449                 fprintf(outfile,")\n");
5450                 ast_print(tree->left,outfile,indent+2);
5451                 ast_print(tree->right,outfile,indent+2);
5452                 return;
5453                 /*------------------------------------------------------------------*/
5454                 /*----------------------------*/
5455                 /*    -= operator             */
5456                 /*----------------------------*/
5457         case SUB_ASSIGN:
5458                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5459                 printTypeChain(tree->ftype,outfile);
5460                 fprintf(outfile,")\n");
5461                 ast_print(tree->left,outfile,indent+2);
5462                 ast_print(tree->right,outfile,indent+2);
5463                 return;
5464                 /*------------------------------------------------------------------*/
5465                 /*----------------------------*/
5466                 /*          += operator       */
5467                 /*----------------------------*/
5468         case ADD_ASSIGN:
5469                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5470                 printTypeChain(tree->ftype,outfile);
5471                 fprintf(outfile,")\n");
5472                 ast_print(tree->left,outfile,indent+2);
5473                 ast_print(tree->right,outfile,indent+2);
5474                 return;
5475                 /*------------------------------------------------------------------*/
5476                 /*----------------------------*/
5477                 /*      straight assignemnt   */
5478                 /*----------------------------*/
5479         case '=':
5480                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5481                 printTypeChain(tree->ftype,outfile);
5482                 fprintf(outfile,")\n");
5483                 ast_print(tree->left,outfile,indent+2);
5484                 ast_print(tree->right,outfile,indent+2);
5485                 return;     
5486                 /*------------------------------------------------------------------*/
5487                 /*----------------------------*/
5488                 /*      comma operator        */
5489                 /*----------------------------*/
5490         case ',':
5491                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
5492                 printTypeChain(tree->ftype,outfile);
5493                 fprintf(outfile,")\n");
5494                 ast_print(tree->left,outfile,indent+2);
5495                 ast_print(tree->right,outfile,indent+2);
5496                 return;
5497                 /*------------------------------------------------------------------*/
5498                 /*----------------------------*/
5499                 /*       function call        */
5500                 /*----------------------------*/
5501         case CALL:
5502         case PCALL:
5503                 fprintf(outfile,"CALL (%p) type (",tree);
5504                 printTypeChain(tree->ftype,outfile);
5505                 fprintf(outfile,")\n");
5506                 ast_print(tree->left,outfile,indent+2);
5507                 ast_print(tree->right,outfile,indent+2);
5508                 return;
5509         case PARAM:
5510                 fprintf(outfile,"PARMS\n");
5511                 ast_print(tree->left,outfile,indent+2);
5512                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
5513                         ast_print(tree->right,outfile,indent+2);
5514                 }
5515                 return ;
5516                 /*------------------------------------------------------------------*/
5517                 /*----------------------------*/
5518                 /*     return statement       */
5519                 /*----------------------------*/
5520         case RETURN:
5521                 fprintf(outfile,"RETURN (%p) type (",tree);
5522                 if (tree->right) {
5523                     printTypeChain(tree->right->ftype,outfile);
5524                 }
5525                 fprintf(outfile,")\n");
5526                 ast_print(tree->right,outfile,indent+2);
5527                 return ;
5528                 /*------------------------------------------------------------------*/
5529                 /*----------------------------*/
5530                 /*     label statement        */
5531                 /*----------------------------*/
5532         case LABEL :
5533                 fprintf(outfile,"LABEL (%p)\n",tree);
5534                 ast_print(tree->left,outfile,indent+2);
5535                 ast_print(tree->right,outfile,indent);
5536                 return;
5537                 /*------------------------------------------------------------------*/
5538                 /*----------------------------*/
5539                 /*     switch statement       */
5540                 /*----------------------------*/
5541         case SWITCH:
5542                 {
5543                         value *val;
5544                         fprintf(outfile,"SWITCH (%p) ",tree);
5545                         ast_print(tree->left,outfile,0);
5546                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
5547                                 INDENT(indent+2,outfile);
5548                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
5549                                         (int) floatFromVal(val),
5550                                         tree->values.switchVals.swNum,
5551                                         (int) floatFromVal(val));
5552                         }
5553                         ast_print(tree->right,outfile,indent);
5554                 }
5555                 return ;
5556                 /*------------------------------------------------------------------*/
5557                 /*----------------------------*/
5558                 /* ifx Statement              */
5559                 /*----------------------------*/
5560         case IFX:
5561                 fprintf(outfile,"IF (%p) \n",tree);
5562                 ast_print(tree->left,outfile,indent+2);
5563                 if (tree->trueLabel) {
5564                         INDENT(indent+2,outfile);
5565                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
5566                 }
5567                 if (tree->falseLabel) {
5568                         INDENT(indent+2,outfile);
5569                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
5570                 }
5571                 ast_print(tree->right,outfile,indent+2);
5572                 return ;
5573                 /*----------------------------*/
5574                 /* goto Statement              */
5575                 /*----------------------------*/
5576         case GOTO:
5577                 fprintf(outfile,"GOTO (%p) \n",tree);
5578                 ast_print(tree->left,outfile,indent+2);
5579                 fprintf(outfile,"\n");
5580                 return ;
5581                 /*------------------------------------------------------------------*/
5582                 /*----------------------------*/
5583                 /* for Statement              */
5584                 /*----------------------------*/
5585         case FOR:
5586                 fprintf(outfile,"FOR (%p) \n",tree);
5587                 if (AST_FOR( tree, initExpr)) {
5588                         INDENT(indent+2,outfile);
5589                         fprintf(outfile,"INIT EXPR ");
5590                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
5591                 }
5592                 if (AST_FOR( tree, condExpr)) {
5593                         INDENT(indent+2,outfile);
5594                         fprintf(outfile,"COND EXPR ");
5595                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
5596                 }
5597                 if (AST_FOR( tree, loopExpr)) {
5598                         INDENT(indent+2,outfile);
5599                         fprintf(outfile,"LOOP EXPR ");
5600                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
5601                 }
5602                 fprintf(outfile,"FOR LOOP BODY \n");
5603                 ast_print(tree->left,outfile,indent+2);
5604                 return ;
5605         case CRITICAL:
5606                 fprintf(outfile,"CRITICAL (%p) \n",tree);
5607                 ast_print(tree->left,outfile,indent+2);
5608         default:
5609             return ;
5610         }
5611 }
5612
5613 void PA(ast *t)
5614 {
5615         ast_print(t,stdout,0);
5616 }