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