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