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