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