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