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