* device/include/malloc.h: removed redundant __reentrant prototypes
[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))
4182           && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
4183         {
4184           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4185           goto errorTreeReturn;
4186         }
4187
4188       /* if there are parms, make sure that
4189          parms are decorate / process / reverse only once */
4190       if (!tree->right ||
4191           !tree->right->decorated)
4192         {
4193           sym_link *functype;      
4194           parmNumber = 1;
4195
4196           if (IS_CODEPTR(LTYPE(tree)))
4197             functype = LTYPE (tree)->next;
4198           else
4199             functype = LTYPE (tree);
4200
4201           if (processParms (tree->left, FUNC_ARGS(functype),
4202                             &tree->right, &parmNumber, TRUE))
4203             {
4204               goto errorTreeReturn;
4205             }
4206         
4207           if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
4208              !IFFUNC_ISBUILTIN(functype))
4209             {
4210               reverseParms (tree->right);
4211             }
4212
4213            TTYPE (tree) = functype->next;
4214            TETYPE (tree) = getSpec (TTYPE (tree));
4215         }
4216       return tree;
4217
4218       /*------------------------------------------------------------------*/
4219       /*----------------------------*/
4220       /*     return statement       */
4221       /*----------------------------*/
4222     case RETURN:
4223       if (!tree->right)
4224         goto voidcheck;
4225
4226       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4227         {
4228           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4229           printFromToType (RTYPE(tree), currFunc->type->next);
4230           goto errorTreeReturn;
4231         }
4232
4233       if (IS_VOID (currFunc->type->next)
4234           && tree->right &&
4235           !IS_VOID (RTYPE (tree)))
4236         {
4237           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4238           goto errorTreeReturn;
4239         }
4240
4241       /* if there is going to be a casting required then add it */
4242       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4243         {
4244           tree->right =
4245             decorateType (newNode (CAST,
4246                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4247                                         tree->right),
4248                           RESULT_TYPE_NONE);
4249         }
4250
4251       RRVAL (tree) = 1;
4252       return tree;
4253
4254     voidcheck:
4255
4256       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4257         {
4258           werror (W_VOID_FUNC, currFunc->name);
4259           goto errorTreeReturn;
4260         }
4261
4262       TTYPE (tree) = TETYPE (tree) = NULL;
4263       return tree;
4264
4265       /*------------------------------------------------------------------*/
4266       /*----------------------------*/
4267       /*     switch statement       */
4268       /*----------------------------*/
4269     case SWITCH:
4270       /* the switch value must be an integer */
4271       if (!IS_INTEGRAL (LTYPE (tree)))
4272         {
4273           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4274           goto errorTreeReturn;
4275         }
4276       LRVAL (tree) = 1;
4277       TTYPE (tree) = TETYPE (tree) = NULL;
4278       return tree;
4279
4280       /*------------------------------------------------------------------*/
4281       /*----------------------------*/
4282       /* ifx Statement              */
4283       /*----------------------------*/
4284     case IFX:
4285       tree->left = backPatchLabels (tree->left,
4286                                     tree->trueLabel,
4287                                     tree->falseLabel);
4288       TTYPE (tree) = TETYPE (tree) = NULL;
4289       return tree;
4290
4291       /*------------------------------------------------------------------*/
4292       /*----------------------------*/
4293       /* for Statement              */
4294       /*----------------------------*/
4295     case FOR:
4296
4297       decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4298       decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4299       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4300
4301       /* if the for loop is reversible then
4302          reverse it otherwise do what we normally
4303          do */
4304       {
4305         symbol *sym;
4306         ast *init, *end;
4307
4308         if (isLoopReversible (tree, &sym, &init, &end))
4309           return reverseLoop (tree, sym, init, end);
4310         else
4311           return decorateType (createFor (AST_FOR (tree, trueLabel),
4312                                           AST_FOR (tree, continueLabel),
4313                                           AST_FOR (tree, falseLabel),
4314                                           AST_FOR (tree, condLabel),
4315                                           AST_FOR (tree, initExpr),
4316                                           AST_FOR (tree, condExpr),
4317                                           AST_FOR (tree, loopExpr),
4318                                           tree->left), RESULT_TYPE_NONE);
4319       }
4320     case PARAM:
4321       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4322               "node PARAM shouldn't be processed here");
4323               /* but in processParams() */
4324       return tree;
4325     default:
4326       TTYPE (tree) = TETYPE (tree) = NULL;
4327       return tree;
4328     }
4329
4330   /* some error found this tree will be killed */
4331 errorTreeReturn:
4332   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4333   tree->opval.op = NULLOP;
4334   tree->isError = 1;
4335
4336   return tree;
4337 }
4338
4339 /*-----------------------------------------------------------------*/
4340 /* sizeofOp - processes size of operation                          */
4341 /*-----------------------------------------------------------------*/
4342 value *
4343 sizeofOp (sym_link * type)
4344 {
4345   char buff[10];
4346   int size;
4347
4348   /* make sure the type is complete and sane */
4349   checkTypeSanity(type, "(sizeof)");
4350
4351   /* get the size and convert it to character  */
4352   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4353   if (!size && !IS_VOID(type))
4354     werror (E_SIZEOF_INCOMPLETE_TYPE);
4355
4356   /* now convert into value  */
4357   return constVal (buff);
4358 }
4359
4360
4361 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4362 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4363 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4364 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4365 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4366 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4367 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4368
4369 /*-----------------------------------------------------------------*/
4370 /* backPatchLabels - change and or not operators to flow control    */
4371 /*-----------------------------------------------------------------*/
4372 ast *
4373 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4374 {
4375
4376   if (!tree)
4377     return NULL;
4378
4379   if (!(IS_ANDORNOT (tree)))
4380     return tree;
4381
4382   /* if this an and */
4383   if (IS_AND (tree))
4384     {
4385       static int localLbl = 0;
4386       symbol *localLabel;
4387
4388       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4389       localLabel = newSymbol (buffer, NestLevel);
4390
4391       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4392
4393       /* if left is already a IFX then just change the if true label in that */
4394       if (!IS_IFX (tree->left))
4395         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4396
4397       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4398       /* right is a IFX then just join */
4399       if (IS_IFX (tree->right))
4400         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4401
4402       tree->right = createLabel (localLabel, tree->right);
4403       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4404
4405       return newNode (NULLOP, tree->left, tree->right);
4406     }
4407
4408   /* if this is an or operation */
4409   if (IS_OR (tree))
4410     {
4411       static int localLbl = 0;
4412       symbol *localLabel;
4413
4414       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4415       localLabel = newSymbol (buffer, NestLevel);
4416
4417       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4418
4419       /* if left is already a IFX then just change the if true label in that */
4420       if (!IS_IFX (tree->left))
4421         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4422
4423       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4424       /* right is a IFX then just join */
4425       if (IS_IFX (tree->right))
4426         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4427
4428       tree->right = createLabel (localLabel, tree->right);
4429       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4430
4431       return newNode (NULLOP, tree->left, tree->right);
4432     }
4433
4434   /* change not */
4435   if (IS_NOT (tree))
4436     {
4437       int wasnot = IS_NOT (tree->left);
4438       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4439
4440       /* if the left is already a IFX */
4441       if (!IS_IFX (tree->left))
4442         tree->left = newNode (IFX, tree->left, NULL);
4443
4444       if (wasnot)
4445         {
4446           tree->left->trueLabel = trueLabel;
4447           tree->left->falseLabel = falseLabel;
4448         }
4449       else
4450         {
4451           tree->left->trueLabel = falseLabel;
4452           tree->left->falseLabel = trueLabel;
4453         }
4454       return tree->left;
4455     }
4456
4457   if (IS_IFX (tree))
4458     {
4459       tree->trueLabel = trueLabel;
4460       tree->falseLabel = falseLabel;
4461     }
4462
4463   return tree;
4464 }
4465
4466
4467 /*-----------------------------------------------------------------*/
4468 /* createBlock - create expression tree for block                  */
4469 /*-----------------------------------------------------------------*/
4470 ast *
4471 createBlock (symbol * decl, ast * body)
4472 {
4473   ast *ex;
4474
4475   /* if the block has nothing */
4476   if (!body && !decl)
4477     return NULL;
4478
4479   ex = newNode (BLOCK, NULL, body);
4480   ex->values.sym = decl;
4481   
4482   ex->level++;
4483   ex->lineno = 0;
4484   return ex;
4485 }
4486
4487 /*-----------------------------------------------------------------*/
4488 /* createLabel - creates the expression tree for labels            */
4489 /*-----------------------------------------------------------------*/
4490 ast *
4491 createLabel (symbol * label, ast * stmnt)
4492 {
4493   symbol *csym;
4494   char name[SDCC_NAME_MAX + 1];
4495   ast *rValue;
4496
4497   /* must create fresh symbol if the symbol name  */
4498   /* exists in the symbol table, since there can  */
4499   /* be a variable with the same name as the labl */
4500   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4501       (csym->level == label->level))
4502     label = newSymbol (label->name, label->level);
4503
4504   /* change the name before putting it in add _ */
4505   SNPRINTF(name, sizeof(name), "%s", label->name);
4506
4507   /* put the label in the LabelSymbol table    */
4508   /* but first check if a label of the same    */
4509   /* name exists                               */
4510   if ((csym = findSym (LabelTab, NULL, name)))
4511     werror (E_DUPLICATE_LABEL, label->name);
4512   else
4513     addSym (LabelTab, label, name, label->level, 0, 0);
4514
4515   label->isitmp = 1;
4516   label->islbl = 1;
4517   label->key = labelKey++;
4518   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4519   rValue->lineno = 0;
4520
4521   return rValue;
4522 }
4523
4524 /*-----------------------------------------------------------------*/
4525 /* createCase - generates the parsetree for a case statement       */
4526 /*-----------------------------------------------------------------*/
4527 ast *
4528 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4529 {
4530   char caseLbl[SDCC_NAME_MAX + 1];
4531   ast *rexpr;
4532   value *val;
4533
4534   /* if the switch statement does not exist */
4535   /* then case is out of context            */
4536   if (!swStat)
4537     {
4538       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4539       return NULL;
4540     }
4541
4542   caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
4543   /* if not a constant then error  */
4544   if (!IS_LITERAL (caseVal->ftype))
4545     {
4546       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4547       return NULL;
4548     }
4549
4550   /* if not a integer than error */
4551   if (!IS_INTEGRAL (caseVal->ftype))
4552     {
4553       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4554       return NULL;
4555     }
4556
4557   /* find the end of the switch values chain   */
4558   if (!(val = swStat->values.switchVals.swVals))
4559     swStat->values.switchVals.swVals = caseVal->opval.val;
4560   else
4561     {
4562       /* also order the cases according to value */
4563       value *pval = NULL;
4564       int cVal = (int) floatFromVal (caseVal->opval.val);
4565       while (val && (int) floatFromVal (val) < cVal)
4566         {
4567           pval = val;
4568           val = val->next;
4569         }
4570
4571       /* if we reached the end then */
4572       if (!val)
4573         {
4574           pval->next = caseVal->opval.val;
4575         }
4576       else if ((int) floatFromVal (val) == cVal)
4577         {
4578           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4579                     "case");
4580           return NULL;
4581         }
4582       else
4583         {
4584           /* we found a value greater than */
4585           /* the current value we must add this */
4586           /* before the value */
4587           caseVal->opval.val->next = val;
4588
4589           /* if this was the first in chain */
4590           if (swStat->values.switchVals.swVals == val)
4591             swStat->values.switchVals.swVals =
4592               caseVal->opval.val;
4593           else
4594             pval->next = caseVal->opval.val;
4595         }
4596
4597     }
4598
4599   /* create the case label   */
4600   SNPRINTF(caseLbl, sizeof(caseLbl), 
4601            "_case_%d_%d",
4602            swStat->values.switchVals.swNum,
4603            (int) floatFromVal (caseVal->opval.val));
4604
4605   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4606   rexpr->lineno = 0;
4607   return rexpr;
4608 }
4609
4610 /*-----------------------------------------------------------------*/
4611 /* createDefault - creates the parse tree for the default statement */
4612 /*-----------------------------------------------------------------*/
4613 ast *
4614 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4615 {
4616   char defLbl[SDCC_NAME_MAX + 1];
4617
4618   /* if the switch statement does not exist */
4619   /* then case is out of context            */
4620   if (!swStat)
4621     {
4622       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4623       return NULL;
4624     }
4625
4626   if (swStat->values.switchVals.swDefault)
4627     {
4628       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4629                 "default");
4630       return NULL;
4631     }
4632
4633   /* turn on the default flag   */
4634   swStat->values.switchVals.swDefault = 1;
4635
4636   /* create the label  */
4637   SNPRINTF (defLbl, sizeof(defLbl),
4638             "_default_%d", swStat->values.switchVals.swNum);
4639   return createLabel (newSymbol (defLbl, 0), stmnt);
4640 }
4641
4642 /*-----------------------------------------------------------------*/
4643 /* createIf - creates the parsetree for the if statement           */
4644 /*-----------------------------------------------------------------*/
4645 ast *
4646 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4647 {
4648   static int Lblnum = 0;
4649   ast *ifTree;
4650   symbol *ifTrue, *ifFalse, *ifEnd;
4651
4652   /* if neither exists */
4653   if (!elseBody && !ifBody) {
4654     // if there are no side effects (i++, j() etc)
4655     if (!hasSEFcalls(condAst)) {
4656       return condAst;
4657     }
4658   }
4659
4660   /* create the labels */
4661   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4662   ifFalse = newSymbol (buffer, NestLevel);
4663   /* if no else body then end == false */
4664   if (!elseBody)
4665     ifEnd = ifFalse;
4666   else
4667     {
4668       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4669       ifEnd = newSymbol (buffer, NestLevel);
4670     }
4671
4672   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4673   ifTrue = newSymbol (buffer, NestLevel);
4674
4675   Lblnum++;
4676
4677   /* attach the ifTrue label to the top of it body */
4678   ifBody = createLabel (ifTrue, ifBody);
4679   /* attach a goto end to the ifBody if else is present */
4680   if (elseBody)
4681     {
4682       ifBody = newNode (NULLOP, ifBody,
4683                         newNode (GOTO,
4684                                  newAst_VALUE (symbolVal (ifEnd)),
4685                                  NULL));
4686       /* put the elseLabel on the else body */
4687       elseBody = createLabel (ifFalse, elseBody);
4688       /* out the end at the end of the body */
4689       elseBody = newNode (NULLOP,
4690                           elseBody,
4691                           createLabel (ifEnd, NULL));
4692     }
4693   else
4694     {
4695       ifBody = newNode (NULLOP, ifBody,
4696                         createLabel (ifFalse, NULL));
4697     }
4698   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4699   if (IS_IFX (condAst))
4700     ifTree = condAst;
4701   else
4702     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4703
4704   return newNode (NULLOP, ifTree,
4705                   newNode (NULLOP, ifBody, elseBody));
4706
4707 }
4708
4709 /*-----------------------------------------------------------------*/
4710 /* createDo - creates parse tree for do                            */
4711 /*        _dobody_n:                                               */
4712 /*            statements                                           */
4713 /*        _docontinue_n:                                           */
4714 /*            condition_expression +-> trueLabel -> _dobody_n      */
4715 /*                                 |                               */
4716 /*                                 +-> falseLabel-> _dobreak_n     */
4717 /*        _dobreak_n:                                              */
4718 /*-----------------------------------------------------------------*/
4719 ast *
4720 createDo (symbol * trueLabel, symbol * continueLabel,
4721           symbol * falseLabel, ast * condAst, ast * doBody)
4722 {
4723   ast *doTree;
4724
4725
4726   /* if the body does not exist then it is simple */
4727   if (!doBody)
4728     {
4729       condAst = backPatchLabels (condAst, continueLabel, NULL);
4730       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4731                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4732       doTree->trueLabel = continueLabel;
4733       doTree->falseLabel = NULL;
4734       return doTree;
4735     }
4736
4737   /* otherwise we have a body */
4738   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4739
4740   /* attach the body label to the top */
4741   doBody = createLabel (trueLabel, doBody);
4742   /* attach the continue label to end of body */
4743   doBody = newNode (NULLOP, doBody,
4744                     createLabel (continueLabel, NULL));
4745
4746   /* now put the break label at the end */
4747   if (IS_IFX (condAst))
4748     doTree = condAst;
4749   else
4750     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4751
4752   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4753
4754   /* putting it together */
4755   return newNode (NULLOP, doBody, doTree);
4756 }
4757
4758 /*-----------------------------------------------------------------*/
4759 /* createFor - creates parse tree for 'for' statement              */
4760 /*        initExpr                                                 */
4761 /*   _forcond_n:                                                   */
4762 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4763 /*                  |                                              */
4764 /*                  +-> falseLabel-> _forbreak_n                   */
4765 /*   _forbody_n:                                                   */
4766 /*        statements                                               */
4767 /*   _forcontinue_n:                                               */
4768 /*        loopExpr                                                 */
4769 /*        goto _forcond_n ;                                        */
4770 /*   _forbreak_n:                                                  */
4771 /*-----------------------------------------------------------------*/
4772 ast *
4773 createFor (symbol * trueLabel, symbol * continueLabel,
4774            symbol * falseLabel, symbol * condLabel,
4775            ast * initExpr, ast * condExpr, ast * loopExpr,
4776            ast * forBody)
4777 {
4778   ast *forTree;
4779
4780   /* if loopexpression not present then we can generate it */
4781   /* the same way as a while */
4782   if (!loopExpr)
4783     return newNode (NULLOP, initExpr,
4784                     createWhile (trueLabel, continueLabel,
4785                                  falseLabel, condExpr, forBody));
4786   /* vanilla for statement */
4787   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4788
4789   if (condExpr && !IS_IFX (condExpr))
4790     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4791
4792
4793   /* attach condition label to condition */
4794   condExpr = createLabel (condLabel, condExpr);
4795
4796   /* attach body label to body */
4797   forBody = createLabel (trueLabel, forBody);
4798
4799   /* attach continue to forLoop expression & attach */
4800   /* goto the forcond @ and of loopExpression       */
4801   loopExpr = createLabel (continueLabel,
4802                           newNode (NULLOP,
4803                                    loopExpr,
4804                                    newNode (GOTO,
4805                                        newAst_VALUE (symbolVal (condLabel)),
4806                                             NULL)));
4807   /* now start putting them together */
4808   forTree = newNode (NULLOP, initExpr, condExpr);
4809   forTree = newNode (NULLOP, forTree, forBody);
4810   forTree = newNode (NULLOP, forTree, loopExpr);
4811   /* finally add the break label */
4812   forTree = newNode (NULLOP, forTree,
4813                      createLabel (falseLabel, NULL));
4814   return forTree;
4815 }
4816
4817 /*-----------------------------------------------------------------*/
4818 /* createWhile - creates parse tree for while statement            */
4819 /*               the while statement will be created as follows    */
4820 /*                                                                 */
4821 /*      _while_continue_n:                                         */
4822 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4823 /*                                 |                               */
4824 /*                                 +-> falseLabel -> _while_break_n */
4825 /*      _while_body_n:                                             */
4826 /*            statements                                           */
4827 /*            goto _while_continue_n                               */
4828 /*      _while_break_n:                                            */
4829 /*-----------------------------------------------------------------*/
4830 ast *
4831 createWhile (symbol * trueLabel, symbol * continueLabel,
4832              symbol * falseLabel, ast * condExpr, ast * whileBody)
4833 {
4834   ast *whileTree;
4835
4836   /* put the continue label */
4837   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4838   condExpr = createLabel (continueLabel, condExpr);
4839   condExpr->lineno = 0;
4840
4841   /* put the body label in front of the body */
4842   whileBody = createLabel (trueLabel, whileBody);
4843   whileBody->lineno = 0;
4844   /* put a jump to continue at the end of the body */
4845   /* and put break label at the end of the body */
4846   whileBody = newNode (NULLOP,
4847                        whileBody,
4848                        newNode (GOTO,
4849                                 newAst_VALUE (symbolVal (continueLabel)),
4850                                 createLabel (falseLabel, NULL)));
4851
4852   /* put it all together */
4853   if (IS_IFX (condExpr))
4854     whileTree = condExpr;
4855   else
4856     {
4857       whileTree = newNode (IFX, condExpr, NULL);
4858       /* put the true & false labels in place */
4859       whileTree->trueLabel = trueLabel;
4860       whileTree->falseLabel = falseLabel;
4861     }
4862
4863   return newNode (NULLOP, whileTree, whileBody);
4864 }
4865
4866 /*-----------------------------------------------------------------*/
4867 /* optimizeGetHbit - get highest order bit of the expression       */
4868 /*-----------------------------------------------------------------*/
4869 ast *
4870 optimizeGetHbit (ast * tree)
4871 {
4872   int i, j;
4873   /* if this is not a bit and */
4874   if (!IS_BITAND (tree))
4875     return tree;
4876
4877   /* will look for tree of the form
4878      ( expr >> ((sizeof expr) -1) ) & 1 */
4879   if (!IS_AST_LIT_VALUE (tree->right))
4880     return tree;
4881
4882   if (AST_LIT_VALUE (tree->right) != 1)
4883     return tree;
4884
4885   if (!IS_RIGHT_OP (tree->left))
4886     return tree;
4887
4888   if (!IS_AST_LIT_VALUE (tree->left->right))
4889     return tree;
4890
4891   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4892       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4893     return tree;
4894       
4895   /* make sure the port supports GETHBIT */
4896   if (port->hasExtBitOp
4897       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4898     return tree;
4899
4900   return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_TYPE_NONE);
4901
4902 }
4903
4904 /*-----------------------------------------------------------------*/
4905 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4906 /*-----------------------------------------------------------------*/
4907 ast *
4908 optimizeRRCRLC (ast * root)
4909 {
4910   /* will look for trees of the form
4911      (?expr << 1) | (?expr >> 7) or
4912      (?expr >> 7) | (?expr << 1) will make that
4913      into a RLC : operation ..
4914      Will also look for
4915      (?expr >> 1) | (?expr << 7) or
4916      (?expr << 7) | (?expr >> 1) will make that
4917      into a RRC operation
4918      note : by 7 I mean (number of bits required to hold the
4919      variable -1 ) */
4920   /* if the root operations is not a | operation the not */
4921   if (!IS_BITOR (root))
4922     return root;
4923
4924   /* I have to think of a better way to match patterns this sucks */
4925   /* that aside let start looking for the first case : I use a the
4926      negative check a lot to improve the efficiency */
4927   /* (?expr << 1) | (?expr >> 7) */
4928   if (IS_LEFT_OP (root->left) &&
4929       IS_RIGHT_OP (root->right))
4930     {
4931
4932       if (!SPEC_USIGN (TETYPE (root->left->left)))
4933         return root;
4934
4935       if (!IS_AST_LIT_VALUE (root->left->right) ||
4936           !IS_AST_LIT_VALUE (root->right->right))
4937         goto tryNext0;
4938
4939       /* make sure it is the same expression */
4940       if (!isAstEqual (root->left->left,
4941                        root->right->left))
4942         goto tryNext0;
4943
4944       if (AST_LIT_VALUE (root->left->right) != 1)
4945         goto tryNext0;
4946
4947       if (AST_LIT_VALUE (root->right->right) !=
4948           (getSize (TTYPE (root->left->left)) * 8 - 1))
4949         goto tryNext0;
4950
4951       /* make sure the port supports RLC */
4952       if (port->hasExtBitOp
4953           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4954         return root;
4955
4956       /* whew got the first case : create the AST */
4957       return newNode (RLC, root->left->left, NULL);
4958     }
4959
4960 tryNext0:
4961   /* check for second case */
4962   /* (?expr >> 7) | (?expr << 1) */
4963   if (IS_LEFT_OP (root->right) &&
4964       IS_RIGHT_OP (root->left))
4965     {
4966
4967       if (!SPEC_USIGN (TETYPE (root->left->left)))
4968         return root;
4969
4970       if (!IS_AST_LIT_VALUE (root->left->right) ||
4971           !IS_AST_LIT_VALUE (root->right->right))
4972         goto tryNext1;
4973
4974       /* make sure it is the same symbol */
4975       if (!isAstEqual (root->left->left,
4976                        root->right->left))
4977         goto tryNext1;
4978
4979       if (AST_LIT_VALUE (root->right->right) != 1)
4980         goto tryNext1;
4981
4982       if (AST_LIT_VALUE (root->left->right) !=
4983           (getSize (TTYPE (root->left->left)) * 8 - 1))
4984         goto tryNext1;
4985
4986       /* make sure the port supports RLC */
4987       if (port->hasExtBitOp
4988           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4989         return root;
4990
4991       /* whew got the first case : create the AST */
4992       return newNode (RLC, root->left->left, NULL);
4993
4994     }
4995
4996 tryNext1:
4997   /* third case for RRC */
4998   /*  (?symbol >> 1) | (?symbol << 7) */
4999   if (IS_LEFT_OP (root->right) &&
5000       IS_RIGHT_OP (root->left))
5001     {
5002
5003       if (!SPEC_USIGN (TETYPE (root->left->left)))
5004         return root;
5005
5006       if (!IS_AST_LIT_VALUE (root->left->right) ||
5007           !IS_AST_LIT_VALUE (root->right->right))
5008         goto tryNext2;
5009
5010       /* make sure it is the same symbol */
5011       if (!isAstEqual (root->left->left,
5012                        root->right->left))
5013         goto tryNext2;
5014
5015       if (AST_LIT_VALUE (root->left->right) != 1)
5016         goto tryNext2;
5017
5018       if (AST_LIT_VALUE (root->right->right) !=
5019           (getSize (TTYPE (root->left->left)) * 8 - 1))
5020         goto tryNext2;
5021
5022       /* make sure the port supports RRC */
5023       if (port->hasExtBitOp
5024           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5025         return root;
5026
5027       /* whew got the first case : create the AST */
5028       return newNode (RRC, root->left->left, NULL);
5029
5030     }
5031 tryNext2:
5032   /* fourth and last case for now */
5033   /* (?symbol << 7) | (?symbol >> 1) */
5034   if (IS_RIGHT_OP (root->right) &&
5035       IS_LEFT_OP (root->left))
5036     {
5037
5038       if (!SPEC_USIGN (TETYPE (root->left->left)))
5039         return root;
5040
5041       if (!IS_AST_LIT_VALUE (root->left->right) ||
5042           !IS_AST_LIT_VALUE (root->right->right))
5043         return root;
5044
5045       /* make sure it is the same symbol */
5046       if (!isAstEqual (root->left->left,
5047                        root->right->left))
5048         return root;
5049
5050       if (AST_LIT_VALUE (root->right->right) != 1)
5051         return root;
5052
5053       if (AST_LIT_VALUE (root->left->right) !=
5054           (getSize (TTYPE (root->left->left)) * 8 - 1))
5055         return root;
5056
5057       /* make sure the port supports RRC */
5058       if (port->hasExtBitOp
5059           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5060         return root;
5061
5062       /* whew got the first case : create the AST */
5063       return newNode (RRC, root->left->left, NULL);
5064
5065     }
5066
5067   /* not found return root */
5068   return root;
5069 }
5070
5071 /*-----------------------------------------------------------------*/
5072 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5073 /*-----------------------------------------------------------------*/
5074 ast *
5075 optimizeSWAP (ast * root)
5076 {
5077   /* will look for trees of the form
5078      (?expr << 4) | (?expr >> 4) or
5079      (?expr >> 4) | (?expr << 4) will make that
5080      into a SWAP : operation ..
5081      note : by 4 I mean (number of bits required to hold the
5082      variable /2 ) */
5083   /* if the root operations is not a | operation the not */
5084   if (!IS_BITOR (root))
5085     return root;
5086
5087   /* (?expr << 4) | (?expr >> 4) */
5088   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5089       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5090     {
5091
5092       if (!SPEC_USIGN (TETYPE (root->left->left)))
5093         return root;
5094
5095       if (!IS_AST_LIT_VALUE (root->left->right) ||
5096           !IS_AST_LIT_VALUE (root->right->right))
5097         return root;
5098
5099       /* make sure it is the same expression */
5100       if (!isAstEqual (root->left->left,
5101                        root->right->left))
5102         return root;
5103
5104       if (AST_LIT_VALUE (root->left->right) !=
5105           (getSize (TTYPE (root->left->left)) * 4))
5106         return root;
5107
5108       if (AST_LIT_VALUE (root->right->right) !=
5109           (getSize (TTYPE (root->left->left)) * 4))
5110         return root;
5111
5112       /* make sure the port supports SWAP */
5113       if (port->hasExtBitOp
5114           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5115         return root;
5116
5117       /* found it : create the AST */
5118       return newNode (SWAP, root->left->left, NULL);
5119     }
5120
5121
5122   /* not found return root */
5123   return root;
5124 }
5125
5126 /*-----------------------------------------------------------------*/
5127 /* optimizeCompare - otimizes compares for bit variables     */
5128 /*-----------------------------------------------------------------*/
5129 static ast *
5130 optimizeCompare (ast * root)
5131 {
5132   ast *optExpr = NULL;
5133   value *vleft;
5134   value *vright;
5135   unsigned int litValue;
5136
5137   /* if nothing then return nothing */
5138   if (!root)
5139     return NULL;
5140
5141   /* if not a compare op then do leaves */
5142   if (!IS_COMPARE_OP (root))
5143     {
5144       root->left = optimizeCompare (root->left);
5145       root->right = optimizeCompare (root->right);
5146       return root;
5147     }
5148
5149   /* if left & right are the same then depending
5150      of the operation do */
5151   if (isAstEqual (root->left, root->right))
5152     {
5153       switch (root->opval.op)
5154         {
5155         case '>':
5156         case '<':
5157         case NE_OP:
5158           optExpr = newAst_VALUE (constVal ("0"));
5159           break;
5160         case GE_OP:
5161         case LE_OP:
5162         case EQ_OP:
5163           optExpr = newAst_VALUE (constVal ("1"));
5164           break;
5165         }
5166
5167       return decorateType (optExpr, RESULT_TYPE_NONE);
5168     }
5169
5170   vleft = (root->left->type == EX_VALUE ?
5171            root->left->opval.val : NULL);
5172
5173   vright = (root->right->type == EX_VALUE ?
5174             root->right->opval.val : NULL);
5175
5176   /* if left is a BITVAR in BITSPACE */
5177   /* and right is a LITERAL then opt- */
5178   /* imize else do nothing       */
5179   if (vleft && vright &&
5180       IS_BITVAR (vleft->etype) &&
5181       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5182       IS_LITERAL (vright->etype))
5183     {
5184
5185       /* if right side > 1 then comparison may never succeed */
5186       if ((litValue = (int) floatFromVal (vright)) > 1)
5187         {
5188           werror (W_BAD_COMPARE);
5189           goto noOptimize;
5190         }
5191
5192       if (litValue)
5193         {
5194           switch (root->opval.op)
5195             {
5196             case '>':           /* bit value greater than 1 cannot be */
5197               werror (W_BAD_COMPARE);
5198               goto noOptimize;
5199               break;
5200
5201             case '<':           /* bit value < 1 means 0 */
5202             case NE_OP:
5203               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5204               break;
5205
5206             case LE_OP: /* bit value <= 1 means no check */
5207               optExpr = newAst_VALUE (vright);
5208               break;
5209
5210             case GE_OP: /* bit value >= 1 means only check for = */
5211             case EQ_OP:
5212               optExpr = newAst_VALUE (vleft);
5213               break;
5214             }
5215         }
5216       else
5217         {                       /* literal is zero */
5218           switch (root->opval.op)
5219             {
5220             case '<':           /* bit value < 0 cannot be */
5221               werror (W_BAD_COMPARE);
5222               goto noOptimize;
5223               break;
5224
5225             case '>':           /* bit value > 0 means 1 */
5226             case NE_OP:
5227               optExpr = newAst_VALUE (vleft);
5228               break;
5229
5230             case LE_OP: /* bit value <= 0 means no check */
5231             case GE_OP: /* bit value >= 0 means no check */
5232               werror (W_BAD_COMPARE);
5233               goto noOptimize;
5234               break;
5235
5236             case EQ_OP: /* bit == 0 means ! of bit */
5237               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5238               break;
5239             }
5240         }
5241       return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5242     }                           /* end-of-if of BITVAR */
5243
5244 noOptimize:
5245   return root;
5246 }
5247 /*-----------------------------------------------------------------*/
5248 /* addSymToBlock : adds the symbol to the first block we find      */
5249 /*-----------------------------------------------------------------*/
5250 void 
5251 addSymToBlock (symbol * sym, ast * tree)
5252 {
5253   /* reached end of tree or a leaf */
5254   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5255     return;
5256
5257   /* found a block */
5258   if (IS_AST_OP (tree) &&
5259       tree->opval.op == BLOCK)
5260     {
5261
5262       symbol *lsym = copySymbol (sym);
5263
5264       lsym->next = AST_VALUES (tree, sym);
5265       AST_VALUES (tree, sym) = lsym;
5266       return;
5267     }
5268
5269   addSymToBlock (sym, tree->left);
5270   addSymToBlock (sym, tree->right);
5271 }
5272
5273 /*-----------------------------------------------------------------*/
5274 /* processRegParms - do processing for register parameters         */
5275 /*-----------------------------------------------------------------*/
5276 static void 
5277 processRegParms (value * args, ast * body)
5278 {
5279   while (args)
5280     {
5281       if (IS_REGPARM (args->etype))
5282         addSymToBlock (args->sym, body);
5283       args = args->next;
5284     }
5285 }
5286
5287 /*-----------------------------------------------------------------*/
5288 /* resetParmKey - resets the operandkeys for the symbols           */
5289 /*-----------------------------------------------------------------*/
5290 DEFSETFUNC (resetParmKey)
5291 {
5292   symbol *sym = item;
5293
5294   sym->key = 0;
5295   sym->defs = NULL;
5296   sym->uses = NULL;
5297   sym->remat = 0;
5298   return 1;
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* createFunction - This is the key node that calls the iCode for  */
5303 /*                  generating the code for a function. Note code  */
5304 /*                  is generated function by function, later when  */
5305 /*                  add inter-procedural analysis this will change */
5306 /*-----------------------------------------------------------------*/
5307 ast *
5308 createFunction (symbol * name, ast * body)
5309 {
5310   ast *ex;
5311   symbol *csym;
5312   int stack = 0;
5313   sym_link *fetype;
5314   iCode *piCode = NULL;
5315
5316   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
5317     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
5318
5319   /* if check function return 0 then some problem */
5320   if (checkFunction (name, NULL) == 0)
5321     return NULL;
5322
5323   /* create a dummy block if none exists */
5324   if (!body)
5325     body = newNode (BLOCK, NULL, NULL);
5326
5327   noLineno++;
5328
5329   /* check if the function name already in the symbol table */
5330   if ((csym = findSym (SymbolTab, NULL, name->name)))
5331     {
5332       name = csym;
5333       /* special case for compiler defined functions
5334          we need to add the name to the publics list : this
5335          actually means we are now compiling the compiler
5336          support routine */
5337       if (name->cdef)
5338         {
5339           addSet (&publics, name);
5340         }
5341     }
5342   else
5343     {
5344       addSymChain (name);
5345       allocVariables (name);
5346     }
5347   name->lastLine = mylineno;
5348   currFunc = name;
5349
5350   /* set the stack pointer */
5351   stackPtr  = -port->stack.direction * port->stack.call_overhead;
5352   xstackPtr = 0;
5353
5354   if (IFFUNC_ISISR (name->type))
5355     stackPtr -= port->stack.direction * port->stack.isr_overhead;
5356
5357   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
5358     {
5359       if (options.useXstack)
5360         xstackPtr -= port->stack.direction * port->stack.reent_overhead;
5361       else
5362         stackPtr  -= port->stack.direction * port->stack.reent_overhead;
5363     }
5364
5365   fetype = getSpec (name->type);        /* get the specifier for the function */
5366   /* if this is a reentrant function then */
5367   if (IFFUNC_ISREENT (name->type))
5368     reentrant++;
5369
5370   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
5371
5372   /* do processing for parameters that are passed in registers */
5373   processRegParms (FUNC_ARGS(name->type), body);
5374
5375   /* set the stack pointer */
5376   stackPtr = 0;
5377   xstackPtr = -1;
5378
5379   /* allocate & autoinit the block variables */
5380   processBlockVars (body, &stack, ALLOCATE);
5381
5382   /* save the stack information */
5383   if (options.useXstack)
5384     name->xstack = SPEC_STAK (fetype) = stack;
5385   else
5386     name->stack = SPEC_STAK (fetype) = stack;
5387
5388   /* name needs to be mangled */
5389   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
5390
5391   body = resolveSymbols (body); /* resolve the symbols */
5392   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
5393                                         
5394
5395   ex = newAst_VALUE (symbolVal (name)); /* create name */
5396   ex = newNode (FUNCTION, ex, body);
5397   ex->values.args = FUNC_ARGS(name->type);
5398   ex->decorated=1;
5399   if (options.dump_tree) PA(ex);
5400   if (fatalError)
5401     {
5402       werror (E_FUNC_NO_CODE, name->name);
5403       goto skipall;
5404     }
5405
5406   /* create the node & generate intermediate code */
5407   GcurMemmap = code;
5408   codeOutFile = code->oFile;
5409   piCode = iCodeFromAst (ex);
5410
5411   if (fatalError)
5412     {
5413       werror (E_FUNC_NO_CODE, name->name);
5414       goto skipall;
5415     }
5416
5417   eBBlockFromiCode (piCode);
5418
5419   /* if there are any statics then do them */
5420   if (staticAutos)
5421     {
5422       GcurMemmap = statsg;
5423       codeOutFile = statsg->oFile;
5424       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
5425       staticAutos = NULL;
5426     }
5427
5428 skipall:
5429
5430   /* dealloc the block variables */
5431   processBlockVars (body, &stack, DEALLOCATE);
5432   outputDebugStackSymbols();
5433   /* deallocate paramaters */
5434   deallocParms (FUNC_ARGS(name->type));
5435
5436   if (IFFUNC_ISREENT (name->type))
5437     reentrant--;
5438
5439   /* we are done freeup memory & cleanup */
5440   noLineno--;
5441   if (port->reset_labelKey) labelKey = 1;
5442   name->key = 0;
5443   FUNC_HASBODY(name->type) = 1;
5444   addSet (&operKeyReset, name);
5445   applyToSet (operKeyReset, resetParmKey);
5446
5447   if (options.debug)
5448     cdbStructBlock(1);
5449
5450   cleanUpLevel (LabelTab, 0);
5451   cleanUpBlock (StructTab, 1);
5452   cleanUpBlock (TypedefTab, 1);
5453
5454   xstack->syms = NULL;
5455   istack->syms = NULL;
5456   return NULL;
5457 }
5458
5459
5460 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5461 /*-----------------------------------------------------------------*/
5462 /* ast_print : prints the ast (for debugging purposes)             */
5463 /*-----------------------------------------------------------------*/
5464
5465 void ast_print (ast * tree, FILE *outfile, int indent)
5466 {
5467
5468         if (!tree) return ;
5469
5470         /* can print only decorated trees */
5471         if (!tree->decorated) return;
5472
5473         /* if any child is an error | this one is an error do nothing */
5474         if (tree->isError ||
5475             (tree->left && tree->left->isError) ||
5476             (tree->right && tree->right->isError)) {
5477                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5478         }
5479
5480
5481         /* print the line          */
5482         /* if not block & function */
5483         if (tree->type == EX_OP &&
5484             (tree->opval.op != FUNCTION &&
5485              tree->opval.op != BLOCK &&
5486              tree->opval.op != NULLOP)) {
5487         }
5488
5489         if (tree->opval.op == FUNCTION) {
5490                 int arg=0;
5491                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5492                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5493                         tree->left->opval.val->name, tree);
5494                 printTypeChain (tree->left->opval.val->type->next,outfile);
5495                 fprintf(outfile,") args (");
5496                 do {
5497                   if (arg) {
5498                     fprintf (outfile, ", ");
5499                   }
5500                   printTypeChain (args ? args->type : NULL, outfile);
5501                   arg++;
5502                   args= args ? args->next : NULL;
5503                 } while (args);
5504                 fprintf(outfile,")\n");
5505                 ast_print(tree->left,outfile,indent);
5506                 ast_print(tree->right,outfile,indent);
5507                 return ;
5508         }
5509         if (tree->opval.op == BLOCK) {
5510                 symbol *decls = tree->values.sym;
5511                 INDENT(indent,outfile);
5512                 fprintf(outfile,"{\n");
5513                 while (decls) {
5514                         INDENT(indent+2,outfile);
5515                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5516                                 decls->name, decls);
5517                         printTypeChain(decls->type,outfile);
5518                         fprintf(outfile,")\n");
5519
5520                         decls = decls->next;
5521                 }
5522                 ast_print(tree->right,outfile,indent+2);
5523                 INDENT(indent,outfile);
5524                 fprintf(outfile,"}\n");
5525                 return;
5526         }
5527         if (tree->opval.op == NULLOP) {
5528                 ast_print(tree->left,outfile,indent);
5529                 ast_print(tree->right,outfile,indent);
5530                 return ;
5531         }
5532         INDENT(indent,outfile);
5533
5534         /*------------------------------------------------------------------*/
5535         /*----------------------------*/
5536         /*   leaf has been reached    */
5537         /*----------------------------*/
5538         /* if this is of type value */
5539         /* just get the type        */
5540         if (tree->type == EX_VALUE) {
5541
5542                 if (IS_LITERAL (tree->opval.val->etype)) {
5543                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5544                         if (SPEC_USIGN (tree->opval.val->etype))
5545                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5546                         else
5547                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5548                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5549                                                       floatFromVal(tree->opval.val));
5550                 } else if (tree->opval.val->sym) {
5551                         /* if the undefined flag is set then give error message */
5552                         if (tree->opval.val->sym->undefined) {
5553                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5554                         } else {
5555                                 fprintf(outfile,"SYMBOL ");
5556                         }
5557                         fprintf(outfile,"(%s=%p)",
5558                                 tree->opval.val->sym->name,tree);
5559                 }
5560                 if (tree->ftype) {
5561                         fprintf(outfile," type (");
5562                         printTypeChain(tree->ftype,outfile);
5563                         fprintf(outfile,")\n");
5564                 } else {
5565                         fprintf(outfile,"\n");
5566                 }
5567                 return ;
5568         }
5569
5570         /* if type link for the case of cast */
5571         if (tree->type == EX_LINK) {
5572                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5573                 printTypeChain(tree->opval.lnk,outfile);
5574                 fprintf(outfile,")\n");
5575                 return ;
5576         }
5577
5578
5579         /* depending on type of operator do */
5580
5581         switch (tree->opval.op) {
5582                 /*------------------------------------------------------------------*/
5583                 /*----------------------------*/
5584                 /*        array node          */
5585                 /*----------------------------*/
5586         case '[':
5587                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5588                 printTypeChain(tree->ftype,outfile);
5589                 fprintf(outfile,")\n");
5590                 ast_print(tree->left,outfile,indent+2);
5591                 ast_print(tree->right,outfile,indent+2);
5592                 return;
5593
5594                 /*------------------------------------------------------------------*/
5595                 /*----------------------------*/
5596                 /*      struct/union          */
5597                 /*----------------------------*/
5598         case '.':
5599                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5600                 printTypeChain(tree->ftype,outfile);
5601                 fprintf(outfile,")\n");
5602                 ast_print(tree->left,outfile,indent+2);
5603                 ast_print(tree->right,outfile,indent+2);
5604                 return ;
5605
5606                 /*------------------------------------------------------------------*/
5607                 /*----------------------------*/
5608                 /*    struct/union pointer    */
5609                 /*----------------------------*/
5610         case PTR_OP:
5611                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5612                 printTypeChain(tree->ftype,outfile);
5613                 fprintf(outfile,")\n");
5614                 ast_print(tree->left,outfile,indent+2);
5615                 ast_print(tree->right,outfile,indent+2);
5616                 return ;
5617
5618                 /*------------------------------------------------------------------*/
5619                 /*----------------------------*/
5620                 /*  ++/-- operation           */
5621                 /*----------------------------*/
5622         case INC_OP:
5623                 if (tree->left)
5624                   fprintf(outfile,"post-");
5625                 else
5626                   fprintf(outfile,"pre-");
5627                 fprintf(outfile,"INC_OP (%p) type (",tree);
5628                 printTypeChain(tree->ftype,outfile);
5629                 fprintf(outfile,")\n");
5630                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5631                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5632                 return ;
5633
5634         case DEC_OP:
5635                 if (tree->left)
5636                   fprintf(outfile,"post-");
5637                 else
5638                   fprintf(outfile,"pre-");
5639                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5640                 printTypeChain(tree->ftype,outfile);
5641                 fprintf(outfile,")\n");
5642                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5643                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5644                 return ;
5645
5646                 /*------------------------------------------------------------------*/
5647                 /*----------------------------*/
5648                 /*  bitwise and               */
5649                 /*----------------------------*/
5650         case '&':
5651                 if (tree->right) {
5652                         fprintf(outfile,"& (%p) type (",tree);
5653                         printTypeChain(tree->ftype,outfile);
5654                         fprintf(outfile,")\n");
5655                         ast_print(tree->left,outfile,indent+2);
5656                         ast_print(tree->right,outfile,indent+2);
5657                 } else {
5658                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5659                         printTypeChain(tree->ftype,outfile);
5660                         fprintf(outfile,")\n");
5661                         ast_print(tree->left,outfile,indent+2);
5662                         ast_print(tree->right,outfile,indent+2);
5663                 }
5664                 return ;
5665                 /*----------------------------*/
5666                 /*  bitwise or                */
5667                 /*----------------------------*/
5668         case '|':
5669                 fprintf(outfile,"OR (%p) type (",tree);
5670                 printTypeChain(tree->ftype,outfile);
5671                 fprintf(outfile,")\n");
5672                 ast_print(tree->left,outfile,indent+2);
5673                 ast_print(tree->right,outfile,indent+2);
5674                 return ;
5675                 /*------------------------------------------------------------------*/
5676                 /*----------------------------*/
5677                 /*  bitwise xor               */
5678                 /*----------------------------*/
5679         case '^':
5680                 fprintf(outfile,"XOR (%p) type (",tree);
5681                 printTypeChain(tree->ftype,outfile);
5682                 fprintf(outfile,")\n");
5683                 ast_print(tree->left,outfile,indent+2);
5684                 ast_print(tree->right,outfile,indent+2);
5685                 return ;
5686
5687                 /*------------------------------------------------------------------*/
5688                 /*----------------------------*/
5689                 /*  division                  */
5690                 /*----------------------------*/
5691         case '/':
5692                 fprintf(outfile,"DIV (%p) type (",tree);
5693                 printTypeChain(tree->ftype,outfile);
5694                 fprintf(outfile,")\n");
5695                 ast_print(tree->left,outfile,indent+2);
5696                 ast_print(tree->right,outfile,indent+2);
5697                 return ;
5698                 /*------------------------------------------------------------------*/
5699                 /*----------------------------*/
5700                 /*            modulus         */
5701                 /*----------------------------*/
5702         case '%':
5703                 fprintf(outfile,"MOD (%p) type (",tree);
5704                 printTypeChain(tree->ftype,outfile);
5705                 fprintf(outfile,")\n");
5706                 ast_print(tree->left,outfile,indent+2);
5707                 ast_print(tree->right,outfile,indent+2);
5708                 return ;
5709
5710                 /*------------------------------------------------------------------*/
5711                 /*----------------------------*/
5712                 /*  address dereference       */
5713                 /*----------------------------*/
5714         case '*':                       /* can be unary  : if right is null then unary operation */
5715                 if (!tree->right) {
5716                         fprintf(outfile,"DEREF (%p) type (",tree);
5717                         printTypeChain(tree->ftype,outfile);
5718                         fprintf(outfile,")\n");
5719                         ast_print(tree->left,outfile,indent+2);
5720                         return ;
5721                 }                       
5722                 /*------------------------------------------------------------------*/
5723                 /*----------------------------*/
5724                 /*      multiplication        */
5725                 /*----------------------------*/                
5726                 fprintf(outfile,"MULT (%p) type (",tree);
5727                 printTypeChain(tree->ftype,outfile);
5728                 fprintf(outfile,")\n");
5729                 ast_print(tree->left,outfile,indent+2);
5730                 ast_print(tree->right,outfile,indent+2);
5731                 return ;
5732
5733
5734                 /*------------------------------------------------------------------*/
5735                 /*----------------------------*/
5736                 /*    unary '+' operator      */
5737                 /*----------------------------*/
5738         case '+':
5739                 /* if unary plus */
5740                 if (!tree->right) {
5741                         fprintf(outfile,"UPLUS (%p) type (",tree);
5742                         printTypeChain(tree->ftype,outfile);
5743                         fprintf(outfile,")\n");
5744                         ast_print(tree->left,outfile,indent+2);
5745                 } else {
5746                         /*------------------------------------------------------------------*/
5747                         /*----------------------------*/
5748                         /*      addition              */
5749                         /*----------------------------*/
5750                         fprintf(outfile,"ADD (%p) type (",tree);
5751                         printTypeChain(tree->ftype,outfile);
5752                         fprintf(outfile,")\n");
5753                         ast_print(tree->left,outfile,indent+2);
5754                         ast_print(tree->right,outfile,indent+2);
5755                 }
5756                 return;
5757                 /*------------------------------------------------------------------*/
5758                 /*----------------------------*/
5759                 /*      unary '-'             */
5760                 /*----------------------------*/
5761         case '-':                       /* can be unary   */
5762                 if (!tree->right) {
5763                         fprintf(outfile,"UMINUS (%p) type (",tree);
5764                         printTypeChain(tree->ftype,outfile);
5765                         fprintf(outfile,")\n");
5766                         ast_print(tree->left,outfile,indent+2);
5767                 } else {
5768                         /*------------------------------------------------------------------*/
5769                         /*----------------------------*/
5770                         /*      subtraction           */
5771                         /*----------------------------*/
5772                         fprintf(outfile,"SUB (%p) type (",tree);
5773                         printTypeChain(tree->ftype,outfile);
5774                         fprintf(outfile,")\n");
5775                         ast_print(tree->left,outfile,indent+2);
5776                         ast_print(tree->right,outfile,indent+2);
5777                 }
5778                 return;
5779                 /*------------------------------------------------------------------*/
5780                 /*----------------------------*/
5781                 /*    compliment              */
5782                 /*----------------------------*/
5783         case '~':
5784                 fprintf(outfile,"COMPL (%p) type (",tree);
5785                 printTypeChain(tree->ftype,outfile);
5786                 fprintf(outfile,")\n");
5787                 ast_print(tree->left,outfile,indent+2);
5788                 return ;
5789                 /*------------------------------------------------------------------*/
5790                 /*----------------------------*/
5791                 /*           not              */
5792                 /*----------------------------*/
5793         case '!':
5794                 fprintf(outfile,"NOT (%p) type (",tree);
5795                 printTypeChain(tree->ftype,outfile);
5796                 fprintf(outfile,")\n");
5797                 ast_print(tree->left,outfile,indent+2);
5798                 return ;
5799                 /*------------------------------------------------------------------*/
5800                 /*----------------------------*/
5801                 /*           shift            */
5802                 /*----------------------------*/
5803         case RRC:
5804                 fprintf(outfile,"RRC (%p) type (",tree);
5805                 printTypeChain(tree->ftype,outfile);
5806                 fprintf(outfile,")\n");
5807                 ast_print(tree->left,outfile,indent+2);
5808                 return ;
5809
5810         case RLC:
5811                 fprintf(outfile,"RLC (%p) type (",tree);
5812                 printTypeChain(tree->ftype,outfile);
5813                 fprintf(outfile,")\n");
5814                 ast_print(tree->left,outfile,indent+2);
5815                 return ;
5816         case SWAP:
5817                 fprintf(outfile,"SWAP (%p) type (",tree);
5818                 printTypeChain(tree->ftype,outfile);
5819                 fprintf(outfile,")\n");
5820                 ast_print(tree->left,outfile,indent+2);
5821                 return ;
5822         case GETHBIT:
5823                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5824                 printTypeChain(tree->ftype,outfile);
5825                 fprintf(outfile,")\n");
5826                 ast_print(tree->left,outfile,indent+2);
5827                 return ;
5828         case LEFT_OP:
5829                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5830                 printTypeChain(tree->ftype,outfile);
5831                 fprintf(outfile,")\n");
5832                 ast_print(tree->left,outfile,indent+2);
5833                 ast_print(tree->right,outfile,indent+2);
5834                 return ;
5835         case RIGHT_OP:
5836                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5837                 printTypeChain(tree->ftype,outfile);
5838                 fprintf(outfile,")\n");
5839                 ast_print(tree->left,outfile,indent+2);
5840                 ast_print(tree->right,outfile,indent+2);
5841                 return ;
5842                 /*------------------------------------------------------------------*/
5843                 /*----------------------------*/
5844                 /*         casting            */
5845                 /*----------------------------*/
5846         case CAST:                      /* change the type   */
5847                 fprintf(outfile,"CAST (%p) from type (",tree);
5848                 printTypeChain(tree->right->ftype,outfile);
5849                 fprintf(outfile,") to type (");
5850                 printTypeChain(tree->ftype,outfile);
5851                 fprintf(outfile,")\n");
5852                 ast_print(tree->right,outfile,indent+2);
5853                 return ;
5854                 
5855         case AND_OP:
5856                 fprintf(outfile,"ANDAND (%p) type (",tree);
5857                 printTypeChain(tree->ftype,outfile);
5858                 fprintf(outfile,")\n");
5859                 ast_print(tree->left,outfile,indent+2);
5860                 ast_print(tree->right,outfile,indent+2);
5861                 return ;
5862         case OR_OP:
5863                 fprintf(outfile,"OROR (%p) type (",tree);
5864                 printTypeChain(tree->ftype,outfile);
5865                 fprintf(outfile,")\n");
5866                 ast_print(tree->left,outfile,indent+2);
5867                 ast_print(tree->right,outfile,indent+2);
5868                 return ;
5869                 
5870                 /*------------------------------------------------------------------*/
5871                 /*----------------------------*/
5872                 /*     comparison operators   */
5873                 /*----------------------------*/
5874         case '>':
5875                 fprintf(outfile,"GT(>) (%p) type (",tree);
5876                 printTypeChain(tree->ftype,outfile);
5877                 fprintf(outfile,")\n");
5878                 ast_print(tree->left,outfile,indent+2);
5879                 ast_print(tree->right,outfile,indent+2);
5880                 return ;
5881         case '<':
5882                 fprintf(outfile,"LT(<) (%p) type (",tree);
5883                 printTypeChain(tree->ftype,outfile);
5884                 fprintf(outfile,")\n");
5885                 ast_print(tree->left,outfile,indent+2);
5886                 ast_print(tree->right,outfile,indent+2);
5887                 return ;
5888         case LE_OP:
5889                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5890                 printTypeChain(tree->ftype,outfile);
5891                 fprintf(outfile,")\n");
5892                 ast_print(tree->left,outfile,indent+2);
5893                 ast_print(tree->right,outfile,indent+2);
5894                 return ;
5895         case GE_OP:
5896                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5897                 printTypeChain(tree->ftype,outfile);
5898                 fprintf(outfile,")\n");
5899                 ast_print(tree->left,outfile,indent+2);
5900                 ast_print(tree->right,outfile,indent+2);
5901                 return ;
5902         case EQ_OP:
5903                 fprintf(outfile,"EQ(==) (%p) type (",tree);
5904                 printTypeChain(tree->ftype,outfile);
5905                 fprintf(outfile,")\n");
5906                 ast_print(tree->left,outfile,indent+2);
5907                 ast_print(tree->right,outfile,indent+2);
5908                 return ;
5909         case NE_OP:
5910                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5911                 printTypeChain(tree->ftype,outfile);
5912                 fprintf(outfile,")\n");
5913                 ast_print(tree->left,outfile,indent+2);
5914                 ast_print(tree->right,outfile,indent+2);
5915                 /*------------------------------------------------------------------*/
5916                 /*----------------------------*/
5917                 /*             sizeof         */
5918                 /*----------------------------*/
5919         case SIZEOF:            /* evaluate wihout code generation */
5920                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5921                 return ;
5922
5923                 /*------------------------------------------------------------------*/
5924                 /*----------------------------*/
5925                 /* conditional operator  '?'  */
5926                 /*----------------------------*/
5927         case '?':
5928                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5929                 printTypeChain(tree->ftype,outfile);
5930                 fprintf(outfile,")\n");
5931                 ast_print(tree->left,outfile,indent+2);
5932                 ast_print(tree->right,outfile,indent+2);
5933                 return;
5934
5935         case ':':
5936                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5937                 printTypeChain(tree->ftype,outfile);
5938                 fprintf(outfile,")\n");
5939                 ast_print(tree->left,outfile,indent+2);
5940                 ast_print(tree->right,outfile,indent+2);
5941                 return ;
5942
5943                 /*------------------------------------------------------------------*/
5944                 /*----------------------------*/
5945                 /*    assignment operators    */
5946                 /*----------------------------*/
5947         case MUL_ASSIGN:
5948                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5949                 printTypeChain(tree->ftype,outfile);
5950                 fprintf(outfile,")\n");
5951                 ast_print(tree->left,outfile,indent+2);
5952                 ast_print(tree->right,outfile,indent+2);
5953                 return;
5954         case DIV_ASSIGN:
5955                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5956                 printTypeChain(tree->ftype,outfile);
5957                 fprintf(outfile,")\n");
5958                 ast_print(tree->left,outfile,indent+2);
5959                 ast_print(tree->right,outfile,indent+2);
5960                 return;
5961         case AND_ASSIGN:
5962                 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
5963                 printTypeChain(tree->ftype,outfile);
5964                 fprintf(outfile,")\n");
5965                 ast_print(tree->left,outfile,indent+2);
5966                 ast_print(tree->right,outfile,indent+2);
5967                 return;
5968         case OR_ASSIGN:
5969                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5970                 printTypeChain(tree->ftype,outfile);
5971                 fprintf(outfile,")\n");
5972                 ast_print(tree->left,outfile,indent+2);
5973                 ast_print(tree->right,outfile,indent+2);
5974                 return;
5975         case XOR_ASSIGN:
5976                 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
5977                 printTypeChain(tree->ftype,outfile);
5978                 fprintf(outfile,")\n");
5979                 ast_print(tree->left,outfile,indent+2);
5980                 ast_print(tree->right,outfile,indent+2);
5981                 return;
5982         case RIGHT_ASSIGN:
5983                 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
5984                 printTypeChain(tree->ftype,outfile);
5985                 fprintf(outfile,")\n");
5986                 ast_print(tree->left,outfile,indent+2);
5987                 ast_print(tree->right,outfile,indent+2);
5988                 return;
5989         case LEFT_ASSIGN:
5990                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5991                 printTypeChain(tree->ftype,outfile);
5992                 fprintf(outfile,")\n");
5993                 ast_print(tree->left,outfile,indent+2);
5994                 ast_print(tree->right,outfile,indent+2);
5995                 return;
5996                 /*------------------------------------------------------------------*/
5997                 /*----------------------------*/
5998                 /*    -= operator             */
5999                 /*----------------------------*/
6000         case SUB_ASSIGN:
6001                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
6002                 printTypeChain(tree->ftype,outfile);
6003                 fprintf(outfile,")\n");
6004                 ast_print(tree->left,outfile,indent+2);
6005                 ast_print(tree->right,outfile,indent+2);
6006                 return;
6007                 /*------------------------------------------------------------------*/
6008                 /*----------------------------*/
6009                 /*          += operator       */
6010                 /*----------------------------*/
6011         case ADD_ASSIGN:
6012                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
6013                 printTypeChain(tree->ftype,outfile);
6014                 fprintf(outfile,")\n");
6015                 ast_print(tree->left,outfile,indent+2);
6016                 ast_print(tree->right,outfile,indent+2);
6017                 return;
6018                 /*------------------------------------------------------------------*/
6019                 /*----------------------------*/
6020                 /*      straight assignemnt   */
6021                 /*----------------------------*/
6022         case '=':
6023                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
6024                 printTypeChain(tree->ftype,outfile);
6025                 fprintf(outfile,")\n");
6026                 ast_print(tree->left,outfile,indent+2);
6027                 ast_print(tree->right,outfile,indent+2);
6028                 return;     
6029                 /*------------------------------------------------------------------*/
6030                 /*----------------------------*/
6031                 /*      comma operator        */
6032                 /*----------------------------*/
6033         case ',':
6034                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
6035                 printTypeChain(tree->ftype,outfile);
6036                 fprintf(outfile,")\n");
6037                 ast_print(tree->left,outfile,indent+2);
6038                 ast_print(tree->right,outfile,indent+2);
6039                 return;
6040                 /*------------------------------------------------------------------*/
6041                 /*----------------------------*/
6042                 /*       function call        */
6043                 /*----------------------------*/
6044         case CALL:
6045         case PCALL:
6046                 fprintf(outfile,"CALL (%p) type (",tree);
6047                 printTypeChain(tree->ftype,outfile);
6048                 fprintf(outfile,")\n");
6049                 ast_print(tree->left,outfile,indent+2);
6050                 ast_print(tree->right,outfile,indent+2);
6051                 return;
6052         case PARAM:
6053                 fprintf(outfile,"PARMS\n");
6054                 ast_print(tree->left,outfile,indent+2);
6055                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
6056                         ast_print(tree->right,outfile,indent+2);
6057                 }
6058                 return ;
6059                 /*------------------------------------------------------------------*/
6060                 /*----------------------------*/
6061                 /*     return statement       */
6062                 /*----------------------------*/
6063         case RETURN:
6064                 fprintf(outfile,"RETURN (%p) type (",tree);
6065                 if (tree->right) {
6066                     printTypeChain(tree->right->ftype,outfile);
6067                 }
6068                 fprintf(outfile,")\n");
6069                 ast_print(tree->right,outfile,indent+2);
6070                 return ;
6071                 /*------------------------------------------------------------------*/
6072                 /*----------------------------*/
6073                 /*     label statement        */
6074                 /*----------------------------*/
6075         case LABEL :
6076                 fprintf(outfile,"LABEL (%p)\n",tree);
6077                 ast_print(tree->left,outfile,indent+2);
6078                 ast_print(tree->right,outfile,indent);
6079                 return;
6080                 /*------------------------------------------------------------------*/
6081                 /*----------------------------*/
6082                 /*     switch statement       */
6083                 /*----------------------------*/
6084         case SWITCH:
6085                 {
6086                         value *val;
6087                         fprintf(outfile,"SWITCH (%p) ",tree);
6088                         ast_print(tree->left,outfile,0);
6089                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
6090                                 INDENT(indent+2,outfile);
6091                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
6092                                         (int) floatFromVal(val),
6093                                         tree->values.switchVals.swNum,
6094                                         (int) floatFromVal(val));
6095                         }
6096                         ast_print(tree->right,outfile,indent);
6097                 }
6098                 return ;
6099                 /*------------------------------------------------------------------*/
6100                 /*----------------------------*/
6101                 /* ifx Statement              */
6102                 /*----------------------------*/
6103         case IFX:
6104                 fprintf(outfile,"IF (%p) \n",tree);
6105                 ast_print(tree->left,outfile,indent+2);
6106                 if (tree->trueLabel) {
6107                         INDENT(indent+2,outfile);
6108                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
6109                 }
6110                 if (tree->falseLabel) {
6111                         INDENT(indent+2,outfile);
6112                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
6113                 }
6114                 ast_print(tree->right,outfile,indent+2);
6115                 return ;
6116                 /*----------------------------*/
6117                 /* goto Statement              */
6118                 /*----------------------------*/
6119         case GOTO:
6120                 fprintf(outfile,"GOTO (%p) \n",tree);
6121                 ast_print(tree->left,outfile,indent+2);
6122                 fprintf(outfile,"\n");
6123                 return ;
6124                 /*------------------------------------------------------------------*/
6125                 /*----------------------------*/
6126                 /* for Statement              */
6127                 /*----------------------------*/
6128         case FOR:
6129                 fprintf(outfile,"FOR (%p) \n",tree);
6130                 if (AST_FOR( tree, initExpr)) {
6131                         INDENT(indent+2,outfile);
6132                         fprintf(outfile,"INIT EXPR ");
6133                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
6134                 }
6135                 if (AST_FOR( tree, condExpr)) {
6136                         INDENT(indent+2,outfile);
6137                         fprintf(outfile,"COND EXPR ");
6138                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
6139                 }
6140                 if (AST_FOR( tree, loopExpr)) {
6141                         INDENT(indent+2,outfile);
6142                         fprintf(outfile,"LOOP EXPR ");
6143                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
6144                 }
6145                 fprintf(outfile,"FOR LOOP BODY \n");
6146                 ast_print(tree->left,outfile,indent+2);
6147                 return ;
6148         case CRITICAL:
6149                 fprintf(outfile,"CRITICAL (%p) \n",tree);
6150                 ast_print(tree->left,outfile,indent+2);
6151         default:
6152             return ;
6153         }
6154 }
6155
6156 void PA(ast *t)
6157 {
6158         ast_print(t,stdout,0);
6159 }
6160
6161
6162
6163 /*-----------------------------------------------------------------*/
6164 /* astErrors : returns non-zero if errors present in tree          */
6165 /*-----------------------------------------------------------------*/
6166 int astErrors(ast *t)
6167 {
6168   int errors=0;
6169   
6170   if (t)
6171     {
6172       if (t->isError)
6173         errors++;
6174   
6175       if (t->type == EX_VALUE
6176           && t->opval.val->sym
6177           && t->opval.val->sym->undefined)
6178         errors++;
6179
6180       errors += astErrors(t->left);
6181       errors += astErrors(t->right);
6182     }
6183     
6184   return errors;
6185 }