* src/SDCCast.c (decorateType): fixed bug 1124787
[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
1537   /* check loop expression is of the form <sym>++ */
1538   if (!IS_AST_OP (loopExpr))
1539     return FALSE;
1540
1541   /* check if <sym> ++ */
1542   if (loopExpr->opval.op == INC_OP)
1543     {
1544
1545       if (loopExpr->left)
1546         {
1547           /* pre */
1548           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1549               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1550             return TRUE;
1551
1552         }
1553       else
1554         {
1555           /* post */
1556           if (IS_AST_SYM_VALUE (loopExpr->right) &&
1557               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1558             return TRUE;
1559         }
1560
1561     }
1562   else
1563     {
1564       /* check for += */
1565       if (loopExpr->opval.op == ADD_ASSIGN)
1566         {
1567
1568           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1569               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1570               IS_AST_LIT_VALUE (loopExpr->right) &&
1571               (int) AST_LIT_VALUE (loopExpr->right) != 1)
1572             return TRUE;
1573         }
1574     }
1575
1576   return FALSE;
1577 }
1578
1579 /*-----------------------------------------------------------------*/
1580 /* astHasVolatile - returns true if ast contains any volatile      */
1581 /*-----------------------------------------------------------------*/
1582 bool 
1583 astHasVolatile (ast * tree)
1584 {
1585   if (!tree)
1586     return FALSE;
1587
1588   if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1589     return TRUE;
1590
1591   if (IS_AST_OP (tree))
1592     return astHasVolatile (tree->left) ||
1593       astHasVolatile (tree->right);
1594   else
1595     return FALSE;
1596 }
1597
1598 /*-----------------------------------------------------------------*/
1599 /* astHasPointer - return true if the ast contains any ptr variable */
1600 /*-----------------------------------------------------------------*/
1601 bool 
1602 astHasPointer (ast * tree)
1603 {
1604   if (!tree)
1605     return FALSE;
1606
1607   if (IS_AST_LINK (tree))
1608     return TRUE;
1609
1610   /* if we hit an array expression then check
1611      only the left side */
1612   if (IS_AST_OP (tree) && tree->opval.op == '[')
1613     return astHasPointer (tree->left);
1614
1615   if (IS_AST_VALUE (tree))
1616     return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1617
1618   return astHasPointer (tree->left) ||
1619     astHasPointer (tree->right);
1620
1621 }
1622
1623 /*-----------------------------------------------------------------*/
1624 /* astHasSymbol - return true if the ast has the given symbol      */
1625 /*-----------------------------------------------------------------*/
1626 bool 
1627 astHasSymbol (ast * tree, symbol * sym)
1628 {
1629   if (!tree || IS_AST_LINK (tree))
1630     return FALSE;
1631
1632   if (IS_AST_VALUE (tree))
1633     {
1634       if (IS_AST_SYM_VALUE (tree))
1635         return isSymbolEqual (AST_SYMBOL (tree), sym);
1636       else
1637         return FALSE;
1638     }
1639
1640   return astHasSymbol (tree->left, sym) ||
1641     astHasSymbol (tree->right, sym);
1642 }
1643
1644 /*-----------------------------------------------------------------*/
1645 /* astHasDeref - return true if the ast has an indirect access     */
1646 /*-----------------------------------------------------------------*/
1647 static bool 
1648 astHasDeref (ast * tree)
1649 {
1650   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1651     return FALSE;
1652
1653   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1654   
1655   return astHasDeref (tree->left) || astHasDeref (tree->right);
1656 }
1657
1658 /*-----------------------------------------------------------------*/
1659 /* isConformingBody - the loop body has to conform to a set of rules */
1660 /* for the loop to be considered reversible read on for rules      */
1661 /*-----------------------------------------------------------------*/
1662 bool 
1663 isConformingBody (ast * pbody, symbol * sym, ast * body)
1664 {
1665
1666   /* we are going to do a pre-order traversal of the
1667      tree && check for the following conditions. (essentially
1668      a set of very shallow tests )
1669      a) the sym passed does not participate in
1670      any arithmetic operation
1671      b) There are no function calls
1672      c) all jumps are within the body
1673      d) address of loop control variable not taken
1674      e) if an assignment has a pointer on the
1675      left hand side make sure right does not have
1676      loop control variable */
1677
1678   /* if we reach the end or a leaf then true */
1679   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1680     return TRUE;
1681   
1682   /* if anything else is "volatile" */
1683   if (IS_VOLATILE (TETYPE (pbody)))
1684     return FALSE;
1685
1686   /* we will walk the body in a pre-order traversal for
1687      efficiency sake */
1688   switch (pbody->opval.op)
1689     {
1690 /*------------------------------------------------------------------*/
1691     case '[':
1692       // if the loopvar is used as an index
1693       /* array op is commutative -- must check both left & right */
1694       if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1695         return FALSE;
1696       }
1697       return isConformingBody (pbody->right, sym, body)
1698               && isConformingBody (pbody->left, sym, body);
1699
1700 /*------------------------------------------------------------------*/
1701     case PTR_OP:
1702     case '.':
1703       return TRUE;
1704
1705 /*------------------------------------------------------------------*/
1706     case INC_OP:
1707     case DEC_OP:
1708
1709       /* sure we are not sym is not modified */
1710       if (pbody->left &&
1711           IS_AST_SYM_VALUE (pbody->left) &&
1712           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1713         return FALSE;
1714
1715       if (pbody->right &&
1716           IS_AST_SYM_VALUE (pbody->right) &&
1717           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1718         return FALSE;
1719
1720       return TRUE;
1721
1722 /*------------------------------------------------------------------*/
1723
1724     case '*':                   /* can be unary  : if right is null then unary operation */
1725     case '+':
1726     case '-':
1727     case '&':
1728
1729       /* if right is NULL then unary operation  */
1730 /*------------------------------------------------------------------*/
1731 /*----------------------------*/
1732       /*  address of                */
1733 /*----------------------------*/
1734       if (!pbody->right)
1735         {
1736           if (IS_AST_SYM_VALUE (pbody->left) &&
1737               isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1738             return FALSE;
1739           else
1740             return isConformingBody (pbody->left, sym, body);
1741         }
1742       else
1743         {
1744           if (astHasSymbol (pbody->left, sym) ||
1745               astHasSymbol (pbody->right, sym))
1746             return FALSE;
1747         }
1748
1749
1750 /*------------------------------------------------------------------*/
1751     case '|':
1752     case '^':
1753     case '/':
1754     case '%':
1755     case LEFT_OP:
1756     case RIGHT_OP:
1757
1758       if (IS_AST_SYM_VALUE (pbody->left) &&
1759           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1760         return FALSE;
1761
1762       if (IS_AST_SYM_VALUE (pbody->right) &&
1763           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1764         return FALSE;
1765
1766       return isConformingBody (pbody->left, sym, body) &&
1767         isConformingBody (pbody->right, sym, body);
1768
1769     case '~':
1770     case '!':
1771     case RRC:
1772     case RLC:
1773     case GETHBIT:
1774     case SWAP:
1775       if (IS_AST_SYM_VALUE (pbody->left) &&
1776           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1777         return FALSE;
1778       return isConformingBody (pbody->left, sym, body);
1779
1780 /*------------------------------------------------------------------*/
1781
1782     case AND_OP:
1783     case OR_OP:
1784     case '>':
1785     case '<':
1786     case LE_OP:
1787     case GE_OP:
1788     case EQ_OP:
1789     case NE_OP:
1790     case '?':
1791     case ':':
1792     case SIZEOF:                /* evaluate wihout code generation */
1793
1794       if (IS_AST_SYM_VALUE (pbody->left) &&
1795           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1796         return FALSE;
1797
1798       if (IS_AST_SYM_VALUE (pbody->right) &&
1799           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1800         return FALSE;
1801
1802       return isConformingBody (pbody->left, sym, body) &&
1803         isConformingBody (pbody->right, sym, body);
1804
1805 /*------------------------------------------------------------------*/
1806     case '=':
1807
1808       /* if left has a pointer & right has loop
1809          control variable then we cannot */
1810       if (astHasPointer (pbody->left) &&
1811           astHasSymbol (pbody->right, sym))
1812         return FALSE;
1813       if (astHasVolatile (pbody->left))
1814         return FALSE;
1815
1816       if (IS_AST_SYM_VALUE (pbody->left)) {
1817         // if the loopvar has an assignment
1818         if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1819           return FALSE;
1820         // if the loopvar is used in another (maybe conditional) block
1821         if (astHasSymbol (pbody->right, sym) &&
1822             (pbody->level >= body->level)) {
1823           return FALSE;
1824         }
1825       }
1826
1827       if (astHasVolatile (pbody->left))
1828         return FALSE;
1829
1830       if (astHasDeref(pbody->right)) return FALSE;
1831
1832       return isConformingBody (pbody->left, sym, body) &&
1833         isConformingBody (pbody->right, sym, body);
1834
1835     case MUL_ASSIGN:
1836     case DIV_ASSIGN:
1837     case AND_ASSIGN:
1838     case OR_ASSIGN:
1839     case XOR_ASSIGN:
1840     case RIGHT_ASSIGN:
1841     case LEFT_ASSIGN:
1842     case SUB_ASSIGN:
1843     case ADD_ASSIGN:
1844       assert ("Parser should not have generated this\n");
1845
1846 /*------------------------------------------------------------------*/
1847 /*----------------------------*/
1848       /*      comma operator        */
1849 /*----------------------------*/
1850     case ',':
1851       return isConformingBody (pbody->left, sym, body) &&
1852         isConformingBody (pbody->right, sym, body);
1853
1854 /*------------------------------------------------------------------*/
1855 /*----------------------------*/
1856       /*       function call        */
1857 /*----------------------------*/
1858     case CALL:
1859         /* if local & not passed as paramater then ok */
1860         if (sym->level && !astHasSymbol(pbody->right,sym)) 
1861             return TRUE;
1862       return FALSE;
1863
1864 /*------------------------------------------------------------------*/
1865 /*----------------------------*/
1866       /*     return statement       */
1867 /*----------------------------*/
1868     case RETURN:
1869       return FALSE;
1870
1871     case GOTO:
1872       if (isLabelInAst (AST_SYMBOL (pbody->left), body))
1873         return TRUE;
1874       else
1875         return FALSE;
1876     case SWITCH:
1877       if (astHasSymbol (pbody->left, sym))
1878         return FALSE;
1879
1880     default:
1881       break;
1882     }
1883
1884   return isConformingBody (pbody->left, sym, body) &&
1885     isConformingBody (pbody->right, sym, body);
1886
1887
1888
1889 }
1890
1891 /*-----------------------------------------------------------------*/
1892 /* isLoopReversible - takes a for loop as input && returns true    */
1893 /* if the for loop is reversible. If yes will set the value of     */
1894 /* the loop control var & init value & termination value           */
1895 /*-----------------------------------------------------------------*/
1896 bool
1897 isLoopReversible (ast * loop, symbol ** loopCntrl,
1898                   ast ** init, ast ** end)
1899 {
1900   /* if option says don't do it then don't */
1901   if (optimize.noLoopReverse)
1902     return 0;
1903   /* there are several tests to determine this */
1904
1905   /* for loop has to be of the form
1906      for ( <sym> = <const1> ;
1907      [<sym> < <const2>]  ;
1908      [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
1909      forBody */
1910   if (!isLoopCountable (AST_FOR (loop, initExpr),
1911                         AST_FOR (loop, condExpr),
1912                         AST_FOR (loop, loopExpr),
1913                         loopCntrl, init, end))
1914     return 0;
1915
1916   /* now do some serious checking on the body of the loop
1917    */
1918
1919   return isConformingBody (loop->left, *loopCntrl, loop->left);
1920
1921 }
1922
1923 /*-----------------------------------------------------------------*/
1924 /* replLoopSym - replace the loop sym by loop sym -1               */
1925 /*-----------------------------------------------------------------*/
1926 static void 
1927 replLoopSym (ast * body, symbol * sym)
1928 {
1929   /* reached end */
1930   if (!body || IS_AST_LINK (body))
1931     return;
1932
1933   if (IS_AST_SYM_VALUE (body))
1934     {
1935
1936       if (isSymbolEqual (AST_SYMBOL (body), sym))
1937         {
1938
1939           body->type = EX_OP;
1940           body->opval.op = '-';
1941           body->left = newAst_VALUE (symbolVal (sym));
1942           body->right = newAst_VALUE (constVal ("1"));
1943
1944         }
1945
1946       return;
1947
1948     }
1949
1950   replLoopSym (body->left, sym);
1951   replLoopSym (body->right, sym);
1952
1953 }
1954
1955 /*-----------------------------------------------------------------*/
1956 /* reverseLoop - do the actual loop reversal                       */
1957 /*-----------------------------------------------------------------*/
1958 ast *
1959 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
1960 {
1961   ast *rloop;
1962
1963   /* create the following tree
1964      <sym> = loopCount ;
1965      for_continue:
1966      forbody
1967      <sym> -= 1;
1968      if (sym) goto for_continue ;
1969      <sym> = end */
1970
1971   /* put it together piece by piece */
1972   rloop = newNode (NULLOP,
1973                    createIf (newAst_VALUE (symbolVal (sym)),
1974                              newNode (GOTO,
1975                                       newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
1976                                       NULL), NULL),
1977                    newNode ('=',
1978                             newAst_VALUE (symbolVal (sym)),
1979                             end));
1980
1981   replLoopSym (loop->left, sym);
1982   setAstLineno (rloop, init->lineno);
1983
1984   rloop = newNode (NULLOP,
1985                    newNode ('=',
1986                             newAst_VALUE (symbolVal (sym)),
1987                             newNode ('-', end, init)),
1988                    createLabel (AST_FOR (loop, continueLabel),
1989                                 newNode (NULLOP,
1990                                          loop->left,
1991                                          newNode (NULLOP,
1992                                                   newNode (SUB_ASSIGN,
1993                                                            newAst_VALUE (symbolVal (sym)),
1994                                                            newAst_VALUE (constVal ("1"))),
1995                                                   rloop))));
1996
1997   rloop->lineno=init->lineno;
1998   return decorateType (rloop, RESULT_TYPE_NONE);
1999
2000 }
2001
2002 /*-----------------------------------------------------------------*/
2003 /* searchLitOp - search tree (*ops only) for an ast with literal */
2004 /*-----------------------------------------------------------------*/
2005 static ast *
2006 searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
2007 {
2008   ast *ret;
2009
2010   if (tree && optimize.global_cse)
2011     {
2012       /* is there a literal operand? */
2013       if (tree->right &&
2014           IS_AST_OP(tree->right) &&
2015           tree->right->right &&
2016           (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
2017         {
2018           if (IS_LITERAL (RTYPE (tree->right)) !=
2019               IS_LITERAL (LTYPE (tree->right)))
2020             {
2021               tree->right->decorated = 0;
2022               tree->decorated = 0;
2023               *parent = tree;
2024               return tree->right;
2025             }
2026           ret = searchLitOp (tree->right, parent, ops);
2027           if (ret)
2028             return ret;
2029         }
2030       if (tree->left &&
2031           IS_AST_OP(tree->left) &&
2032           tree->left->right &&
2033           (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
2034         {
2035           if (IS_LITERAL (RTYPE (tree->left)) !=
2036               IS_LITERAL (LTYPE (tree->left)))
2037             {
2038               tree->left->decorated = 0;
2039               tree->decorated = 0;
2040               *parent = tree;
2041               return tree->left;
2042             }
2043           ret = searchLitOp (tree->left, parent, ops);
2044           if (ret)
2045             return ret;
2046         }
2047     }
2048   return NULL;
2049 }
2050
2051 /*-----------------------------------------------------------------*/
2052 /* getResultFromType                                               */
2053 /*-----------------------------------------------------------------*/
2054 RESULT_TYPE
2055 getResultTypeFromType (sym_link *type)
2056 {
2057   /* type = getSpec (type); */
2058   if (IS_BIT (type))
2059     return RESULT_TYPE_BIT;
2060   if (IS_BITFIELD (type))
2061     {
2062       int blen = SPEC_BLEN (type);
2063       
2064       if (blen <= 1)
2065         return RESULT_TYPE_BIT;
2066       if (blen <= 8)
2067         return RESULT_TYPE_CHAR;
2068       return RESULT_TYPE_INT;
2069     }
2070   if (IS_CHAR (type))
2071     return RESULT_TYPE_CHAR;
2072   if (   IS_INT (type)
2073       && !IS_LONG (type))
2074     return RESULT_TYPE_INT;
2075   return RESULT_TYPE_OTHER;
2076 }
2077
2078 /*-----------------------------------------------------------------*/
2079 /* addCast - adds casts to a type specified by RESULT_TYPE         */
2080 /*-----------------------------------------------------------------*/
2081 static ast *
2082 addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
2083 {
2084   sym_link *newLink;
2085   bool upCasted = FALSE;
2086   
2087   switch (resultType)
2088     {
2089       case RESULT_TYPE_NONE:
2090         /* char: promote to int */
2091         if (!upcast ||
2092             getSize (tree->etype) >= INTSIZE)
2093           return tree;
2094         newLink = newIntLink();
2095         upCasted = TRUE;
2096         break;
2097       case RESULT_TYPE_CHAR:
2098         if (IS_CHAR (tree->etype) ||
2099             IS_FLOAT(tree->etype))
2100           return tree;
2101         newLink = newCharLink();
2102         break;
2103       case RESULT_TYPE_INT:
2104 #if 0
2105         if (getSize (tree->etype) > INTSIZE)
2106           {
2107             /* warn ("Loosing significant digits"); */
2108             return;
2109           }
2110 #endif
2111         /* char: promote to int */
2112         if (!upcast ||
2113             getSize (tree->etype) >= INTSIZE)
2114           return tree;
2115         newLink = newIntLink();
2116         upCasted = TRUE;
2117         break;
2118       case RESULT_TYPE_OTHER:
2119         if (!upcast)
2120           return tree;
2121         /* return type is long, float: promote char to int */
2122         if (getSize (tree->etype) >= INTSIZE)
2123           return tree;
2124         newLink = newIntLink();
2125         upCasted = TRUE;
2126         break;
2127       default:
2128         return tree;
2129     }
2130   tree->decorated = 0;
2131   tree = newNode (CAST, newAst_LINK (newLink), tree);
2132   tree->lineno = tree->right->lineno;
2133   /* keep unsigned type during cast to smaller type,
2134      but not when promoting from char to int */
2135   if (!upCasted)
2136     SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2137   return decorateType (tree, resultType);
2138 }
2139
2140 /*-----------------------------------------------------------------*/
2141 /* resultTypePropagate - decides if resultType can be propagated   */
2142 /*-----------------------------------------------------------------*/
2143 static RESULT_TYPE
2144 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2145 {
2146   switch (tree->opval.op)
2147     {
2148       case '=':
2149       case '?':
2150       case ':':
2151       case '|':
2152       case '^':
2153       case '~':
2154       case '*':
2155       case '+':
2156       case '-':
2157       case LABEL:
2158         return resultType;
2159       case '&':
2160         if (!tree->right)
2161           /* can be unary */
2162           return RESULT_TYPE_NONE;
2163         else
2164           return resultType;
2165       case IFX:
2166         return RESULT_TYPE_IFX;
2167       default:
2168         return RESULT_TYPE_NONE;
2169     }
2170 }
2171
2172 /*-----------------------------------------------------------------*/
2173 /* getLeftResultType - gets type from left branch for propagation  */
2174 /*-----------------------------------------------------------------*/
2175 static RESULT_TYPE
2176 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2177 {
2178   switch (tree->opval.op)
2179     {
2180       case '=':
2181       case CAST:
2182         if (IS_PTR (LTYPE (tree)))
2183           return RESULT_TYPE_NONE;
2184         else
2185           return getResultTypeFromType (LETYPE (tree));
2186       case RETURN:
2187         if (IS_PTR (currFunc->type->next))
2188           return RESULT_TYPE_NONE;
2189         else
2190           return getResultTypeFromType (currFunc->type->next);
2191       case '[':
2192         if (!IS_ARRAY (LTYPE (tree)))
2193           return resultType;
2194         if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
2195           return RESULT_TYPE_CHAR;
2196         return resultType;
2197       default:
2198         return resultType;
2199     }
2200 }
2201
2202 /*--------------------------------------------------------------------*/
2203 /* decorateType - compute type for this tree, also does type checking.*/
2204 /* This is done bottom up, since type has to flow upwards.            */
2205 /* resultType flows top-down and forces e.g. char-arithmetik, if the  */
2206 /* result is a char and the operand(s) are int's.                     */
2207 /* It also does constant folding, and parameter checking.             */
2208 /*--------------------------------------------------------------------*/
2209 ast *
2210 decorateType (ast * tree, RESULT_TYPE resultType)
2211 {
2212   int parmNumber;
2213   sym_link *p;
2214   RESULT_TYPE resultTypeProp;
2215
2216   if (!tree)
2217     return tree;
2218
2219   /* if already has type then do nothing */
2220   if (tree->decorated)
2221     return tree;
2222
2223   tree->decorated = 1;
2224
2225 #if 0
2226   /* print the line          */
2227   /* if not block & function */
2228   if (tree->type == EX_OP &&
2229       (tree->opval.op != FUNCTION &&
2230        tree->opval.op != BLOCK &&
2231        tree->opval.op != NULLOP))
2232     {
2233       filename = tree->filename;
2234       lineno = tree->lineno;
2235     }
2236 #endif
2237
2238   /* if any child is an error | this one is an error do nothing */
2239   if (tree->isError ||
2240       (tree->left && tree->left->isError) ||
2241       (tree->right && tree->right->isError))
2242     return tree;
2243
2244 /*------------------------------------------------------------------*/
2245 /*----------------------------*/
2246 /*   leaf has been reached    */
2247 /*----------------------------*/
2248   lineno=tree->lineno;
2249   /* if this is of type value */
2250   /* just get the type        */
2251   if (tree->type == EX_VALUE)
2252     {
2253
2254       if (IS_LITERAL (tree->opval.val->etype))
2255         {
2256
2257           /* if this is a character array then declare it */
2258           if (IS_ARRAY (tree->opval.val->type))
2259             tree->opval.val = stringToSymbol (tree->opval.val);
2260
2261           /* otherwise just copy the type information */
2262           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2263           return tree;
2264         }
2265
2266       if (tree->opval.val->sym)
2267         {
2268           /* if the undefined flag is set then give error message */
2269           if (tree->opval.val->sym->undefined)
2270             {
2271               werror (E_ID_UNDEF, tree->opval.val->sym->name);
2272               /* assume int */
2273               TTYPE (tree) = TETYPE (tree) =
2274                 tree->opval.val->type = tree->opval.val->sym->type =
2275                 tree->opval.val->etype = tree->opval.val->sym->etype =
2276                 copyLinkChain (INTTYPE);
2277             }
2278           else
2279             {
2280
2281               /* if impilicit i.e. struct/union member then no type */
2282               if (tree->opval.val->sym->implicit)
2283                 TTYPE (tree) = TETYPE (tree) = NULL;
2284
2285               else
2286                 {
2287
2288                   /* else copy the type */
2289                   COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2290
2291                   /* and mark it as referenced */
2292                   tree->opval.val->sym->isref = 1;
2293                 }
2294             }
2295         }
2296
2297       return tree;
2298     }
2299
2300   /* if type link for the case of cast */
2301   if (tree->type == EX_LINK)
2302     {
2303       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2304       return tree;
2305     }
2306
2307   {
2308     ast *dtl, *dtr;
2309
2310     #if 0
2311     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2312       {
2313         if (tree->left && tree->left->type == EX_OPERAND
2314             && (tree->left->opval.op == INC_OP
2315                 || tree->left->opval.op == DEC_OP)
2316             && tree->left->left)
2317           {
2318             tree->left->right = tree->left->left;
2319             tree->left->left = NULL;
2320           }
2321         if (tree->right && tree->right->type == EX_OPERAND
2322             && (tree->right->opval.op == INC_OP
2323                 || tree->right->opval.op == DEC_OP)
2324             && tree->right->left)
2325           {
2326             tree->right->right = tree->right->left;
2327             tree->right->left = NULL;
2328           }
2329       }
2330     #endif
2331
2332     /* Before decorating the left branch we've to decide in dependence
2333        upon tree->opval.op, if resultType can be propagated */
2334     resultTypeProp = resultTypePropagate (tree, resultType);
2335
2336     if (tree->opval.op == '?')
2337       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2338     else
2339       dtl = decorateType (tree->left, resultTypeProp);
2340
2341     /* if an array node, we may need to swap branches */
2342     if (tree->opval.op == '[')
2343       {
2344         /* determine which is the array & which the index */
2345         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2346             IS_INTEGRAL (LTYPE (tree)))
2347           {
2348             ast *tempTree = tree->left;
2349             tree->left = tree->right;
2350             tree->right = tempTree;
2351           }
2352       }
2353
2354     /* After decorating the left branch there's type information available
2355        in tree->left->?type. If the op is e.g. '=' we extract the type
2356        information from there and propagate it to the right branch. */
2357     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2358     
2359     switch (tree->opval.op)
2360       {
2361         case '?':
2362           /* delay right side for '?' operator since conditional macro
2363              expansions might rely on this */
2364           dtr = tree->right;
2365           break;
2366         case CALL: 
2367           /* decorate right side for CALL (parameter list) in processParms();
2368              there is resultType available */
2369           dtr = tree->right;
2370           break;
2371         default:     
2372           dtr = decorateType (tree->right, resultTypeProp);
2373           break;
2374       }
2375
2376     /* this is to take care of situations
2377        when the tree gets rewritten */
2378     if (dtl != tree->left)
2379       tree->left = dtl;
2380     if (dtr != tree->right)
2381       tree->right = dtr;
2382     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2383       return tree;
2384   }
2385
2386   /* depending on type of operator do */
2387
2388   switch (tree->opval.op)
2389     {
2390         /*------------------------------------------------------------------*/
2391         /*----------------------------*/
2392         /*        array node          */
2393         /*----------------------------*/
2394     case '[':
2395
2396       /* first check if this is a array or a pointer */
2397       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2398         {
2399           werror (E_NEED_ARRAY_PTR, "[]");
2400           goto errorTreeReturn;
2401         }
2402
2403       /* check if the type of the idx */
2404       if (!IS_INTEGRAL (RTYPE (tree)))
2405         {
2406           werror (E_IDX_NOT_INT);
2407           goto errorTreeReturn;
2408         }
2409
2410       /* if the left is an rvalue then error */
2411       if (LRVAL (tree))
2412         {
2413           werror (E_LVALUE_REQUIRED, "array access");
2414           goto errorTreeReturn;
2415         }
2416
2417       if (IS_LITERAL (RTYPE (tree)))
2418         {
2419           int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
2420           int arraySize = DCL_ELEM (LTYPE (tree));
2421           if (arraySize && arrayIndex >= arraySize)
2422             {
2423               werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2424             }
2425         }
2426
2427       RRVAL (tree) = 1;
2428       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2429       return tree;
2430
2431       /*------------------------------------------------------------------*/
2432       /*----------------------------*/
2433       /*      struct/union          */
2434       /*----------------------------*/
2435     case '.':
2436       /* if this is not a structure */
2437       if (!IS_STRUCT (LTYPE (tree)))
2438         {
2439           werror (E_STRUCT_UNION, ".");
2440           goto errorTreeReturn;
2441         }
2442       TTYPE (tree) = structElemType (LTYPE (tree),
2443                                      (tree->right->type == EX_VALUE ?
2444                                tree->right->opval.val : NULL));
2445       TETYPE (tree) = getSpec (TTYPE (tree));
2446       return tree;
2447
2448       /*------------------------------------------------------------------*/
2449       /*----------------------------*/
2450       /*    struct/union pointer    */
2451       /*----------------------------*/
2452     case PTR_OP:
2453       /* if not pointer to a structure */
2454       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2455         {
2456           werror (E_PTR_REQD);
2457           goto errorTreeReturn;
2458         }
2459
2460       if (!IS_STRUCT (LTYPE (tree)->next))
2461         {
2462           werror (E_STRUCT_UNION, "->");
2463           goto errorTreeReturn;
2464         }
2465
2466       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2467                                      (tree->right->type == EX_VALUE ?
2468                                tree->right->opval.val : NULL));
2469       TETYPE (tree) = getSpec (TTYPE (tree));
2470
2471       /* adjust the storage class */
2472       switch (DCL_TYPE(tree->left->ftype)) {
2473       case POINTER:
2474         SPEC_SCLS(TETYPE(tree)) = S_DATA; 
2475         break;
2476       case FPOINTER:
2477         SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2478         break;
2479       case CPOINTER:
2480         SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2481         break;
2482       case GPOINTER:
2483         SPEC_SCLS (TETYPE (tree)) = 0;
2484         break;
2485       case PPOINTER:
2486         SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2487         break;
2488       case IPOINTER:
2489         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2490         break;
2491       case EEPPOINTER:
2492         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2493         break;
2494       case UPOINTER:
2495         SPEC_SCLS (TETYPE (tree)) = 0;
2496         break;
2497       case ARRAY:
2498       case FUNCTION:
2499         break;
2500       }
2501       
2502       /* This breaks with extern declarations, bitfields, and perhaps other */
2503       /* cases (gcse). Let's leave this optimization disabled for now and   */
2504       /* ponder if there's a safe way to do this. -- EEP                    */
2505       #if 0
2506       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2507           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2508         {
2509             /* If defined    struct type at addr var
2510                then rewrite  (&struct var)->member
2511                as            temp
2512                and define    membertype at (addr+offsetof(struct var,member)) temp
2513             */
2514             symbol *sym;
2515             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2516                                                 AST_SYMBOL(tree->right));
2517
2518             sym = newSymbol(genSymName (0), 0);
2519             sym->type = TTYPE (tree);
2520             sym->etype = getSpec(sym->type);
2521             sym->lineDef = tree->lineno;
2522             sym->cdef = 1;
2523             sym->isref = 1;
2524             SPEC_STAT (sym->etype) = 1;
2525             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2526                                      + element->offset;
2527             SPEC_ABSA(sym->etype) = 1;
2528             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2529             allocGlobal (sym);
2530             
2531             AST_VALUE (tree) = symbolVal(sym);
2532             TLVAL (tree) = 1;
2533             TRVAL (tree) = 0;
2534             tree->type = EX_VALUE;
2535             tree->left = NULL;
2536             tree->right = NULL;
2537         }
2538       #endif
2539       
2540       return tree;
2541
2542       /*------------------------------------------------------------------*/
2543       /*----------------------------*/
2544       /*  ++/-- operation           */
2545       /*----------------------------*/
2546     case INC_OP:
2547     case DEC_OP:
2548       {
2549         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2550         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2551         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2552           werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2553
2554         if (tree->right)
2555           RLVAL (tree) = 1;
2556         else
2557           LLVAL (tree) = 1;
2558         return tree;
2559       }
2560
2561       /*------------------------------------------------------------------*/
2562       /*----------------------------*/
2563       /*  bitwise and               */
2564       /*----------------------------*/
2565     case '&':                   /* can be unary   */
2566       /* if right is NULL then unary operation  */
2567       if (tree->right)          /* not an unary operation */
2568         {
2569
2570           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2571             {
2572               werror (E_BITWISE_OP);
2573               werror (W_CONTINUE, "left & right types are ");
2574               printTypeChain (LTYPE (tree), stderr);
2575               fprintf (stderr, ",");
2576               printTypeChain (RTYPE (tree), stderr);
2577               fprintf (stderr, "\n");
2578               goto errorTreeReturn;
2579             }
2580
2581           /* if they are both literal */
2582           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2583             {
2584               tree->type = EX_VALUE;
2585               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2586                                           valFromType (RETYPE (tree)), '&');
2587
2588               tree->right = tree->left = NULL;
2589               TETYPE (tree) = tree->opval.val->etype;
2590               TTYPE (tree) = tree->opval.val->type;
2591               return tree;
2592             }
2593
2594           /* see if this is a GETHBIT operation if yes
2595              then return that */
2596           {
2597             ast *otree = optimizeGetHbit (tree);
2598
2599             if (otree != tree)
2600               return decorateType (otree, RESULT_TYPE_NONE);
2601           }
2602
2603           /* if left is a literal exchange left & right */
2604           if (IS_LITERAL (LTYPE (tree)))
2605             {
2606               ast *tTree = tree->left;
2607               tree->left = tree->right;
2608               tree->right = tTree;
2609             }
2610
2611           /* if right is a literal and */
2612           /* we can find a 2nd literal in an and-tree then */
2613           /* rearrange the tree */
2614           if (IS_LITERAL (RTYPE (tree)))
2615             {
2616               ast *parent;
2617               ast *litTree = searchLitOp (tree, &parent, "&");
2618               if (litTree)
2619                 {
2620                   DEBUG_CF("&")
2621                   ast *tTree = litTree->left;
2622                   litTree->left = tree->right;
2623                   tree->right = tTree;
2624                   /* both operands in litTree are literal now */
2625                   decorateType (parent, resultType);
2626                 }
2627             }
2628
2629           LRVAL (tree) = RRVAL (tree) = 1;
2630           
2631           TTYPE (tree) = computeType (LTYPE (tree),
2632                                       RTYPE (tree),
2633                                       resultType,
2634                                       tree->opval.op);
2635           TETYPE (tree) = getSpec (TTYPE (tree));
2636
2637           return tree;
2638         }
2639
2640       /*------------------------------------------------------------------*/
2641       /*----------------------------*/
2642       /*  address of                */
2643       /*----------------------------*/
2644       p = newLink (DECLARATOR);
2645       /* if bit field then error */
2646       if (IS_BITVAR (tree->left->etype))
2647         {
2648           werror (E_ILLEGAL_ADDR, "address of bit variable");
2649           goto errorTreeReturn;
2650         }
2651
2652       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2653         {
2654           werror (E_ILLEGAL_ADDR, "address of register variable");
2655           goto errorTreeReturn;
2656         }
2657
2658       if (IS_FUNC (LTYPE (tree)))
2659         {
2660           // this ought to be ignored
2661           return (tree->left);
2662         }
2663
2664       if (IS_LITERAL(LTYPE(tree)))
2665         {
2666           werror (E_ILLEGAL_ADDR, "address of literal");
2667           goto errorTreeReturn;
2668         }
2669
2670      if (LRVAL (tree))
2671         {
2672           werror (E_LVALUE_REQUIRED, "address of");
2673           goto errorTreeReturn;
2674         }
2675       if (!LETYPE (tree))
2676         DCL_TYPE (p) = POINTER;
2677       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2678         DCL_TYPE (p) = CPOINTER;
2679       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2680         DCL_TYPE (p) = FPOINTER;
2681       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2682         DCL_TYPE (p) = PPOINTER;
2683       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2684         DCL_TYPE (p) = IPOINTER;
2685       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2686         DCL_TYPE (p) = EEPPOINTER;
2687       else if (SPEC_OCLS(tree->left->etype))
2688           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2689       else
2690           DCL_TYPE (p) = POINTER;
2691
2692       if (IS_AST_SYM_VALUE (tree->left))
2693         {
2694           AST_SYMBOL (tree->left)->addrtaken = 1;
2695           AST_SYMBOL (tree->left)->allocreq = 1;
2696         }
2697
2698       p->next = LTYPE (tree);
2699       TTYPE (tree) = p;
2700       TETYPE (tree) = getSpec (TTYPE (tree));
2701       LLVAL (tree) = 1;
2702       TLVAL (tree) = 1;
2703
2704       #if 0
2705       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2706           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2707         {
2708           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2709                                       AST_SYMBOL(tree->left->right));
2710           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2711                                     valueFromLit(element->offset));
2712           tree->left = NULL;
2713           tree->right = NULL;
2714           tree->type = EX_VALUE;
2715           tree->values.literalFromCast = 1;
2716         }
2717       #endif
2718
2719       return tree;
2720
2721       /*------------------------------------------------------------------*/
2722       /*----------------------------*/
2723       /*  bitwise or                */
2724       /*----------------------------*/
2725     case '|':
2726       /* if the rewrite succeeds then don't go any furthur */
2727       {
2728         ast *wtree = optimizeRRCRLC (tree);
2729         if (wtree != tree)
2730           return decorateType (wtree, RESULT_TYPE_NONE);
2731         
2732         wtree = optimizeSWAP (tree);
2733         if (wtree != tree)
2734           return decorateType (wtree, RESULT_TYPE_NONE);
2735       }
2736
2737       /* if left is a literal exchange left & right */
2738       if (IS_LITERAL (LTYPE (tree)))
2739         {
2740           ast *tTree = tree->left;
2741           tree->left = tree->right;
2742           tree->right = tTree;
2743         }
2744
2745       /* if right is a literal and */
2746       /* we can find a 2nd literal in an or-tree then */
2747       /* rearrange the tree */
2748       if (IS_LITERAL (RTYPE (tree)))
2749         {
2750           ast *parent;
2751           ast *litTree = searchLitOp (tree, &parent, "|");
2752           if (litTree)
2753             {
2754               DEBUG_CF("|")
2755               ast *tTree = litTree->left;
2756               litTree->left = tree->right;
2757               tree->right = tTree;
2758               /* both operands in tTree are literal now */
2759               decorateType (parent, resultType);
2760             }
2761         }
2762       /* fall through */
2763
2764       /*------------------------------------------------------------------*/
2765       /*----------------------------*/
2766       /*  bitwise xor               */
2767       /*----------------------------*/
2768     case '^':
2769       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2770         {
2771           werror (E_BITWISE_OP);
2772           werror (W_CONTINUE, "left & right types are ");
2773           printTypeChain (LTYPE (tree), stderr);
2774           fprintf (stderr, ",");
2775           printTypeChain (RTYPE (tree), stderr);
2776           fprintf (stderr, "\n");
2777           goto errorTreeReturn;
2778         }
2779
2780       /* if they are both literal then rewrite the tree */
2781       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2782         {
2783           tree->type = EX_VALUE;
2784           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2785                                         valFromType (RETYPE (tree)),
2786                                         tree->opval.op);
2787           tree->right = tree->left = NULL;
2788           TETYPE (tree) = tree->opval.val->etype;
2789           TTYPE (tree) = tree->opval.val->type;
2790           return tree;
2791         }
2792
2793       /* if left is a literal exchange left & right */
2794       if (IS_LITERAL (LTYPE (tree)))
2795         {
2796           ast *tTree = tree->left;
2797           tree->left = tree->right;
2798           tree->right = tTree;
2799         }
2800
2801       /* if right is a literal and */
2802       /* we can find a 2nd literal in a xor-tree then */
2803       /* rearrange the tree */
2804       if (IS_LITERAL (RTYPE (tree)) &&
2805           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
2806         {
2807           ast *parent;
2808           ast *litTree = searchLitOp (tree, &parent, "^");
2809           if (litTree)
2810             {
2811               DEBUG_CF("^")
2812               ast *tTree = litTree->left;
2813               litTree->left = tree->right;
2814               tree->right = tTree;
2815               /* both operands in litTree are literal now */
2816               decorateType (parent, resultType);
2817             }
2818         }
2819
2820       LRVAL (tree) = RRVAL (tree) = 1;
2821
2822       TTYPE (tree) = computeType (LTYPE (tree),
2823                                   RTYPE (tree),
2824                                   resultType,
2825                                   tree->opval.op);
2826       TETYPE (tree) = getSpec (TTYPE (tree));
2827
2828       return tree;
2829
2830       /*------------------------------------------------------------------*/
2831       /*----------------------------*/
2832       /*  division                  */
2833       /*----------------------------*/
2834     case '/':
2835       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2836         {
2837           werror (E_INVALID_OP, "divide");
2838           goto errorTreeReturn;
2839         }
2840       /* if they are both literal then */
2841       /* rewrite the tree */
2842       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2843         {
2844           tree->type = EX_VALUE;
2845           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
2846                                     valFromType (RETYPE (tree)));
2847           tree->right = tree->left = NULL;
2848           TETYPE (tree) = getSpec (TTYPE (tree) =
2849                                    tree->opval.val->type);
2850           return tree;
2851         }
2852
2853       LRVAL (tree) = RRVAL (tree) = 1;
2854
2855       TETYPE (tree) = getSpec (TTYPE (tree) =
2856                                computeType (LTYPE (tree),
2857                                             RTYPE (tree),
2858                                             resultType,
2859                                             tree->opval.op));
2860
2861       /* if right is a literal and */
2862       /* left is also a division by a literal then */
2863       /* rearrange the tree */
2864       if (IS_LITERAL (RTYPE (tree))
2865           /* avoid infinite loop */
2866           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
2867         {
2868           ast *parent;
2869           ast *litTree = searchLitOp (tree, &parent, "/");
2870           if (litTree)
2871             {
2872               if (IS_LITERAL (RTYPE (litTree)))
2873                 {
2874                   /* foo_div */
2875                   DEBUG_CF("div r")
2876                   litTree->right = newNode ('*',
2877                                             litTree->right,
2878                                             copyAst (tree->right));
2879                   litTree->right->lineno = tree->lineno;
2880
2881                   tree->right->opval.val = constVal ("1");
2882                   decorateType (parent, resultType);
2883                 }
2884               else
2885                 {
2886                   /* litTree->left is literal: no gcse possible.
2887                      We can't call decorateType(parent, RESULT_TYPE_NONE), because
2888                      this would cause an infinit loop. */
2889                   parent->decorated = 1;
2890                   decorateType (litTree, resultType);
2891                 }
2892             }
2893         }
2894
2895       return tree;
2896
2897       /*------------------------------------------------------------------*/
2898       /*----------------------------*/
2899       /*            modulus         */
2900       /*----------------------------*/
2901     case '%':
2902       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2903         {
2904           werror (E_BITWISE_OP);
2905           werror (W_CONTINUE, "left & right types are ");
2906           printTypeChain (LTYPE (tree), stderr);
2907           fprintf (stderr, ",");
2908           printTypeChain (RTYPE (tree), stderr);
2909           fprintf (stderr, "\n");
2910           goto errorTreeReturn;
2911         }
2912       /* if they are both literal then */
2913       /* rewrite the tree */
2914       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2915         {
2916           tree->type = EX_VALUE;
2917           tree->opval.val = valMod (valFromType (LETYPE (tree)),
2918                                     valFromType (RETYPE (tree)));
2919           tree->right = tree->left = NULL;
2920           TETYPE (tree) = getSpec (TTYPE (tree) =
2921                                    tree->opval.val->type);
2922           return tree;
2923         }
2924       LRVAL (tree) = RRVAL (tree) = 1;
2925       TETYPE (tree) = getSpec (TTYPE (tree) =
2926                                computeType (LTYPE (tree),
2927                                             RTYPE (tree),
2928                                             resultType,
2929                                             tree->opval.op));
2930       return tree;
2931
2932       /*------------------------------------------------------------------*/
2933       /*----------------------------*/
2934       /*  address dereference       */
2935       /*----------------------------*/
2936     case '*':                   /* can be unary  : if right is null then unary operation */
2937       if (!tree->right)
2938         {
2939           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2940             {
2941               werror (E_PTR_REQD);
2942               goto errorTreeReturn;
2943             }
2944
2945           if (LRVAL (tree))
2946             {
2947               werror (E_LVALUE_REQUIRED, "pointer deref");
2948               goto errorTreeReturn;
2949             }
2950           if (IS_ADDRESS_OF_OP(tree->left))
2951             {
2952               /* replace *&obj with obj */
2953               return tree->left->left;
2954             }
2955           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
2956           TETYPE (tree) = getSpec (TTYPE (tree));
2957           /* adjust the storage class */
2958           switch (DCL_TYPE(tree->left->ftype)) {
2959             case POINTER:
2960               SPEC_SCLS(TETYPE(tree)) = S_DATA;
2961               break;
2962             case FPOINTER:
2963               SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2964               break;
2965             case CPOINTER:
2966               SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2967               break;
2968             case GPOINTER:
2969               SPEC_SCLS (TETYPE (tree)) = 0;
2970               break;
2971             case PPOINTER:
2972               SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2973               break;
2974             case IPOINTER:
2975               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2976               break;
2977             case EEPPOINTER:
2978               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2979               break;
2980             case UPOINTER:
2981               SPEC_SCLS (TETYPE (tree)) = 0;
2982               break;
2983             case ARRAY:
2984             case FUNCTION:
2985               break;
2986           }
2987           return tree;
2988         }
2989
2990       /*------------------------------------------------------------------*/
2991       /*----------------------------*/
2992       /*      multiplication        */
2993       /*----------------------------*/
2994       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2995         {
2996           werror (E_INVALID_OP, "multiplication");
2997           goto errorTreeReturn;
2998         }
2999
3000       /* if they are both literal then */
3001       /* rewrite the tree */
3002       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3003         {
3004           tree->type = EX_VALUE;
3005           tree->opval.val = valMult (valFromType (LETYPE (tree)),
3006                                      valFromType (RETYPE (tree)));
3007           tree->right = tree->left = NULL;
3008           TETYPE (tree) = getSpec (TTYPE (tree) =
3009                                    tree->opval.val->type);
3010           return tree;
3011         }
3012
3013       /* if left is a literal exchange left & right */
3014       if (IS_LITERAL (LTYPE (tree)))
3015         {
3016           ast *tTree = tree->left;
3017           tree->left = tree->right;
3018           tree->right = tTree;
3019         }
3020
3021       /* if right is a literal and */
3022       /* we can find a 2nd literal in a mul-tree then */
3023       /* rearrange the tree */
3024       if (IS_LITERAL (RTYPE (tree)))
3025         {
3026           ast *parent;
3027           ast *litTree = searchLitOp (tree, &parent, "*");
3028           if (litTree)
3029             {
3030               DEBUG_CF("mul")
3031               ast *tTree = litTree->left;
3032               litTree->left = tree->right;
3033               tree->right = tTree;
3034               /* both operands in litTree are literal now */
3035               decorateType (parent, resultType);
3036             }
3037         }
3038
3039       LRVAL (tree) = RRVAL (tree) = 1;
3040       tree->left  = addCast (tree->left,  resultType, FALSE);
3041       tree->right = addCast (tree->right, resultType, FALSE);
3042       TETYPE (tree) = getSpec (TTYPE (tree) =
3043                                    computeType (LTYPE (tree),
3044                                                 RTYPE (tree),
3045                                                 resultType,
3046                                                 tree->opval.op));
3047
3048       return tree;
3049
3050       /*------------------------------------------------------------------*/
3051       /*----------------------------*/
3052       /*    unary '+' operator      */
3053       /*----------------------------*/
3054     case '+':
3055       /* if unary plus */
3056       if (!tree->right)
3057         {
3058           if (!IS_ARITHMETIC (LTYPE (tree)))
3059             {
3060               werror (E_UNARY_OP, '+');
3061               goto errorTreeReturn;
3062             }
3063
3064           /* if left is a literal then do it */
3065           if (IS_LITERAL (LTYPE (tree)))
3066             {
3067               tree->type = EX_VALUE;
3068               tree->opval.val = valFromType (LETYPE (tree));
3069               tree->left = NULL;
3070               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3071               return tree;
3072             }
3073           LRVAL (tree) = 1;
3074           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3075           return tree;
3076         }
3077
3078       /*------------------------------------------------------------------*/
3079       /*----------------------------*/
3080       /*      addition              */
3081       /*----------------------------*/
3082
3083       /* this is not a unary operation */
3084       /* if both pointers then problem */
3085       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3086           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3087         {
3088           werror (E_PTR_PLUS_PTR);
3089           goto errorTreeReturn;
3090         }
3091
3092       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3093           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3094         {
3095           werror (E_PLUS_INVALID, "+");
3096           goto errorTreeReturn;
3097         }
3098
3099       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3100           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3101         {
3102           werror (E_PLUS_INVALID, "+");
3103           goto errorTreeReturn;
3104         }
3105       /* if they are both literal then */
3106       /* rewrite the tree */
3107       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3108         {
3109           tree->type = EX_VALUE;
3110           tree->left  = addCast (tree->left,  resultType, TRUE);
3111           tree->right = addCast (tree->right, resultType, TRUE);
3112           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3113                                      valFromType (RETYPE (tree)));
3114           tree->right = tree->left = NULL;
3115           TETYPE (tree) = getSpec (TTYPE (tree) =
3116                                    tree->opval.val->type);
3117           return tree;
3118         }
3119
3120       /* if the right is a pointer or left is a literal
3121          xchange left & right */
3122       if (IS_ARRAY (RTYPE (tree)) ||
3123           IS_PTR (RTYPE (tree)) ||
3124           IS_LITERAL (LTYPE (tree)))
3125         {
3126           ast *tTree = tree->left;
3127           tree->left = tree->right;
3128           tree->right = tTree;
3129         }
3130
3131       /* if right is a literal and */
3132       /* left is also an addition/subtraction with a literal then */
3133       /* rearrange the tree */
3134       if (IS_LITERAL (RTYPE (tree)))
3135         {
3136           ast *litTree, *parent;
3137           litTree = searchLitOp (tree, &parent, "+-");
3138           if (litTree)
3139             {
3140               if (litTree->opval.op == '+')
3141                 {
3142                   /* foo_aa */
3143                   DEBUG_CF("+ 1 AA")
3144                   ast *tTree = litTree->left;
3145                   litTree->left = tree->right;
3146                   tree->right = tree->left;
3147                   tree->left = tTree;
3148                 }
3149               else if (litTree->opval.op == '-')
3150                 {
3151                   if (IS_LITERAL (RTYPE (litTree)))
3152                     {
3153                       DEBUG_CF("+ 2 ASR")
3154                       /* foo_asr */
3155                       ast *tTree = litTree->left;
3156                       litTree->left = tree->right;
3157                       tree->right = tTree;
3158                     }
3159                   else
3160                     {
3161                       DEBUG_CF("+ 3 ASL")
3162                       /* foo_asl */
3163                       ast *tTree = litTree->right;
3164                       litTree->right = tree->right;
3165                       tree->right = tTree;
3166                       litTree->opval.op = '+';
3167                       tree->opval.op = '-';
3168                     }
3169                 }
3170               decorateType (parent, resultType);
3171             }
3172         }
3173
3174       LRVAL (tree) = RRVAL (tree) = 1;
3175       /* if the left is a pointer */
3176       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3177         TETYPE (tree) = getSpec (TTYPE (tree) =
3178                                  LTYPE (tree));
3179       else
3180         {
3181           tree->left  = addCast (tree->left,  resultType, TRUE);
3182           tree->right = addCast (tree->right, resultType, TRUE);
3183           TETYPE (tree) = getSpec (TTYPE (tree) =
3184                                      computeType (LTYPE (tree),
3185                                                   RTYPE (tree),
3186                                                   resultType,
3187                                                   tree->opval.op));
3188         }
3189         
3190       return tree;
3191
3192       /*------------------------------------------------------------------*/
3193       /*----------------------------*/
3194       /*      unary '-'             */
3195       /*----------------------------*/
3196     case '-':                   /* can be unary   */
3197       /* if right is null then unary */
3198       if (!tree->right)
3199         {
3200
3201           if (!IS_ARITHMETIC (LTYPE (tree)))
3202             {
3203               werror (E_UNARY_OP, tree->opval.op);
3204               goto errorTreeReturn;
3205             }
3206
3207           /* if left is a literal then do it */
3208           if (IS_LITERAL (LTYPE (tree)))
3209             {
3210               tree->type = EX_VALUE;
3211               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3212               tree->left = NULL;
3213               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3214               SPEC_USIGN(TETYPE(tree)) = 0;
3215               return tree;
3216             }
3217           LRVAL (tree) = 1;
3218           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3219           return tree;
3220         }
3221
3222       /*------------------------------------------------------------------*/
3223       /*----------------------------*/
3224       /*    subtraction             */
3225       /*----------------------------*/
3226
3227       if (!(IS_PTR (LTYPE (tree)) ||
3228             IS_ARRAY (LTYPE (tree)) ||
3229             IS_ARITHMETIC (LTYPE (tree))))
3230         {
3231           werror (E_PLUS_INVALID, "-");
3232           goto errorTreeReturn;
3233         }
3234
3235       if (!(IS_PTR (RTYPE (tree)) ||
3236             IS_ARRAY (RTYPE (tree)) ||
3237             IS_ARITHMETIC (RTYPE (tree))))
3238         {
3239           werror (E_PLUS_INVALID, "-");
3240           goto errorTreeReturn;
3241         }
3242
3243       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3244           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3245             IS_INTEGRAL (RTYPE (tree))))
3246         {
3247           werror (E_PLUS_INVALID, "-");
3248           goto errorTreeReturn;
3249         }
3250
3251       /* if they are both literal then */
3252       /* rewrite the tree */
3253       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3254         {
3255           tree->type = EX_VALUE;
3256           tree->left  = addCast (tree->left,  resultType, TRUE);
3257           tree->right = addCast (tree->right, resultType, TRUE);
3258           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3259                                       valFromType (RETYPE (tree)));
3260           tree->right = tree->left = NULL;
3261           TETYPE (tree) = getSpec (TTYPE (tree) =
3262                                    tree->opval.val->type);
3263           return tree;
3264         }
3265
3266       /* if the left & right are equal then zero */
3267       if (isAstEqual (tree->left, tree->right))
3268         {
3269           tree->type = EX_VALUE;
3270           tree->left = tree->right = NULL;
3271           tree->opval.val = constVal ("0");
3272           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3273           return tree;
3274         }
3275
3276       /* if both of them are pointers or arrays then */
3277       /* the result is going to be an integer        */
3278       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3279           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3280         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3281       else
3282         /* if only the left is a pointer */
3283         /* then result is a pointer      */
3284       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3285         TETYPE (tree) = getSpec (TTYPE (tree) =
3286                                  LTYPE (tree));
3287       else
3288         {
3289           tree->left  = addCast (tree->left,  resultType, TRUE);
3290           tree->right = addCast (tree->right, resultType, TRUE);
3291
3292           TETYPE (tree) = getSpec (TTYPE (tree) =
3293                                      computeType (LTYPE (tree),
3294                                                   RTYPE (tree),
3295                                                   resultType,
3296                                                   tree->opval.op));
3297         }
3298
3299       LRVAL (tree) = RRVAL (tree) = 1;
3300
3301       /* if right is a literal and */
3302       /* left is also an addition/subtraction with a literal then */
3303       /* rearrange the tree */
3304       if (IS_LITERAL (RTYPE (tree))
3305           /* avoid infinite loop */
3306           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
3307         {
3308           ast *litTree, *litParent;
3309           litTree = searchLitOp (tree, &litParent, "+-");
3310           if (litTree)
3311             {
3312               if (litTree->opval.op == '+')
3313                 {
3314                   /* foo_sa */
3315                   DEBUG_CF("- 1 SA")
3316                   ast *tTree = litTree->left;
3317                   litTree->left = litTree->right;
3318                   litTree->right = tree->right;
3319                   tree->right = tTree;
3320                   tree->opval.op = '+';
3321                   litTree->opval.op = '-';
3322                 }
3323               else if (litTree->opval.op == '-')
3324                 {
3325                   if (IS_LITERAL (RTYPE (litTree)))
3326                     {
3327                       /* foo_ssr */
3328                       DEBUG_CF("- 2 SSR")
3329                       ast *tTree = litTree->left;
3330                       litTree->left = tree->right;
3331                       tree->right = litParent->left;
3332                       litParent->left = tTree;
3333                       litTree->opval.op = '+';
3334                       
3335                       tree->decorated = 0;
3336                       decorateType (tree, resultType);
3337                     }
3338                   else
3339                     {
3340                       /* foo_ssl */
3341                       DEBUG_CF("- 3 SSL")
3342                       ast *tTree = litTree->right;
3343                       litTree->right = tree->right;
3344                       tree->right = tTree;
3345                     }
3346                 }
3347               decorateType (litParent, resultType);
3348             }
3349         }
3350       return tree;
3351
3352       /*------------------------------------------------------------------*/
3353       /*----------------------------*/
3354       /*    complement              */
3355       /*----------------------------*/
3356     case '~':
3357       /* can be only integral type */
3358       if (!IS_INTEGRAL (LTYPE (tree)))
3359         {
3360           werror (E_UNARY_OP, tree->opval.op);
3361           goto errorTreeReturn;
3362         }
3363
3364       /* if left is a literal then do it */
3365       if (IS_LITERAL (LTYPE (tree)))
3366         {
3367           tree->type = EX_VALUE;
3368           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3369           tree->left = NULL;
3370           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3371           return addCast (tree, resultType, TRUE);
3372         }
3373       tree->left = addCast (tree->left, resultType, TRUE);
3374       LRVAL (tree) = 1;
3375       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3376       return tree;
3377
3378       /*------------------------------------------------------------------*/
3379       /*----------------------------*/
3380       /*           not              */
3381       /*----------------------------*/
3382     case '!':
3383       /* can be pointer */
3384       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3385           !IS_PTR (LTYPE (tree)) &&
3386           !IS_ARRAY (LTYPE (tree)))
3387         {
3388           werror (E_UNARY_OP, tree->opval.op);
3389           goto errorTreeReturn;
3390         }
3391
3392       /* if left is a literal then do it */
3393       if (IS_LITERAL (LTYPE (tree)))
3394         {
3395           tree->type = EX_VALUE;
3396           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3397           tree->left = NULL;
3398           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3399           return tree;
3400         }
3401       LRVAL (tree) = 1;
3402       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3403       return tree;
3404
3405       /*------------------------------------------------------------------*/
3406       /*----------------------------*/
3407       /*           shift            */
3408       /*----------------------------*/
3409     case RRC:
3410     case RLC:
3411     case SWAP:
3412       TTYPE (tree) = LTYPE (tree);
3413       TETYPE (tree) = LETYPE (tree);
3414       return tree;
3415
3416     case GETHBIT:
3417       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3418       return tree;
3419
3420     case LEFT_OP:
3421     case RIGHT_OP:
3422       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3423         {
3424           werror (E_SHIFT_OP_INVALID);
3425           werror (W_CONTINUE, "left & right types are ");
3426           printTypeChain (LTYPE (tree), stderr);
3427           fprintf (stderr, ",");
3428           printTypeChain (RTYPE (tree), stderr);
3429           fprintf (stderr, "\n");
3430           goto errorTreeReturn;
3431         }
3432
3433       /* make smaller type only if it's a LEFT_OP */
3434       if (tree->opval.op == LEFT_OP)
3435         tree->left = addCast (tree->left, resultType, TRUE);
3436       
3437       /* if they are both literal then */
3438       /* rewrite the tree */
3439       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3440         {
3441           tree->type = EX_VALUE;
3442           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3443                                       valFromType (RETYPE (tree)),
3444                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3445           tree->right = tree->left = NULL;
3446           TETYPE (tree) = getSpec (TTYPE (tree) =
3447                                    tree->opval.val->type);
3448           return tree;
3449         }
3450
3451       LRVAL (tree) = RRVAL (tree) = 1;
3452       if (tree->opval.op == LEFT_OP)
3453         {
3454           TETYPE (tree) = getSpec (TTYPE (tree) =
3455                                        computeType (LTYPE (tree),
3456                                                     NULL,
3457                                                     resultType,
3458                                                     tree->opval.op));
3459         }
3460       else /* RIGHT_OP */
3461         {
3462           /* no promotion necessary */
3463           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3464           if (IS_LITERAL (TTYPE (tree)))
3465             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3466         }
3467
3468       /* if only the right side is a literal & we are
3469          shifting more than size of the left operand then zero */
3470       if (IS_LITERAL (RTYPE (tree)) &&
3471           ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
3472           (getSize (TETYPE (tree)) * 8))
3473         {
3474           if (tree->opval.op==LEFT_OP ||
3475               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3476             {
3477               lineno=tree->lineno;
3478               werror (W_SHIFT_CHANGED,
3479                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3480               tree->type = EX_VALUE;
3481               tree->left = tree->right = NULL;
3482               tree->opval.val = constVal ("0");
3483               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3484               return tree;
3485             }
3486         }
3487
3488       return tree;
3489
3490       /*------------------------------------------------------------------*/
3491       /*----------------------------*/
3492       /*         casting            */
3493       /*----------------------------*/
3494     case CAST:                  /* change the type   */
3495       /* cannot cast to an aggregate type */
3496       if (IS_AGGREGATE (LTYPE (tree)))
3497         {
3498           werror (E_CAST_ILLEGAL);
3499           goto errorTreeReturn;
3500         }
3501
3502       /* make sure the type is complete and sane */
3503       changePointer(LTYPE(tree));
3504       checkTypeSanity(LETYPE(tree), "(cast)");
3505
3506       /* If code memory is read only, then pointers to code memory */
3507       /* implicitly point to constants -- make this explicit       */
3508       {
3509         sym_link *t = LTYPE(tree);
3510         while (t && t->next)
3511           {
3512             if (IS_CODEPTR(t) && port->mem.code_ro)
3513               {
3514                 if (IS_SPEC(t->next))
3515                   SPEC_CONST (t->next) = 1;
3516                 else
3517                   DCL_PTR_CONST (t->next) = 1;
3518               }
3519             t = t->next;
3520           }
3521       }
3522
3523 #if 0
3524       /* if the right is a literal replace the tree */
3525       if (IS_LITERAL (RETYPE (tree))) {
3526               if (!IS_PTR (LTYPE (tree))) {
3527                       tree->type = EX_VALUE;
3528                       tree->opval.val =
3529                               valCastLiteral (LTYPE (tree),
3530                                               floatFromVal (valFromType (RETYPE (tree))));
3531                       tree->left = NULL;
3532                       tree->right = NULL;
3533                       TTYPE (tree) = tree->opval.val->type;
3534                       tree->values.literalFromCast = 1;
3535               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3536                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3537                       sym_link *rest = LTYPE(tree)->next;
3538                       werror(W_LITERAL_GENERIC);
3539                       TTYPE(tree) = newLink(DECLARATOR);
3540                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3541                       TTYPE(tree)->next = rest;
3542                       tree->left->opval.lnk = TTYPE(tree);
3543                       LRVAL (tree) = 1;
3544               } else {
3545                       TTYPE (tree) = LTYPE (tree);
3546                       LRVAL (tree) = 1;
3547               }
3548       } else {
3549               TTYPE (tree) = LTYPE (tree);
3550               LRVAL (tree) = 1;
3551       }
3552 #else
3553 #if 0 // this is already checked, now this could be explicit
3554       /* if pointer to struct then check names */
3555       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3556           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3557           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3558         {
3559           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3560                  SPEC_STRUCT(LETYPE(tree))->tag);
3561         }
3562 #endif
3563       if (IS_ADDRESS_OF_OP(tree->right)
3564           && IS_AST_SYM_VALUE (tree->right->left)
3565           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3566
3567         tree->type = EX_VALUE;
3568         tree->opval.val =
3569           valCastLiteral (LTYPE (tree),
3570                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3571         TTYPE (tree) = tree->opval.val->type;
3572         TETYPE (tree) = getSpec (TTYPE (tree));
3573         tree->left = NULL;
3574         tree->right = NULL;
3575         tree->values.literalFromCast = 1;
3576         return tree;
3577       }
3578
3579       /* handle offsetof macro:            */
3580       /* #define offsetof(TYPE, MEMBER) \  */
3581       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3582       if (IS_ADDRESS_OF_OP(tree->right)
3583           && IS_AST_OP (tree->right->left)
3584           && tree->right->left->opval.op == PTR_OP
3585           && IS_AST_OP (tree->right->left->left)
3586           && tree->right->left->left->opval.op == CAST
3587           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3588
3589         symbol *element = getStructElement (
3590           SPEC_STRUCT (LETYPE(tree->right->left)),
3591           AST_SYMBOL(tree->right->left->right)
3592         );
3593
3594         if (element) {
3595           tree->type = EX_VALUE;
3596           tree->opval.val = valCastLiteral (
3597             LTYPE (tree),
3598             element->offset
3599             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3600           );
3601
3602           TTYPE (tree) = tree->opval.val->type;
3603           TETYPE (tree) = getSpec (TTYPE (tree));
3604           tree->left = NULL;
3605           tree->right = NULL;
3606           return tree;
3607         }
3608       }
3609
3610       /* if the right is a literal replace the tree */
3611       if (IS_LITERAL (RETYPE (tree))) {
3612         #if 0
3613         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3614           /* rewrite      (type *)litaddr
3615              as           &temp
3616              and define   type at litaddr temp
3617              (but only if type's storage class is not generic)
3618           */
3619           ast *newTree = newNode ('&', NULL, NULL);
3620           symbol *sym;
3621
3622           TTYPE (newTree) = LTYPE (tree);
3623           TETYPE (newTree) = getSpec(LTYPE (tree));
3624
3625           /* define a global symbol at the casted address*/
3626           sym = newSymbol(genSymName (0), 0);
3627           sym->type = LTYPE (tree)->next;
3628           if (!sym->type)
3629             sym->type = newLink (V_VOID);
3630           sym->etype = getSpec(sym->type);
3631           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3632           sym->lineDef = tree->lineno;
3633           sym->cdef = 1;
3634           sym->isref = 1;
3635           SPEC_STAT (sym->etype) = 1;
3636           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3637           SPEC_ABSA(sym->etype) = 1;
3638           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3639           allocGlobal (sym);
3640
3641           newTree->left = newAst_VALUE(symbolVal(sym));
3642           newTree->left->lineno = tree->lineno;
3643           LTYPE (newTree) = sym->type;
3644           LETYPE (newTree) = sym->etype;
3645           LLVAL (newTree) = 1;
3646           LRVAL (newTree) = 0;
3647           TLVAL (newTree) = 1;
3648           return newTree;
3649         }
3650         #endif
3651         if (!IS_PTR (LTYPE (tree))) {
3652           tree->type = EX_VALUE;
3653           tree->opval.val =
3654           valCastLiteral (LTYPE (tree),
3655                           floatFromVal (valFromType (RTYPE (tree))));
3656           TTYPE (tree) = tree->opval.val->type;
3657           tree->left = NULL;
3658           tree->right = NULL;
3659           tree->values.literalFromCast = 1;
3660           TETYPE (tree) = getSpec (TTYPE (tree));
3661           return tree;
3662         }
3663       }
3664       TTYPE (tree) = LTYPE (tree);
3665       LRVAL (tree) = 1;
3666
3667 #endif
3668       TETYPE (tree) = getSpec (TTYPE (tree));
3669
3670       return tree;
3671
3672       /*------------------------------------------------------------------*/
3673       /*----------------------------*/
3674       /*       logical &&, ||       */
3675       /*----------------------------*/
3676     case AND_OP:
3677     case OR_OP:
3678       /* each must be arithmetic type or be a pointer */
3679       if (!IS_PTR (LTYPE (tree)) &&
3680           !IS_ARRAY (LTYPE (tree)) &&
3681           !IS_INTEGRAL (LTYPE (tree)))
3682         {
3683           werror (E_COMPARE_OP);
3684           goto errorTreeReturn;
3685         }
3686
3687       if (!IS_PTR (RTYPE (tree)) &&
3688           !IS_ARRAY (RTYPE (tree)) &&
3689           !IS_INTEGRAL (RTYPE (tree)))
3690         {
3691           werror (E_COMPARE_OP);
3692           goto errorTreeReturn;
3693         }
3694       /* if they are both literal then */
3695       /* rewrite the tree */
3696       if (IS_LITERAL (RTYPE (tree)) &&
3697           IS_LITERAL (LTYPE (tree)))
3698         {
3699           tree->type = EX_VALUE;
3700           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
3701                                            valFromType (RTYPE (tree)),
3702                                            tree->opval.op);
3703           tree->right = tree->left = NULL;
3704           TETYPE (tree) = getSpec (TTYPE (tree) =
3705                                    tree->opval.val->type);
3706           return tree;
3707         }
3708       LRVAL (tree) = RRVAL (tree) = 1;
3709       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3710       return tree;
3711
3712       /*------------------------------------------------------------------*/
3713       /*----------------------------*/
3714       /*     comparison operators   */
3715       /*----------------------------*/
3716     case '>':
3717     case '<':
3718     case LE_OP:
3719     case GE_OP:
3720     case EQ_OP:
3721     case NE_OP:
3722       {
3723         ast *lt = optimizeCompare (tree);
3724
3725         if (tree != lt)
3726           return lt;
3727       }
3728
3729       /* if they are pointers they must be castable */
3730       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3731         {
3732           if (tree->opval.op==EQ_OP &&
3733               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3734             // we cannot cast a gptr to a !gptr: switch the leaves
3735             struct ast *s=tree->left;
3736             tree->left=tree->right;
3737             tree->right=s;
3738           }
3739           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3740             {
3741               werror (E_COMPARE_OP);
3742               fprintf (stderr, "comparing type ");
3743               printTypeChain (LTYPE (tree), stderr);
3744               fprintf (stderr, "to type ");
3745               printTypeChain (RTYPE (tree), stderr);
3746               fprintf (stderr, "\n");
3747               goto errorTreeReturn;
3748             }
3749         }
3750       /* else they should be promotable to one another */
3751       else
3752         {
3753           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3754                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3755
3756             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3757               {
3758                 werror (E_COMPARE_OP);
3759                 fprintf (stderr, "comparing type ");
3760                 printTypeChain (LTYPE (tree), stderr);
3761                 fprintf (stderr, "to type ");
3762                 printTypeChain (RTYPE (tree), stderr);
3763                 fprintf (stderr, "\n");
3764                 goto errorTreeReturn;
3765               }
3766         }
3767       /* if unsigned value < 0  then always false */
3768       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
3769       if (SPEC_USIGN(LETYPE(tree)) &&
3770           !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
3771           IS_LITERAL(RTYPE(tree))  &&
3772           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
3773         {
3774           if (tree->opval.op == '<')
3775             {
3776               return tree->right;
3777             }
3778           if (tree->opval.op == '>')
3779             {
3780               if (resultType == RESULT_TYPE_IFX)
3781                 {
3782                   /* the parent is an ifx: */
3783                   /* if (unsigned value) */
3784                   return tree->left;
3785                 }
3786               
3787               /* (unsigned value) ? 1 : 0 */
3788               tree->opval.op = '?';
3789               tree->right = newNode (':',
3790                                      newAst_VALUE (constVal ("1")),
3791                                      tree->right); /* val 0 */
3792               tree->right->lineno = tree->lineno;
3793               tree->right->left->lineno = tree->lineno;
3794               decorateType (tree->right, RESULT_TYPE_NONE);
3795             }
3796         }
3797       /* if they are both literal then */
3798       /* rewrite the tree */
3799       if (IS_LITERAL (RTYPE (tree)) &&
3800           IS_LITERAL (LTYPE (tree)))
3801         {
3802           tree->type = EX_VALUE;
3803           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3804                                         valFromType (RETYPE (tree)),
3805                                         tree->opval.op);
3806           tree->right = tree->left = NULL;
3807           TETYPE (tree) = getSpec (TTYPE (tree) =
3808                                    tree->opval.val->type);
3809           return tree;
3810         }
3811       LRVAL (tree) = RRVAL (tree) = 1;
3812       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3813       return tree;
3814
3815       /*------------------------------------------------------------------*/
3816       /*----------------------------*/
3817       /*             sizeof         */
3818       /*----------------------------*/
3819     case SIZEOF:                /* evaluate wihout code generation */
3820       /* change the type to a integer */
3821       {
3822         int size = getSize (tree->right->ftype);
3823         SNPRINTF(buffer, sizeof(buffer), "%d", size);
3824         if (!size && !IS_VOID(tree->right->ftype))
3825           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
3826       }
3827       tree->type = EX_VALUE;
3828       tree->opval.val = constVal (buffer);
3829       tree->right = tree->left = NULL;
3830       TETYPE (tree) = getSpec (TTYPE (tree) =
3831                                tree->opval.val->type);
3832       return tree;
3833
3834       /*------------------------------------------------------------------*/
3835       /*----------------------------*/
3836       /*             typeof         */
3837       /*----------------------------*/
3838     case TYPEOF:
3839         /* return typeof enum value */
3840         tree->type = EX_VALUE;
3841         {
3842             int typeofv = 0;
3843             if (IS_SPEC(tree->right->ftype)) {
3844                 switch (SPEC_NOUN(tree->right->ftype)) {
3845                 case V_INT:
3846                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3847                     else typeofv = TYPEOF_INT;
3848                     break;
3849                 case V_FLOAT:
3850                     typeofv = TYPEOF_FLOAT;
3851                     break;
3852                 case V_CHAR:
3853                     typeofv = TYPEOF_CHAR;
3854                     break;
3855                 case V_VOID:
3856                     typeofv = TYPEOF_VOID;
3857                     break;
3858                 case V_STRUCT:
3859                     typeofv = TYPEOF_STRUCT;
3860                     break;
3861                 case V_BITFIELD:
3862                     typeofv = TYPEOF_BITFIELD;
3863                     break;
3864                 case V_BIT:
3865                     typeofv = TYPEOF_BIT;
3866                     break;
3867                 case V_SBIT:
3868                     typeofv = TYPEOF_SBIT;
3869                     break;
3870                 default:
3871                     break;
3872                 }
3873             } else {
3874                 switch (DCL_TYPE(tree->right->ftype)) {
3875                 case POINTER:
3876                     typeofv = TYPEOF_POINTER;
3877                     break;
3878                 case FPOINTER:
3879                     typeofv = TYPEOF_FPOINTER;
3880                     break;
3881                 case CPOINTER:
3882                     typeofv = TYPEOF_CPOINTER;
3883                     break;
3884                 case GPOINTER:
3885                     typeofv = TYPEOF_GPOINTER;
3886                     break;
3887                 case PPOINTER:
3888                     typeofv = TYPEOF_PPOINTER;
3889                     break;
3890                 case IPOINTER:
3891                     typeofv = TYPEOF_IPOINTER;
3892                     break;
3893                 case ARRAY:
3894                     typeofv = TYPEOF_ARRAY;
3895                     break;
3896                 case FUNCTION:
3897                     typeofv = TYPEOF_FUNCTION;
3898                     break;
3899                 default:
3900                     break;
3901                 }
3902             }
3903             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3904             tree->opval.val = constVal (buffer);
3905             tree->right = tree->left = NULL;
3906             TETYPE (tree) = getSpec (TTYPE (tree) =
3907                                      tree->opval.val->type);
3908         }
3909         return tree;
3910       /*------------------------------------------------------------------*/
3911       /*----------------------------*/
3912       /* conditional operator  '?'  */
3913       /*----------------------------*/
3914     case '?':
3915       /* the type is value of the colon operator (on the right) */
3916       assert (IS_COLON_OP (tree->right));
3917       /* if already known then replace the tree : optimizer will do it
3918          but faster to do it here */
3919       if (IS_LITERAL (LTYPE (tree)))
3920         {
3921           if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
3922             return decorateType (tree->right->left, resultTypeProp);
3923           else
3924             return decorateType (tree->right->right, resultTypeProp);
3925         }
3926       else
3927         {
3928           tree->right = decorateType (tree->right, resultTypeProp);
3929           TTYPE (tree) = RTYPE (tree);
3930           TETYPE (tree) = getSpec (TTYPE (tree));
3931         }
3932       return tree;
3933
3934     case ':':
3935       /* if they don't match we have a problem */
3936       if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
3937           (compareType (RTYPE (tree), LTYPE (tree)) == 0))
3938         {
3939           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3940           goto errorTreeReturn;
3941         }
3942
3943       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
3944                                   resultType, tree->opval.op);
3945       TETYPE (tree) = getSpec (TTYPE (tree));
3946       return tree;
3947
3948
3949 #if 0 // assignment operators are converted by the parser
3950       /*------------------------------------------------------------------*/
3951       /*----------------------------*/
3952       /*    assignment operators    */
3953       /*----------------------------*/
3954     case MUL_ASSIGN:
3955     case DIV_ASSIGN:
3956       /* for these it must be both must be integral */
3957       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3958           !IS_ARITHMETIC (RTYPE (tree)))
3959         {
3960           werror (E_OPS_INTEGRAL);
3961           goto errorTreeReturn;
3962         }
3963       RRVAL (tree) = 1;
3964       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3965
3966       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3967         werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3968
3969       if (LRVAL (tree))
3970         {
3971           werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3972           goto errorTreeReturn;
3973         }
3974       LLVAL (tree) = 1;
3975
3976       return tree;
3977
3978     case AND_ASSIGN:
3979     case OR_ASSIGN:
3980     case XOR_ASSIGN:
3981     case RIGHT_ASSIGN:
3982     case LEFT_ASSIGN:
3983       /* for these it must be both must be integral */
3984       if (!IS_INTEGRAL (LTYPE (tree)) ||
3985           !IS_INTEGRAL (RTYPE (tree)))
3986         {
3987           werror (E_OPS_INTEGRAL);
3988           goto errorTreeReturn;
3989         }
3990       RRVAL (tree) = 1;
3991       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3992
3993       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3994         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3995
3996       if (LRVAL (tree))
3997         {
3998           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3999           goto errorTreeReturn;
4000         }
4001       LLVAL (tree) = 1;
4002
4003       return tree;
4004
4005       /*------------------------------------------------------------------*/
4006       /*----------------------------*/
4007       /*    -= operator             */
4008       /*----------------------------*/
4009     case SUB_ASSIGN:
4010       if (!(IS_PTR (LTYPE (tree)) ||
4011             IS_ARITHMETIC (LTYPE (tree))))
4012         {
4013           werror (E_PLUS_INVALID, "-=");
4014           goto errorTreeReturn;
4015         }
4016
4017       if (!(IS_PTR (RTYPE (tree)) ||
4018             IS_ARITHMETIC (RTYPE (tree))))
4019         {
4020           werror (E_PLUS_INVALID, "-=");
4021           goto errorTreeReturn;
4022         }
4023       RRVAL (tree) = 1;
4024       TETYPE (tree) = getSpec (TTYPE (tree) =
4025                                computeType (LTYPE (tree),
4026                                             RTYPE (tree),
4027                                             RESULT_TYPE_NOPROM,
4028                                             tree->opval.op));
4029
4030       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4031         werror (E_CODE_WRITE, "-=");
4032
4033       if (LRVAL (tree))
4034         {
4035           werror (E_LVALUE_REQUIRED, "-=");
4036           goto errorTreeReturn;
4037         }
4038       LLVAL (tree) = 1;
4039
4040       return tree;
4041
4042       /*------------------------------------------------------------------*/
4043       /*----------------------------*/
4044       /*          += operator       */
4045       /*----------------------------*/
4046     case ADD_ASSIGN:
4047       /* this is not a unary operation */
4048       /* if both pointers then problem */
4049       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4050         {
4051           werror (E_PTR_PLUS_PTR);
4052           goto errorTreeReturn;
4053         }
4054
4055       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4056         {
4057           werror (E_PLUS_INVALID, "+=");
4058           goto errorTreeReturn;
4059         }
4060
4061       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4062         {
4063           werror (E_PLUS_INVALID, "+=");
4064           goto errorTreeReturn;
4065         }
4066       RRVAL (tree) = 1;
4067       TETYPE (tree) = getSpec (TTYPE (tree) =
4068                                computeType (LTYPE (tree),
4069                                             RTYPE (tree),
4070                                             RESULT_TYPE_NOPROM,
4071                                             tree->opval.op));
4072
4073       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4074         werror (E_CODE_WRITE, "+=");
4075
4076       if (LRVAL (tree))
4077         {
4078           werror (E_LVALUE_REQUIRED, "+=");
4079           goto errorTreeReturn;
4080         }
4081
4082       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4083       tree->opval.op = '=';
4084
4085       return tree;
4086 #endif
4087
4088       /*------------------------------------------------------------------*/
4089       /*----------------------------*/
4090       /*      straight assignemnt   */
4091       /*----------------------------*/
4092     case '=':
4093       /* cannot be an aggregate */
4094       if (IS_AGGREGATE (LTYPE (tree)))
4095         {
4096           werror (E_AGGR_ASSIGN);
4097           goto errorTreeReturn;
4098         }
4099
4100       /* they should either match or be castable */
4101       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4102         {
4103           werror (E_TYPE_MISMATCH, "assignment", " ");
4104           printFromToType(RTYPE(tree),LTYPE(tree));
4105         }
4106
4107       /* if the left side of the tree is of type void
4108          then report error */
4109       if (IS_VOID (LTYPE (tree)))
4110         {
4111           werror (E_CAST_ZERO);
4112           printFromToType(RTYPE(tree), LTYPE(tree));
4113         }
4114
4115       TETYPE (tree) = getSpec (TTYPE (tree) =
4116                                LTYPE (tree));
4117       RRVAL (tree) = 1;
4118       LLVAL (tree) = 1;
4119       if (!tree->initMode ) {
4120         if (IS_CONSTANT(LTYPE(tree)))
4121           werror (E_CODE_WRITE, "=");
4122       }
4123       if (LRVAL (tree))
4124         {
4125           werror (E_LVALUE_REQUIRED, "=");
4126           goto errorTreeReturn;
4127         }
4128
4129       return tree;
4130
4131       /*------------------------------------------------------------------*/
4132       /*----------------------------*/
4133       /*      comma operator        */
4134       /*----------------------------*/
4135     case ',':
4136       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4137       return tree;
4138
4139       /*------------------------------------------------------------------*/
4140       /*----------------------------*/
4141       /*       function call        */
4142       /*----------------------------*/
4143     case CALL:
4144       
4145       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4146       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4147         {
4148           if (tree->left->opval.op == '*' && !tree->left->right)
4149             tree->left = tree->left->left;
4150         }
4151
4152       /* require a function or pointer to function */
4153       if (!IS_FUNC (LTYPE (tree))
4154           && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
4155         {
4156           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4157           goto errorTreeReturn;
4158         }
4159
4160       /* if there are parms, make sure that
4161          parms are decorate / process / reverse only once */
4162       if (!tree->right ||
4163           !tree->right->decorated)
4164         {
4165           sym_link *functype;      
4166           parmNumber = 1;
4167
4168           if (IS_CODEPTR(LTYPE(tree)))
4169             functype = LTYPE (tree)->next;
4170           else
4171             functype = LTYPE (tree);
4172
4173           if (processParms (tree->left, FUNC_ARGS(functype),
4174                             &tree->right, &parmNumber, TRUE))
4175             {
4176               goto errorTreeReturn;
4177             }
4178         
4179           if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
4180              !IFFUNC_ISBUILTIN(functype))
4181             {
4182               reverseParms (tree->right);
4183             }
4184
4185            TTYPE (tree) = functype->next;
4186            TETYPE (tree) = getSpec (TTYPE (tree));
4187         }
4188       return tree;
4189
4190       /*------------------------------------------------------------------*/
4191       /*----------------------------*/
4192       /*     return statement       */
4193       /*----------------------------*/
4194     case RETURN:
4195       if (!tree->right)
4196         goto voidcheck;
4197
4198       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4199         {
4200           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4201           printFromToType (RTYPE(tree), currFunc->type->next);
4202           goto errorTreeReturn;
4203         }
4204
4205       if (IS_VOID (currFunc->type->next)
4206           && tree->right &&
4207           !IS_VOID (RTYPE (tree)))
4208         {
4209           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4210           goto errorTreeReturn;
4211         }
4212
4213       /* if there is going to be a casting required then add it */
4214       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4215         {
4216           tree->right =
4217             decorateType (newNode (CAST,
4218                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4219                                         tree->right),
4220                           RESULT_TYPE_NONE);
4221         }
4222
4223       RRVAL (tree) = 1;
4224       return tree;
4225
4226     voidcheck:
4227
4228       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4229         {
4230           werror (W_VOID_FUNC, currFunc->name);
4231           goto errorTreeReturn;
4232         }
4233
4234       TTYPE (tree) = TETYPE (tree) = NULL;
4235       return tree;
4236
4237       /*------------------------------------------------------------------*/
4238       /*----------------------------*/
4239       /*     switch statement       */
4240       /*----------------------------*/
4241     case SWITCH:
4242       /* the switch value must be an integer */
4243       if (!IS_INTEGRAL (LTYPE (tree)))
4244         {
4245           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4246           goto errorTreeReturn;
4247         }
4248       LRVAL (tree) = 1;
4249       TTYPE (tree) = TETYPE (tree) = NULL;
4250       return tree;
4251
4252       /*------------------------------------------------------------------*/
4253       /*----------------------------*/
4254       /* ifx Statement              */
4255       /*----------------------------*/
4256     case IFX:
4257       tree->left = backPatchLabels (tree->left,
4258                                     tree->trueLabel,
4259                                     tree->falseLabel);
4260       TTYPE (tree) = TETYPE (tree) = NULL;
4261       return tree;
4262
4263       /*------------------------------------------------------------------*/
4264       /*----------------------------*/
4265       /* for Statement              */
4266       /*----------------------------*/
4267     case FOR:
4268
4269       decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4270       decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4271       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4272
4273       /* if the for loop is reversible then
4274          reverse it otherwise do what we normally
4275          do */
4276       {
4277         symbol *sym;
4278         ast *init, *end;
4279
4280         if (isLoopReversible (tree, &sym, &init, &end))
4281           return reverseLoop (tree, sym, init, end);
4282         else
4283           return decorateType (createFor (AST_FOR (tree, trueLabel),
4284                                           AST_FOR (tree, continueLabel),
4285                                           AST_FOR (tree, falseLabel),
4286                                           AST_FOR (tree, condLabel),
4287                                           AST_FOR (tree, initExpr),
4288                                           AST_FOR (tree, condExpr),
4289                                           AST_FOR (tree, loopExpr),
4290                                           tree->left), RESULT_TYPE_NONE);
4291       }
4292     case PARAM:
4293       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4294               "node PARAM shouldn't be processed here");
4295               /* but in processParams() */
4296       return tree;
4297     default:
4298       TTYPE (tree) = TETYPE (tree) = NULL;
4299       return tree;
4300     }
4301
4302   /* some error found this tree will be killed */
4303 errorTreeReturn:
4304   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4305   tree->opval.op = NULLOP;
4306   tree->isError = 1;
4307
4308   return tree;
4309 }
4310
4311 /*-----------------------------------------------------------------*/
4312 /* sizeofOp - processes size of operation                          */
4313 /*-----------------------------------------------------------------*/
4314 value *
4315 sizeofOp (sym_link * type)
4316 {
4317   char buff[10];
4318   int size;
4319
4320   /* make sure the type is complete and sane */
4321   checkTypeSanity(type, "(sizeof)");
4322
4323   /* get the size and convert it to character  */
4324   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4325   if (!size && !IS_VOID(type))
4326     werror (E_SIZEOF_INCOMPLETE_TYPE);
4327
4328   /* now convert into value  */
4329   return constVal (buff);
4330 }
4331
4332
4333 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4334 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4335 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4336 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4337 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4338 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4339 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4340
4341 /*-----------------------------------------------------------------*/
4342 /* backPatchLabels - change and or not operators to flow control    */
4343 /*-----------------------------------------------------------------*/
4344 ast *
4345 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4346 {
4347
4348   if (!tree)
4349     return NULL;
4350
4351   if (!(IS_ANDORNOT (tree)))
4352     return tree;
4353
4354   /* if this an and */
4355   if (IS_AND (tree))
4356     {
4357       static int localLbl = 0;
4358       symbol *localLabel;
4359
4360       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4361       localLabel = newSymbol (buffer, NestLevel);
4362
4363       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4364
4365       /* if left is already a IFX then just change the if true label in that */
4366       if (!IS_IFX (tree->left))
4367         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4368
4369       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4370       /* right is a IFX then just join */
4371       if (IS_IFX (tree->right))
4372         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4373
4374       tree->right = createLabel (localLabel, tree->right);
4375       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4376
4377       return newNode (NULLOP, tree->left, tree->right);
4378     }
4379
4380   /* if this is an or operation */
4381   if (IS_OR (tree))
4382     {
4383       static int localLbl = 0;
4384       symbol *localLabel;
4385
4386       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4387       localLabel = newSymbol (buffer, NestLevel);
4388
4389       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4390
4391       /* if left is already a IFX then just change the if true label in that */
4392       if (!IS_IFX (tree->left))
4393         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4394
4395       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4396       /* right is a IFX then just join */
4397       if (IS_IFX (tree->right))
4398         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4399
4400       tree->right = createLabel (localLabel, tree->right);
4401       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4402
4403       return newNode (NULLOP, tree->left, tree->right);
4404     }
4405
4406   /* change not */
4407   if (IS_NOT (tree))
4408     {
4409       int wasnot = IS_NOT (tree->left);
4410       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4411
4412       /* if the left is already a IFX */
4413       if (!IS_IFX (tree->left))
4414         tree->left = newNode (IFX, tree->left, NULL);
4415
4416       if (wasnot)
4417         {
4418           tree->left->trueLabel = trueLabel;
4419           tree->left->falseLabel = falseLabel;
4420         }
4421       else
4422         {
4423           tree->left->trueLabel = falseLabel;
4424           tree->left->falseLabel = trueLabel;
4425         }
4426       return tree->left;
4427     }
4428
4429   if (IS_IFX (tree))
4430     {
4431       tree->trueLabel = trueLabel;
4432       tree->falseLabel = falseLabel;
4433     }
4434
4435   return tree;
4436 }
4437
4438
4439 /*-----------------------------------------------------------------*/
4440 /* createBlock - create expression tree for block                  */
4441 /*-----------------------------------------------------------------*/
4442 ast *
4443 createBlock (symbol * decl, ast * body)
4444 {
4445   ast *ex;
4446
4447   /* if the block has nothing */
4448   if (!body && !decl)
4449     return NULL;
4450
4451   ex = newNode (BLOCK, NULL, body);
4452   ex->values.sym = decl;
4453   
4454   ex->level++;
4455   ex->lineno = 0;
4456   return ex;
4457 }
4458
4459 /*-----------------------------------------------------------------*/
4460 /* createLabel - creates the expression tree for labels            */
4461 /*-----------------------------------------------------------------*/
4462 ast *
4463 createLabel (symbol * label, ast * stmnt)
4464 {
4465   symbol *csym;
4466   char name[SDCC_NAME_MAX + 1];
4467   ast *rValue;
4468
4469   /* must create fresh symbol if the symbol name  */
4470   /* exists in the symbol table, since there can  */
4471   /* be a variable with the same name as the labl */
4472   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4473       (csym->level == label->level))
4474     label = newSymbol (label->name, label->level);
4475
4476   /* change the name before putting it in add _ */
4477   SNPRINTF(name, sizeof(name), "%s", label->name);
4478
4479   /* put the label in the LabelSymbol table    */
4480   /* but first check if a label of the same    */
4481   /* name exists                               */
4482   if ((csym = findSym (LabelTab, NULL, name)))
4483     werror (E_DUPLICATE_LABEL, label->name);
4484   else
4485     addSym (LabelTab, label, name, label->level, 0, 0);
4486
4487   label->isitmp = 1;
4488   label->islbl = 1;
4489   label->key = labelKey++;
4490   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4491   rValue->lineno = 0;
4492
4493   return rValue;
4494 }
4495
4496 /*-----------------------------------------------------------------*/
4497 /* createCase - generates the parsetree for a case statement       */
4498 /*-----------------------------------------------------------------*/
4499 ast *
4500 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4501 {
4502   char caseLbl[SDCC_NAME_MAX + 1];
4503   ast *rexpr;
4504   value *val;
4505
4506   /* if the switch statement does not exist */
4507   /* then case is out of context            */
4508   if (!swStat)
4509     {
4510       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4511       return NULL;
4512     }
4513
4514   caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
4515   /* if not a constant then error  */
4516   if (!IS_LITERAL (caseVal->ftype))
4517     {
4518       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4519       return NULL;
4520     }
4521
4522   /* if not a integer than error */
4523   if (!IS_INTEGRAL (caseVal->ftype))
4524     {
4525       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4526       return NULL;
4527     }
4528
4529   /* find the end of the switch values chain   */
4530   if (!(val = swStat->values.switchVals.swVals))
4531     swStat->values.switchVals.swVals = caseVal->opval.val;
4532   else
4533     {
4534       /* also order the cases according to value */
4535       value *pval = NULL;
4536       int cVal = (int) floatFromVal (caseVal->opval.val);
4537       while (val && (int) floatFromVal (val) < cVal)
4538         {
4539           pval = val;
4540           val = val->next;
4541         }
4542
4543       /* if we reached the end then */
4544       if (!val)
4545         {
4546           pval->next = caseVal->opval.val;
4547         }
4548       else if ((int) floatFromVal (val) == cVal)
4549         {
4550           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4551                     "case");
4552           return NULL;
4553         }
4554       else
4555         {
4556           /* we found a value greater than */
4557           /* the current value we must add this */
4558           /* before the value */
4559           caseVal->opval.val->next = val;
4560
4561           /* if this was the first in chain */
4562           if (swStat->values.switchVals.swVals == val)
4563             swStat->values.switchVals.swVals =
4564               caseVal->opval.val;
4565           else
4566             pval->next = caseVal->opval.val;
4567         }
4568
4569     }
4570
4571   /* create the case label   */
4572   SNPRINTF(caseLbl, sizeof(caseLbl), 
4573            "_case_%d_%d",
4574            swStat->values.switchVals.swNum,
4575            (int) floatFromVal (caseVal->opval.val));
4576
4577   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4578   rexpr->lineno = 0;
4579   return rexpr;
4580 }
4581
4582 /*-----------------------------------------------------------------*/
4583 /* createDefault - creates the parse tree for the default statement */
4584 /*-----------------------------------------------------------------*/
4585 ast *
4586 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4587 {
4588   char defLbl[SDCC_NAME_MAX + 1];
4589
4590   /* if the switch statement does not exist */
4591   /* then case is out of context            */
4592   if (!swStat)
4593     {
4594       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4595       return NULL;
4596     }
4597
4598   if (swStat->values.switchVals.swDefault)
4599     {
4600       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4601                 "default");
4602       return NULL;
4603     }
4604
4605   /* turn on the default flag   */
4606   swStat->values.switchVals.swDefault = 1;
4607
4608   /* create the label  */
4609   SNPRINTF (defLbl, sizeof(defLbl),
4610             "_default_%d", swStat->values.switchVals.swNum);
4611   return createLabel (newSymbol (defLbl, 0), stmnt);
4612 }
4613
4614 /*-----------------------------------------------------------------*/
4615 /* createIf - creates the parsetree for the if statement           */
4616 /*-----------------------------------------------------------------*/
4617 ast *
4618 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4619 {
4620   static int Lblnum = 0;
4621   ast *ifTree;
4622   symbol *ifTrue, *ifFalse, *ifEnd;
4623
4624   /* if neither exists */
4625   if (!elseBody && !ifBody) {
4626     // if there are no side effects (i++, j() etc)
4627     if (!hasSEFcalls(condAst)) {
4628       return condAst;
4629     }
4630   }
4631
4632   /* create the labels */
4633   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4634   ifFalse = newSymbol (buffer, NestLevel);
4635   /* if no else body then end == false */
4636   if (!elseBody)
4637     ifEnd = ifFalse;
4638   else
4639     {
4640       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4641       ifEnd = newSymbol (buffer, NestLevel);
4642     }
4643
4644   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4645   ifTrue = newSymbol (buffer, NestLevel);
4646
4647   Lblnum++;
4648
4649   /* attach the ifTrue label to the top of it body */
4650   ifBody = createLabel (ifTrue, ifBody);
4651   /* attach a goto end to the ifBody if else is present */
4652   if (elseBody)
4653     {
4654       ifBody = newNode (NULLOP, ifBody,
4655                         newNode (GOTO,
4656                                  newAst_VALUE (symbolVal (ifEnd)),
4657                                  NULL));
4658       /* put the elseLabel on the else body */
4659       elseBody = createLabel (ifFalse, elseBody);
4660       /* out the end at the end of the body */
4661       elseBody = newNode (NULLOP,
4662                           elseBody,
4663                           createLabel (ifEnd, NULL));
4664     }
4665   else
4666     {
4667       ifBody = newNode (NULLOP, ifBody,
4668                         createLabel (ifFalse, NULL));
4669     }
4670   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4671   if (IS_IFX (condAst))
4672     ifTree = condAst;
4673   else
4674     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4675
4676   return newNode (NULLOP, ifTree,
4677                   newNode (NULLOP, ifBody, elseBody));
4678
4679 }
4680
4681 /*-----------------------------------------------------------------*/
4682 /* createDo - creates parse tree for do                            */
4683 /*        _dobody_n:                                               */
4684 /*            statements                                           */
4685 /*        _docontinue_n:                                           */
4686 /*            condition_expression +-> trueLabel -> _dobody_n      */
4687 /*                                 |                               */
4688 /*                                 +-> falseLabel-> _dobreak_n     */
4689 /*        _dobreak_n:                                              */
4690 /*-----------------------------------------------------------------*/
4691 ast *
4692 createDo (symbol * trueLabel, symbol * continueLabel,
4693           symbol * falseLabel, ast * condAst, ast * doBody)
4694 {
4695   ast *doTree;
4696
4697
4698   /* if the body does not exist then it is simple */
4699   if (!doBody)
4700     {
4701       condAst = backPatchLabels (condAst, continueLabel, NULL);
4702       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4703                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4704       doTree->trueLabel = continueLabel;
4705       doTree->falseLabel = NULL;
4706       return doTree;
4707     }
4708
4709   /* otherwise we have a body */
4710   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4711
4712   /* attach the body label to the top */
4713   doBody = createLabel (trueLabel, doBody);
4714   /* attach the continue label to end of body */
4715   doBody = newNode (NULLOP, doBody,
4716                     createLabel (continueLabel, NULL));
4717
4718   /* now put the break label at the end */
4719   if (IS_IFX (condAst))
4720     doTree = condAst;
4721   else
4722     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4723
4724   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4725
4726   /* putting it together */
4727   return newNode (NULLOP, doBody, doTree);
4728 }
4729
4730 /*-----------------------------------------------------------------*/
4731 /* createFor - creates parse tree for 'for' statement              */
4732 /*        initExpr                                                 */
4733 /*   _forcond_n:                                                   */
4734 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4735 /*                  |                                              */
4736 /*                  +-> falseLabel-> _forbreak_n                   */
4737 /*   _forbody_n:                                                   */
4738 /*        statements                                               */
4739 /*   _forcontinue_n:                                               */
4740 /*        loopExpr                                                 */
4741 /*        goto _forcond_n ;                                        */
4742 /*   _forbreak_n:                                                  */
4743 /*-----------------------------------------------------------------*/
4744 ast *
4745 createFor (symbol * trueLabel, symbol * continueLabel,
4746            symbol * falseLabel, symbol * condLabel,
4747            ast * initExpr, ast * condExpr, ast * loopExpr,
4748            ast * forBody)
4749 {
4750   ast *forTree;
4751
4752   /* if loopexpression not present then we can generate it */
4753   /* the same way as a while */
4754   if (!loopExpr)
4755     return newNode (NULLOP, initExpr,
4756                     createWhile (trueLabel, continueLabel,
4757                                  falseLabel, condExpr, forBody));
4758   /* vanilla for statement */
4759   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4760
4761   if (condExpr && !IS_IFX (condExpr))
4762     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4763
4764
4765   /* attach condition label to condition */
4766   condExpr = createLabel (condLabel, condExpr);
4767
4768   /* attach body label to body */
4769   forBody = createLabel (trueLabel, forBody);
4770
4771   /* attach continue to forLoop expression & attach */
4772   /* goto the forcond @ and of loopExpression       */
4773   loopExpr = createLabel (continueLabel,
4774                           newNode (NULLOP,
4775                                    loopExpr,
4776                                    newNode (GOTO,
4777                                        newAst_VALUE (symbolVal (condLabel)),
4778                                             NULL)));
4779   /* now start putting them together */
4780   forTree = newNode (NULLOP, initExpr, condExpr);
4781   forTree = newNode (NULLOP, forTree, forBody);
4782   forTree = newNode (NULLOP, forTree, loopExpr);
4783   /* finally add the break label */
4784   forTree = newNode (NULLOP, forTree,
4785                      createLabel (falseLabel, NULL));
4786   return forTree;
4787 }
4788
4789 /*-----------------------------------------------------------------*/
4790 /* createWhile - creates parse tree for while statement            */
4791 /*               the while statement will be created as follows    */
4792 /*                                                                 */
4793 /*      _while_continue_n:                                         */
4794 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4795 /*                                 |                               */
4796 /*                                 +-> falseLabel -> _while_break_n */
4797 /*      _while_body_n:                                             */
4798 /*            statements                                           */
4799 /*            goto _while_continue_n                               */
4800 /*      _while_break_n:                                            */
4801 /*-----------------------------------------------------------------*/
4802 ast *
4803 createWhile (symbol * trueLabel, symbol * continueLabel,
4804              symbol * falseLabel, ast * condExpr, ast * whileBody)
4805 {
4806   ast *whileTree;
4807
4808   /* put the continue label */
4809   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4810   condExpr = createLabel (continueLabel, condExpr);
4811   condExpr->lineno = 0;
4812
4813   /* put the body label in front of the body */
4814   whileBody = createLabel (trueLabel, whileBody);
4815   whileBody->lineno = 0;
4816   /* put a jump to continue at the end of the body */
4817   /* and put break label at the end of the body */
4818   whileBody = newNode (NULLOP,
4819                        whileBody,
4820                        newNode (GOTO,
4821                                 newAst_VALUE (symbolVal (continueLabel)),
4822                                 createLabel (falseLabel, NULL)));
4823
4824   /* put it all together */
4825   if (IS_IFX (condExpr))
4826     whileTree = condExpr;
4827   else
4828     {
4829       whileTree = newNode (IFX, condExpr, NULL);
4830       /* put the true & false labels in place */
4831       whileTree->trueLabel = trueLabel;
4832       whileTree->falseLabel = falseLabel;
4833     }
4834
4835   return newNode (NULLOP, whileTree, whileBody);
4836 }
4837
4838 /*-----------------------------------------------------------------*/
4839 /* optimizeGetHbit - get highest order bit of the expression       */
4840 /*-----------------------------------------------------------------*/
4841 ast *
4842 optimizeGetHbit (ast * tree)
4843 {
4844   int i, j;
4845   /* if this is not a bit and */
4846   if (!IS_BITAND (tree))
4847     return tree;
4848
4849   /* will look for tree of the form
4850      ( expr >> ((sizeof expr) -1) ) & 1 */
4851   if (!IS_AST_LIT_VALUE (tree->right))
4852     return tree;
4853
4854   if (AST_LIT_VALUE (tree->right) != 1)
4855     return tree;
4856
4857   if (!IS_RIGHT_OP (tree->left))
4858     return tree;
4859
4860   if (!IS_AST_LIT_VALUE (tree->left->right))
4861     return tree;
4862
4863   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4864       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4865     return tree;
4866       
4867   /* make sure the port supports GETHBIT */
4868   if (port->hasExtBitOp
4869       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4870     return tree;
4871
4872   return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_TYPE_NONE);
4873
4874 }
4875
4876 /*-----------------------------------------------------------------*/
4877 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4878 /*-----------------------------------------------------------------*/
4879 ast *
4880 optimizeRRCRLC (ast * root)
4881 {
4882   /* will look for trees of the form
4883      (?expr << 1) | (?expr >> 7) or
4884      (?expr >> 7) | (?expr << 1) will make that
4885      into a RLC : operation ..
4886      Will also look for
4887      (?expr >> 1) | (?expr << 7) or
4888      (?expr << 7) | (?expr >> 1) will make that
4889      into a RRC operation
4890      note : by 7 I mean (number of bits required to hold the
4891      variable -1 ) */
4892   /* if the root operations is not a | operation the not */
4893   if (!IS_BITOR (root))
4894     return root;
4895
4896   /* I have to think of a better way to match patterns this sucks */
4897   /* that aside let start looking for the first case : I use a the
4898      negative check a lot to improve the efficiency */
4899   /* (?expr << 1) | (?expr >> 7) */
4900   if (IS_LEFT_OP (root->left) &&
4901       IS_RIGHT_OP (root->right))
4902     {
4903
4904       if (!SPEC_USIGN (TETYPE (root->left->left)))
4905         return root;
4906
4907       if (!IS_AST_LIT_VALUE (root->left->right) ||
4908           !IS_AST_LIT_VALUE (root->right->right))
4909         goto tryNext0;
4910
4911       /* make sure it is the same expression */
4912       if (!isAstEqual (root->left->left,
4913                        root->right->left))
4914         goto tryNext0;
4915
4916       if (AST_LIT_VALUE (root->left->right) != 1)
4917         goto tryNext0;
4918
4919       if (AST_LIT_VALUE (root->right->right) !=
4920           (getSize (TTYPE (root->left->left)) * 8 - 1))
4921         goto tryNext0;
4922
4923       /* make sure the port supports RLC */
4924       if (port->hasExtBitOp
4925           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4926         return root;
4927
4928       /* whew got the first case : create the AST */
4929       return newNode (RLC, root->left->left, NULL);
4930     }
4931
4932 tryNext0:
4933   /* check for second case */
4934   /* (?expr >> 7) | (?expr << 1) */
4935   if (IS_LEFT_OP (root->right) &&
4936       IS_RIGHT_OP (root->left))
4937     {
4938
4939       if (!SPEC_USIGN (TETYPE (root->left->left)))
4940         return root;
4941
4942       if (!IS_AST_LIT_VALUE (root->left->right) ||
4943           !IS_AST_LIT_VALUE (root->right->right))
4944         goto tryNext1;
4945
4946       /* make sure it is the same symbol */
4947       if (!isAstEqual (root->left->left,
4948                        root->right->left))
4949         goto tryNext1;
4950
4951       if (AST_LIT_VALUE (root->right->right) != 1)
4952         goto tryNext1;
4953
4954       if (AST_LIT_VALUE (root->left->right) !=
4955           (getSize (TTYPE (root->left->left)) * 8 - 1))
4956         goto tryNext1;
4957
4958       /* make sure the port supports RLC */
4959       if (port->hasExtBitOp
4960           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4961         return root;
4962
4963       /* whew got the first case : create the AST */
4964       return newNode (RLC, root->left->left, NULL);
4965
4966     }
4967
4968 tryNext1:
4969   /* third case for RRC */
4970   /*  (?symbol >> 1) | (?symbol << 7) */
4971   if (IS_LEFT_OP (root->right) &&
4972       IS_RIGHT_OP (root->left))
4973     {
4974
4975       if (!SPEC_USIGN (TETYPE (root->left->left)))
4976         return root;
4977
4978       if (!IS_AST_LIT_VALUE (root->left->right) ||
4979           !IS_AST_LIT_VALUE (root->right->right))
4980         goto tryNext2;
4981
4982       /* make sure it is the same symbol */
4983       if (!isAstEqual (root->left->left,
4984                        root->right->left))
4985         goto tryNext2;
4986
4987       if (AST_LIT_VALUE (root->left->right) != 1)
4988         goto tryNext2;
4989
4990       if (AST_LIT_VALUE (root->right->right) !=
4991           (getSize (TTYPE (root->left->left)) * 8 - 1))
4992         goto tryNext2;
4993
4994       /* make sure the port supports RRC */
4995       if (port->hasExtBitOp
4996           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4997         return root;
4998
4999       /* whew got the first case : create the AST */
5000       return newNode (RRC, root->left->left, NULL);
5001
5002     }
5003 tryNext2:
5004   /* fourth and last case for now */
5005   /* (?symbol << 7) | (?symbol >> 1) */
5006   if (IS_RIGHT_OP (root->right) &&
5007       IS_LEFT_OP (root->left))
5008     {
5009
5010       if (!SPEC_USIGN (TETYPE (root->left->left)))
5011         return root;
5012
5013       if (!IS_AST_LIT_VALUE (root->left->right) ||
5014           !IS_AST_LIT_VALUE (root->right->right))
5015         return root;
5016
5017       /* make sure it is the same symbol */
5018       if (!isAstEqual (root->left->left,
5019                        root->right->left))
5020         return root;
5021
5022       if (AST_LIT_VALUE (root->right->right) != 1)
5023         return root;
5024
5025       if (AST_LIT_VALUE (root->left->right) !=
5026           (getSize (TTYPE (root->left->left)) * 8 - 1))
5027         return root;
5028
5029       /* make sure the port supports RRC */
5030       if (port->hasExtBitOp
5031           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5032         return root;
5033
5034       /* whew got the first case : create the AST */
5035       return newNode (RRC, root->left->left, NULL);
5036
5037     }
5038
5039   /* not found return root */
5040   return root;
5041 }
5042
5043 /*-----------------------------------------------------------------*/
5044 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5045 /*-----------------------------------------------------------------*/
5046 ast *
5047 optimizeSWAP (ast * root)
5048 {
5049   /* will look for trees of the form
5050      (?expr << 4) | (?expr >> 4) or
5051      (?expr >> 4) | (?expr << 4) will make that
5052      into a SWAP : operation ..
5053      note : by 4 I mean (number of bits required to hold the
5054      variable /2 ) */
5055   /* if the root operations is not a | operation the not */
5056   if (!IS_BITOR (root))
5057     return root;
5058
5059   /* (?expr << 4) | (?expr >> 4) */
5060   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5061       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5062     {
5063
5064       if (!SPEC_USIGN (TETYPE (root->left->left)))
5065         return root;
5066
5067       if (!IS_AST_LIT_VALUE (root->left->right) ||
5068           !IS_AST_LIT_VALUE (root->right->right))
5069         return root;
5070
5071       /* make sure it is the same expression */
5072       if (!isAstEqual (root->left->left,
5073                        root->right->left))
5074         return root;
5075
5076       if (AST_LIT_VALUE (root->left->right) !=
5077           (getSize (TTYPE (root->left->left)) * 4))
5078         return root;
5079
5080       if (AST_LIT_VALUE (root->right->right) !=
5081           (getSize (TTYPE (root->left->left)) * 4))
5082         return root;
5083
5084       /* make sure the port supports SWAP */
5085       if (port->hasExtBitOp
5086           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5087         return root;
5088
5089       /* found it : create the AST */
5090       return newNode (SWAP, root->left->left, NULL);
5091     }
5092
5093
5094   /* not found return root */
5095   return root;
5096 }
5097
5098 /*-----------------------------------------------------------------*/
5099 /* optimizeCompare - otimizes compares for bit variables     */
5100 /*-----------------------------------------------------------------*/
5101 static ast *
5102 optimizeCompare (ast * root)
5103 {
5104   ast *optExpr = NULL;
5105   value *vleft;
5106   value *vright;
5107   unsigned int litValue;
5108
5109   /* if nothing then return nothing */
5110   if (!root)
5111     return NULL;
5112
5113   /* if not a compare op then do leaves */
5114   if (!IS_COMPARE_OP (root))
5115     {
5116       root->left = optimizeCompare (root->left);
5117       root->right = optimizeCompare (root->right);
5118       return root;
5119     }
5120
5121   /* if left & right are the same then depending
5122      of the operation do */
5123   if (isAstEqual (root->left, root->right))
5124     {
5125       switch (root->opval.op)
5126         {
5127         case '>':
5128         case '<':
5129         case NE_OP:
5130           optExpr = newAst_VALUE (constVal ("0"));
5131           break;
5132         case GE_OP:
5133         case LE_OP:
5134         case EQ_OP:
5135           optExpr = newAst_VALUE (constVal ("1"));
5136           break;
5137         }
5138
5139       return decorateType (optExpr, RESULT_TYPE_NONE);
5140     }
5141
5142   vleft = (root->left->type == EX_VALUE ?
5143            root->left->opval.val : NULL);
5144
5145   vright = (root->right->type == EX_VALUE ?
5146             root->right->opval.val : NULL);
5147
5148   /* if left is a BITVAR in BITSPACE */
5149   /* and right is a LITERAL then opt- */
5150   /* imize else do nothing       */
5151   if (vleft && vright &&
5152       IS_BITVAR (vleft->etype) &&
5153       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5154       IS_LITERAL (vright->etype))
5155     {
5156
5157       /* if right side > 1 then comparison may never succeed */
5158       if ((litValue = (int) floatFromVal (vright)) > 1)
5159         {
5160           werror (W_BAD_COMPARE);
5161           goto noOptimize;
5162         }
5163
5164       if (litValue)
5165         {
5166           switch (root->opval.op)
5167             {
5168             case '>':           /* bit value greater than 1 cannot be */
5169               werror (W_BAD_COMPARE);
5170               goto noOptimize;
5171               break;
5172
5173             case '<':           /* bit value < 1 means 0 */
5174             case NE_OP:
5175               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5176               break;
5177
5178             case LE_OP: /* bit value <= 1 means no check */
5179               optExpr = newAst_VALUE (vright);
5180               break;
5181
5182             case GE_OP: /* bit value >= 1 means only check for = */
5183             case EQ_OP:
5184               optExpr = newAst_VALUE (vleft);
5185               break;
5186             }
5187         }
5188       else
5189         {                       /* literal is zero */
5190           switch (root->opval.op)
5191             {
5192             case '<':           /* bit value < 0 cannot be */
5193               werror (W_BAD_COMPARE);
5194               goto noOptimize;
5195               break;
5196
5197             case '>':           /* bit value > 0 means 1 */
5198             case NE_OP:
5199               optExpr = newAst_VALUE (vleft);
5200               break;
5201
5202             case LE_OP: /* bit value <= 0 means no check */
5203             case GE_OP: /* bit value >= 0 means no check */
5204               werror (W_BAD_COMPARE);
5205               goto noOptimize;
5206               break;
5207
5208             case EQ_OP: /* bit == 0 means ! of bit */
5209               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5210               break;
5211             }
5212         }
5213       return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5214     }                           /* end-of-if of BITVAR */
5215
5216 noOptimize:
5217   return root;
5218 }
5219 /*-----------------------------------------------------------------*/
5220 /* addSymToBlock : adds the symbol to the first block we find      */
5221 /*-----------------------------------------------------------------*/
5222 void 
5223 addSymToBlock (symbol * sym, ast * tree)
5224 {
5225   /* reached end of tree or a leaf */
5226   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5227     return;
5228
5229   /* found a block */
5230   if (IS_AST_OP (tree) &&
5231       tree->opval.op == BLOCK)
5232     {
5233
5234       symbol *lsym = copySymbol (sym);
5235
5236       lsym->next = AST_VALUES (tree, sym);
5237       AST_VALUES (tree, sym) = lsym;
5238       return;
5239     }
5240
5241   addSymToBlock (sym, tree->left);
5242   addSymToBlock (sym, tree->right);
5243 }
5244
5245 /*-----------------------------------------------------------------*/
5246 /* processRegParms - do processing for register parameters         */
5247 /*-----------------------------------------------------------------*/
5248 static void 
5249 processRegParms (value * args, ast * body)
5250 {
5251   while (args)
5252     {
5253       if (IS_REGPARM (args->etype))
5254         addSymToBlock (args->sym, body);
5255       args = args->next;
5256     }
5257 }
5258
5259 /*-----------------------------------------------------------------*/
5260 /* resetParmKey - resets the operandkeys for the symbols           */
5261 /*-----------------------------------------------------------------*/
5262 DEFSETFUNC (resetParmKey)
5263 {
5264   symbol *sym = item;
5265
5266   sym->key = 0;
5267   sym->defs = NULL;
5268   sym->uses = NULL;
5269   sym->remat = 0;
5270   return 1;
5271 }
5272
5273 /*-----------------------------------------------------------------*/
5274 /* createFunction - This is the key node that calls the iCode for  */
5275 /*                  generating the code for a function. Note code  */
5276 /*                  is generated function by function, later when  */
5277 /*                  add inter-procedural analysis this will change */
5278 /*-----------------------------------------------------------------*/
5279 ast *
5280 createFunction (symbol * name, ast * body)
5281 {
5282   ast *ex;
5283   symbol *csym;
5284   int stack = 0;
5285   sym_link *fetype;
5286   iCode *piCode = NULL;
5287
5288   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
5289     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
5290
5291   /* if check function return 0 then some problem */
5292   if (checkFunction (name, NULL) == 0)
5293     return NULL;
5294
5295   /* create a dummy block if none exists */
5296   if (!body)
5297     body = newNode (BLOCK, NULL, NULL);
5298
5299   noLineno++;
5300
5301   /* check if the function name already in the symbol table */
5302   if ((csym = findSym (SymbolTab, NULL, name->name)))
5303     {
5304       name = csym;
5305       /* special case for compiler defined functions
5306          we need to add the name to the publics list : this
5307          actually means we are now compiling the compiler
5308          support routine */
5309       if (name->cdef)
5310         {
5311           addSet (&publics, name);
5312         }
5313     }
5314   else
5315     {
5316       addSymChain (name);
5317       allocVariables (name);
5318     }
5319   name->lastLine = mylineno;
5320   currFunc = name;
5321
5322   /* set the stack pointer */
5323   stackPtr  = -port->stack.direction * port->stack.call_overhead;
5324   xstackPtr = -port->stack.direction * port->stack.call_overhead;
5325
5326   if (IFFUNC_ISISR (name->type))
5327     stackPtr -= port->stack.direction * port->stack.isr_overhead;
5328
5329   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
5330     {
5331       if (options.useXstack)
5332         xstackPtr -= port->stack.direction * port->stack.reent_overhead;
5333       else
5334         stackPtr  -= port->stack.direction * port->stack.reent_overhead;
5335     }
5336
5337   fetype = getSpec (name->type);        /* get the specifier for the function */
5338   /* if this is a reentrant function then */
5339   if (IFFUNC_ISREENT (name->type))
5340     reentrant++;
5341
5342   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
5343
5344   /* do processing for parameters that are passed in registers */
5345   processRegParms (FUNC_ARGS(name->type), body);
5346
5347   /* set the stack pointer */
5348   stackPtr = 0;
5349   xstackPtr = -1;
5350
5351   /* allocate & autoinit the block variables */
5352   processBlockVars (body, &stack, ALLOCATE);
5353
5354   /* save the stack information */
5355   if (options.useXstack)
5356     name->xstack = SPEC_STAK (fetype) = stack;
5357   else
5358     name->stack = SPEC_STAK (fetype) = stack;
5359
5360   /* name needs to be mangled */
5361   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
5362
5363   body = resolveSymbols (body); /* resolve the symbols */
5364   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
5365                                         
5366
5367   ex = newAst_VALUE (symbolVal (name)); /* create name */
5368   ex = newNode (FUNCTION, ex, body);
5369   ex->values.args = FUNC_ARGS(name->type);
5370   ex->decorated=1;
5371   if (options.dump_tree) PA(ex);
5372   if (fatalError)
5373     {
5374       werror (E_FUNC_NO_CODE, name->name);
5375       goto skipall;
5376     }
5377
5378   /* create the node & generate intermediate code */
5379   GcurMemmap = code;
5380   codeOutFile = code->oFile;
5381   piCode = iCodeFromAst (ex);
5382
5383   if (fatalError)
5384     {
5385       werror (E_FUNC_NO_CODE, name->name);
5386       goto skipall;
5387     }
5388
5389   eBBlockFromiCode (piCode);
5390
5391   /* if there are any statics then do them */
5392   if (staticAutos)
5393     {
5394       GcurMemmap = statsg;
5395       codeOutFile = statsg->oFile;
5396       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
5397       staticAutos = NULL;
5398     }
5399
5400 skipall:
5401
5402   /* dealloc the block variables */
5403   processBlockVars (body, &stack, DEALLOCATE);
5404   outputDebugStackSymbols();
5405   /* deallocate paramaters */
5406   deallocParms (FUNC_ARGS(name->type));
5407
5408   if (IFFUNC_ISREENT (name->type))
5409     reentrant--;
5410
5411   /* we are done freeup memory & cleanup */
5412   noLineno--;
5413   if (port->reset_labelKey) labelKey = 1;
5414   name->key = 0;
5415   FUNC_HASBODY(name->type) = 1;
5416   addSet (&operKeyReset, name);
5417   applyToSet (operKeyReset, resetParmKey);
5418
5419   if (options.debug)
5420     cdbStructBlock(1);
5421
5422   cleanUpLevel (LabelTab, 0);
5423   cleanUpBlock (StructTab, 1);
5424   cleanUpBlock (TypedefTab, 1);
5425
5426   xstack->syms = NULL;
5427   istack->syms = NULL;
5428   return NULL;
5429 }
5430
5431
5432 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5433 /*-----------------------------------------------------------------*/
5434 /* ast_print : prints the ast (for debugging purposes)             */
5435 /*-----------------------------------------------------------------*/
5436
5437 void ast_print (ast * tree, FILE *outfile, int indent)
5438 {
5439
5440         if (!tree) return ;
5441
5442         /* can print only decorated trees */
5443         if (!tree->decorated) return;
5444
5445         /* if any child is an error | this one is an error do nothing */
5446         if (tree->isError ||
5447             (tree->left && tree->left->isError) ||
5448             (tree->right && tree->right->isError)) {
5449                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5450         }
5451
5452
5453         /* print the line          */
5454         /* if not block & function */
5455         if (tree->type == EX_OP &&
5456             (tree->opval.op != FUNCTION &&
5457              tree->opval.op != BLOCK &&
5458              tree->opval.op != NULLOP)) {
5459         }
5460
5461         if (tree->opval.op == FUNCTION) {
5462                 int arg=0;
5463                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5464                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5465                         tree->left->opval.val->name, tree);
5466                 printTypeChain (tree->left->opval.val->type->next,outfile);
5467                 fprintf(outfile,") args (");
5468                 do {
5469                   if (arg) {
5470                     fprintf (outfile, ", ");
5471                   }
5472                   printTypeChain (args ? args->type : NULL, outfile);
5473                   arg++;
5474                   args= args ? args->next : NULL;
5475                 } while (args);
5476                 fprintf(outfile,")\n");
5477                 ast_print(tree->left,outfile,indent);
5478                 ast_print(tree->right,outfile,indent);
5479                 return ;
5480         }
5481         if (tree->opval.op == BLOCK) {
5482                 symbol *decls = tree->values.sym;
5483                 INDENT(indent,outfile);
5484                 fprintf(outfile,"{\n");
5485                 while (decls) {
5486                         INDENT(indent+2,outfile);
5487                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5488                                 decls->name, decls);
5489                         printTypeChain(decls->type,outfile);
5490                         fprintf(outfile,")\n");
5491
5492                         decls = decls->next;
5493                 }
5494                 ast_print(tree->right,outfile,indent+2);
5495                 INDENT(indent,outfile);
5496                 fprintf(outfile,"}\n");
5497                 return;
5498         }
5499         if (tree->opval.op == NULLOP) {
5500                 ast_print(tree->left,outfile,indent);
5501                 ast_print(tree->right,outfile,indent);
5502                 return ;
5503         }
5504         INDENT(indent,outfile);
5505
5506         /*------------------------------------------------------------------*/
5507         /*----------------------------*/
5508         /*   leaf has been reached    */
5509         /*----------------------------*/
5510         /* if this is of type value */
5511         /* just get the type        */
5512         if (tree->type == EX_VALUE) {
5513
5514                 if (IS_LITERAL (tree->opval.val->etype)) {
5515                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5516                         if (SPEC_USIGN (tree->opval.val->etype))
5517                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5518                         else
5519                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5520                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5521                                                       floatFromVal(tree->opval.val));
5522                 } else if (tree->opval.val->sym) {
5523                         /* if the undefined flag is set then give error message */
5524                         if (tree->opval.val->sym->undefined) {
5525                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5526                         } else {
5527                                 fprintf(outfile,"SYMBOL ");
5528                         }
5529                         fprintf(outfile,"(%s=%p)",
5530                                 tree->opval.val->sym->name,tree);
5531                 }
5532                 if (tree->ftype) {
5533                         fprintf(outfile," type (");
5534                         printTypeChain(tree->ftype,outfile);
5535                         fprintf(outfile,")\n");
5536                 } else {
5537                         fprintf(outfile,"\n");
5538                 }
5539                 return ;
5540         }
5541
5542         /* if type link for the case of cast */
5543         if (tree->type == EX_LINK) {
5544                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5545                 printTypeChain(tree->opval.lnk,outfile);
5546                 fprintf(outfile,")\n");
5547                 return ;
5548         }
5549
5550
5551         /* depending on type of operator do */
5552
5553         switch (tree->opval.op) {
5554                 /*------------------------------------------------------------------*/
5555                 /*----------------------------*/
5556                 /*        array node          */
5557                 /*----------------------------*/
5558         case '[':
5559                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5560                 printTypeChain(tree->ftype,outfile);
5561                 fprintf(outfile,")\n");
5562                 ast_print(tree->left,outfile,indent+2);
5563                 ast_print(tree->right,outfile,indent+2);
5564                 return;
5565
5566                 /*------------------------------------------------------------------*/
5567                 /*----------------------------*/
5568                 /*      struct/union          */
5569                 /*----------------------------*/
5570         case '.':
5571                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5572                 printTypeChain(tree->ftype,outfile);
5573                 fprintf(outfile,")\n");
5574                 ast_print(tree->left,outfile,indent+2);
5575                 ast_print(tree->right,outfile,indent+2);
5576                 return ;
5577
5578                 /*------------------------------------------------------------------*/
5579                 /*----------------------------*/
5580                 /*    struct/union pointer    */
5581                 /*----------------------------*/
5582         case PTR_OP:
5583                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5584                 printTypeChain(tree->ftype,outfile);
5585                 fprintf(outfile,")\n");
5586                 ast_print(tree->left,outfile,indent+2);
5587                 ast_print(tree->right,outfile,indent+2);
5588                 return ;
5589
5590                 /*------------------------------------------------------------------*/
5591                 /*----------------------------*/
5592                 /*  ++/-- operation           */
5593                 /*----------------------------*/
5594         case INC_OP:
5595                 if (tree->left)
5596                   fprintf(outfile,"post-");
5597                 else
5598                   fprintf(outfile,"pre-");
5599                 fprintf(outfile,"INC_OP (%p) type (",tree);
5600                 printTypeChain(tree->ftype,outfile);
5601                 fprintf(outfile,")\n");
5602                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5603                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5604                 return ;
5605
5606         case DEC_OP:
5607                 if (tree->left)
5608                   fprintf(outfile,"post-");
5609                 else
5610                   fprintf(outfile,"pre-");
5611                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5612                 printTypeChain(tree->ftype,outfile);
5613                 fprintf(outfile,")\n");
5614                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5615                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5616                 return ;
5617
5618                 /*------------------------------------------------------------------*/
5619                 /*----------------------------*/
5620                 /*  bitwise and               */
5621                 /*----------------------------*/
5622         case '&':
5623                 if (tree->right) {
5624                         fprintf(outfile,"& (%p) type (",tree);
5625                         printTypeChain(tree->ftype,outfile);
5626                         fprintf(outfile,")\n");
5627                         ast_print(tree->left,outfile,indent+2);
5628                         ast_print(tree->right,outfile,indent+2);
5629                 } else {
5630                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5631                         printTypeChain(tree->ftype,outfile);
5632                         fprintf(outfile,")\n");
5633                         ast_print(tree->left,outfile,indent+2);
5634                         ast_print(tree->right,outfile,indent+2);
5635                 }
5636                 return ;
5637                 /*----------------------------*/
5638                 /*  bitwise or                */
5639                 /*----------------------------*/
5640         case '|':
5641                 fprintf(outfile,"OR (%p) type (",tree);
5642                 printTypeChain(tree->ftype,outfile);
5643                 fprintf(outfile,")\n");
5644                 ast_print(tree->left,outfile,indent+2);
5645                 ast_print(tree->right,outfile,indent+2);
5646                 return ;
5647                 /*------------------------------------------------------------------*/
5648                 /*----------------------------*/
5649                 /*  bitwise xor               */
5650                 /*----------------------------*/
5651         case '^':
5652                 fprintf(outfile,"XOR (%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                 return ;
5658
5659                 /*------------------------------------------------------------------*/
5660                 /*----------------------------*/
5661                 /*  division                  */
5662                 /*----------------------------*/
5663         case '/':
5664                 fprintf(outfile,"DIV (%p) type (",tree);
5665                 printTypeChain(tree->ftype,outfile);
5666                 fprintf(outfile,")\n");
5667                 ast_print(tree->left,outfile,indent+2);
5668                 ast_print(tree->right,outfile,indent+2);
5669                 return ;
5670                 /*------------------------------------------------------------------*/
5671                 /*----------------------------*/
5672                 /*            modulus         */
5673                 /*----------------------------*/
5674         case '%':
5675                 fprintf(outfile,"MOD (%p) type (",tree);
5676                 printTypeChain(tree->ftype,outfile);
5677                 fprintf(outfile,")\n");
5678                 ast_print(tree->left,outfile,indent+2);
5679                 ast_print(tree->right,outfile,indent+2);
5680                 return ;
5681
5682                 /*------------------------------------------------------------------*/
5683                 /*----------------------------*/
5684                 /*  address dereference       */
5685                 /*----------------------------*/
5686         case '*':                       /* can be unary  : if right is null then unary operation */
5687                 if (!tree->right) {
5688                         fprintf(outfile,"DEREF (%p) type (",tree);
5689                         printTypeChain(tree->ftype,outfile);
5690                         fprintf(outfile,")\n");
5691                         ast_print(tree->left,outfile,indent+2);
5692                         return ;
5693                 }                       
5694                 /*------------------------------------------------------------------*/
5695                 /*----------------------------*/
5696                 /*      multiplication        */
5697                 /*----------------------------*/                
5698                 fprintf(outfile,"MULT (%p) type (",tree);
5699                 printTypeChain(tree->ftype,outfile);
5700                 fprintf(outfile,")\n");
5701                 ast_print(tree->left,outfile,indent+2);
5702                 ast_print(tree->right,outfile,indent+2);
5703                 return ;
5704
5705
5706                 /*------------------------------------------------------------------*/
5707                 /*----------------------------*/
5708                 /*    unary '+' operator      */
5709                 /*----------------------------*/
5710         case '+':
5711                 /* if unary plus */
5712                 if (!tree->right) {
5713                         fprintf(outfile,"UPLUS (%p) type (",tree);
5714                         printTypeChain(tree->ftype,outfile);
5715                         fprintf(outfile,")\n");
5716                         ast_print(tree->left,outfile,indent+2);
5717                 } else {
5718                         /*------------------------------------------------------------------*/
5719                         /*----------------------------*/
5720                         /*      addition              */
5721                         /*----------------------------*/
5722                         fprintf(outfile,"ADD (%p) type (",tree);
5723                         printTypeChain(tree->ftype,outfile);
5724                         fprintf(outfile,")\n");
5725                         ast_print(tree->left,outfile,indent+2);
5726                         ast_print(tree->right,outfile,indent+2);
5727                 }
5728                 return;
5729                 /*------------------------------------------------------------------*/
5730                 /*----------------------------*/
5731                 /*      unary '-'             */
5732                 /*----------------------------*/
5733         case '-':                       /* can be unary   */
5734                 if (!tree->right) {
5735                         fprintf(outfile,"UMINUS (%p) type (",tree);
5736                         printTypeChain(tree->ftype,outfile);
5737                         fprintf(outfile,")\n");
5738                         ast_print(tree->left,outfile,indent+2);
5739                 } else {
5740                         /*------------------------------------------------------------------*/
5741                         /*----------------------------*/
5742                         /*      subtraction           */
5743                         /*----------------------------*/
5744                         fprintf(outfile,"SUB (%p) type (",tree);
5745                         printTypeChain(tree->ftype,outfile);
5746                         fprintf(outfile,")\n");
5747                         ast_print(tree->left,outfile,indent+2);
5748                         ast_print(tree->right,outfile,indent+2);
5749                 }
5750                 return;
5751                 /*------------------------------------------------------------------*/
5752                 /*----------------------------*/
5753                 /*    compliment              */
5754                 /*----------------------------*/
5755         case '~':
5756                 fprintf(outfile,"COMPL (%p) type (",tree);
5757                 printTypeChain(tree->ftype,outfile);
5758                 fprintf(outfile,")\n");
5759                 ast_print(tree->left,outfile,indent+2);
5760                 return ;
5761                 /*------------------------------------------------------------------*/
5762                 /*----------------------------*/
5763                 /*           not              */
5764                 /*----------------------------*/
5765         case '!':
5766                 fprintf(outfile,"NOT (%p) type (",tree);
5767                 printTypeChain(tree->ftype,outfile);
5768                 fprintf(outfile,")\n");
5769                 ast_print(tree->left,outfile,indent+2);
5770                 return ;
5771                 /*------------------------------------------------------------------*/
5772                 /*----------------------------*/
5773                 /*           shift            */
5774                 /*----------------------------*/
5775         case RRC:
5776                 fprintf(outfile,"RRC (%p) type (",tree);
5777                 printTypeChain(tree->ftype,outfile);
5778                 fprintf(outfile,")\n");
5779                 ast_print(tree->left,outfile,indent+2);
5780                 return ;
5781
5782         case RLC:
5783                 fprintf(outfile,"RLC (%p) type (",tree);
5784                 printTypeChain(tree->ftype,outfile);
5785                 fprintf(outfile,")\n");
5786                 ast_print(tree->left,outfile,indent+2);
5787                 return ;
5788         case SWAP:
5789                 fprintf(outfile,"SWAP (%p) type (",tree);
5790                 printTypeChain(tree->ftype,outfile);
5791                 fprintf(outfile,")\n");
5792                 ast_print(tree->left,outfile,indent+2);
5793                 return ;
5794         case GETHBIT:
5795                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5796                 printTypeChain(tree->ftype,outfile);
5797                 fprintf(outfile,")\n");
5798                 ast_print(tree->left,outfile,indent+2);
5799                 return ;
5800         case LEFT_OP:
5801                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5802                 printTypeChain(tree->ftype,outfile);
5803                 fprintf(outfile,")\n");
5804                 ast_print(tree->left,outfile,indent+2);
5805                 ast_print(tree->right,outfile,indent+2);
5806                 return ;
5807         case RIGHT_OP:
5808                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5809                 printTypeChain(tree->ftype,outfile);
5810                 fprintf(outfile,")\n");
5811                 ast_print(tree->left,outfile,indent+2);
5812                 ast_print(tree->right,outfile,indent+2);
5813                 return ;
5814                 /*------------------------------------------------------------------*/
5815                 /*----------------------------*/
5816                 /*         casting            */
5817                 /*----------------------------*/
5818         case CAST:                      /* change the type   */
5819                 fprintf(outfile,"CAST (%p) from type (",tree);
5820                 printTypeChain(tree->right->ftype,outfile);
5821                 fprintf(outfile,") to type (");
5822                 printTypeChain(tree->ftype,outfile);
5823                 fprintf(outfile,")\n");
5824                 ast_print(tree->right,outfile,indent+2);
5825                 return ;
5826                 
5827         case AND_OP:
5828                 fprintf(outfile,"ANDAND (%p) type (",tree);
5829                 printTypeChain(tree->ftype,outfile);
5830                 fprintf(outfile,")\n");
5831                 ast_print(tree->left,outfile,indent+2);
5832                 ast_print(tree->right,outfile,indent+2);
5833                 return ;
5834         case OR_OP:
5835                 fprintf(outfile,"OROR (%p) type (",tree);
5836                 printTypeChain(tree->ftype,outfile);
5837                 fprintf(outfile,")\n");
5838                 ast_print(tree->left,outfile,indent+2);
5839                 ast_print(tree->right,outfile,indent+2);
5840                 return ;
5841                 
5842                 /*------------------------------------------------------------------*/
5843                 /*----------------------------*/
5844                 /*     comparison operators   */
5845                 /*----------------------------*/
5846         case '>':
5847                 fprintf(outfile,"GT(>) (%p) type (",tree);
5848                 printTypeChain(tree->ftype,outfile);
5849                 fprintf(outfile,")\n");
5850                 ast_print(tree->left,outfile,indent+2);
5851                 ast_print(tree->right,outfile,indent+2);
5852                 return ;
5853         case '<':
5854                 fprintf(outfile,"LT(<) (%p) type (",tree);
5855                 printTypeChain(tree->ftype,outfile);
5856                 fprintf(outfile,")\n");
5857                 ast_print(tree->left,outfile,indent+2);
5858                 ast_print(tree->right,outfile,indent+2);
5859                 return ;
5860         case LE_OP:
5861                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5862                 printTypeChain(tree->ftype,outfile);
5863                 fprintf(outfile,")\n");
5864                 ast_print(tree->left,outfile,indent+2);
5865                 ast_print(tree->right,outfile,indent+2);
5866                 return ;
5867         case GE_OP:
5868                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5869                 printTypeChain(tree->ftype,outfile);
5870                 fprintf(outfile,")\n");
5871                 ast_print(tree->left,outfile,indent+2);
5872                 ast_print(tree->right,outfile,indent+2);
5873                 return ;
5874         case EQ_OP:
5875                 fprintf(outfile,"EQ(==) (%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 NE_OP:
5882                 fprintf(outfile,"NE(!=) (%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                 /*------------------------------------------------------------------*/
5888                 /*----------------------------*/
5889                 /*             sizeof         */
5890                 /*----------------------------*/
5891         case SIZEOF:            /* evaluate wihout code generation */
5892                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5893                 return ;
5894
5895                 /*------------------------------------------------------------------*/
5896                 /*----------------------------*/
5897                 /* conditional operator  '?'  */
5898                 /*----------------------------*/
5899         case '?':
5900                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5901                 printTypeChain(tree->ftype,outfile);
5902                 fprintf(outfile,")\n");
5903                 ast_print(tree->left,outfile,indent+2);
5904                 ast_print(tree->right,outfile,indent+2);
5905                 return;
5906
5907         case ':':
5908                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5909                 printTypeChain(tree->ftype,outfile);
5910                 fprintf(outfile,")\n");
5911                 ast_print(tree->left,outfile,indent+2);
5912                 ast_print(tree->right,outfile,indent+2);
5913                 return ;
5914
5915                 /*------------------------------------------------------------------*/
5916                 /*----------------------------*/
5917                 /*    assignment operators    */
5918                 /*----------------------------*/
5919         case MUL_ASSIGN:
5920                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5921                 printTypeChain(tree->ftype,outfile);
5922                 fprintf(outfile,")\n");
5923                 ast_print(tree->left,outfile,indent+2);
5924                 ast_print(tree->right,outfile,indent+2);
5925                 return;
5926         case DIV_ASSIGN:
5927                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5928                 printTypeChain(tree->ftype,outfile);
5929                 fprintf(outfile,")\n");
5930                 ast_print(tree->left,outfile,indent+2);
5931                 ast_print(tree->right,outfile,indent+2);
5932                 return;
5933         case AND_ASSIGN:
5934                 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
5935                 printTypeChain(tree->ftype,outfile);
5936                 fprintf(outfile,")\n");
5937                 ast_print(tree->left,outfile,indent+2);
5938                 ast_print(tree->right,outfile,indent+2);
5939                 return;
5940         case OR_ASSIGN:
5941                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5942                 printTypeChain(tree->ftype,outfile);
5943                 fprintf(outfile,")\n");
5944                 ast_print(tree->left,outfile,indent+2);
5945                 ast_print(tree->right,outfile,indent+2);
5946                 return;
5947         case XOR_ASSIGN:
5948                 fprintf(outfile,"XORASS(^=) (%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 RIGHT_ASSIGN:
5955                 fprintf(outfile,"RSHFTASS(>>=) (%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 LEFT_ASSIGN:
5962                 fprintf(outfile,"LSHFTASS(<<=) (%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                 /*------------------------------------------------------------------*/
5969                 /*----------------------------*/
5970                 /*    -= operator             */
5971                 /*----------------------------*/
5972         case SUB_ASSIGN:
5973                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5974                 printTypeChain(tree->ftype,outfile);
5975                 fprintf(outfile,")\n");
5976                 ast_print(tree->left,outfile,indent+2);
5977                 ast_print(tree->right,outfile,indent+2);
5978                 return;
5979                 /*------------------------------------------------------------------*/
5980                 /*----------------------------*/
5981                 /*          += operator       */
5982                 /*----------------------------*/
5983         case ADD_ASSIGN:
5984                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5985                 printTypeChain(tree->ftype,outfile);
5986                 fprintf(outfile,")\n");
5987                 ast_print(tree->left,outfile,indent+2);
5988                 ast_print(tree->right,outfile,indent+2);
5989                 return;
5990                 /*------------------------------------------------------------------*/
5991                 /*----------------------------*/
5992                 /*      straight assignemnt   */
5993                 /*----------------------------*/
5994         case '=':
5995                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5996                 printTypeChain(tree->ftype,outfile);
5997                 fprintf(outfile,")\n");
5998                 ast_print(tree->left,outfile,indent+2);
5999                 ast_print(tree->right,outfile,indent+2);
6000                 return;     
6001                 /*------------------------------------------------------------------*/
6002                 /*----------------------------*/
6003                 /*      comma operator        */
6004                 /*----------------------------*/
6005         case ',':
6006                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
6007                 printTypeChain(tree->ftype,outfile);
6008                 fprintf(outfile,")\n");
6009                 ast_print(tree->left,outfile,indent+2);
6010                 ast_print(tree->right,outfile,indent+2);
6011                 return;
6012                 /*------------------------------------------------------------------*/
6013                 /*----------------------------*/
6014                 /*       function call        */
6015                 /*----------------------------*/
6016         case CALL:
6017         case PCALL:
6018                 fprintf(outfile,"CALL (%p) type (",tree);
6019                 printTypeChain(tree->ftype,outfile);
6020                 fprintf(outfile,")\n");
6021                 ast_print(tree->left,outfile,indent+2);
6022                 ast_print(tree->right,outfile,indent+2);
6023                 return;
6024         case PARAM:
6025                 fprintf(outfile,"PARMS\n");
6026                 ast_print(tree->left,outfile,indent+2);
6027                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
6028                         ast_print(tree->right,outfile,indent+2);
6029                 }
6030                 return ;
6031                 /*------------------------------------------------------------------*/
6032                 /*----------------------------*/
6033                 /*     return statement       */
6034                 /*----------------------------*/
6035         case RETURN:
6036                 fprintf(outfile,"RETURN (%p) type (",tree);
6037                 if (tree->right) {
6038                     printTypeChain(tree->right->ftype,outfile);
6039                 }
6040                 fprintf(outfile,")\n");
6041                 ast_print(tree->right,outfile,indent+2);
6042                 return ;
6043                 /*------------------------------------------------------------------*/
6044                 /*----------------------------*/
6045                 /*     label statement        */
6046                 /*----------------------------*/
6047         case LABEL :
6048                 fprintf(outfile,"LABEL (%p)\n",tree);
6049                 ast_print(tree->left,outfile,indent+2);
6050                 ast_print(tree->right,outfile,indent);
6051                 return;
6052                 /*------------------------------------------------------------------*/
6053                 /*----------------------------*/
6054                 /*     switch statement       */
6055                 /*----------------------------*/
6056         case SWITCH:
6057                 {
6058                         value *val;
6059                         fprintf(outfile,"SWITCH (%p) ",tree);
6060                         ast_print(tree->left,outfile,0);
6061                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
6062                                 INDENT(indent+2,outfile);
6063                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
6064                                         (int) floatFromVal(val),
6065                                         tree->values.switchVals.swNum,
6066                                         (int) floatFromVal(val));
6067                         }
6068                         ast_print(tree->right,outfile,indent);
6069                 }
6070                 return ;
6071                 /*------------------------------------------------------------------*/
6072                 /*----------------------------*/
6073                 /* ifx Statement              */
6074                 /*----------------------------*/
6075         case IFX:
6076                 fprintf(outfile,"IF (%p) \n",tree);
6077                 ast_print(tree->left,outfile,indent+2);
6078                 if (tree->trueLabel) {
6079                         INDENT(indent+2,outfile);
6080                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
6081                 }
6082                 if (tree->falseLabel) {
6083                         INDENT(indent+2,outfile);
6084                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
6085                 }
6086                 ast_print(tree->right,outfile,indent+2);
6087                 return ;
6088                 /*----------------------------*/
6089                 /* goto Statement              */
6090                 /*----------------------------*/
6091         case GOTO:
6092                 fprintf(outfile,"GOTO (%p) \n",tree);
6093                 ast_print(tree->left,outfile,indent+2);
6094                 fprintf(outfile,"\n");
6095                 return ;
6096                 /*------------------------------------------------------------------*/
6097                 /*----------------------------*/
6098                 /* for Statement              */
6099                 /*----------------------------*/
6100         case FOR:
6101                 fprintf(outfile,"FOR (%p) \n",tree);
6102                 if (AST_FOR( tree, initExpr)) {
6103                         INDENT(indent+2,outfile);
6104                         fprintf(outfile,"INIT EXPR ");
6105                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
6106                 }
6107                 if (AST_FOR( tree, condExpr)) {
6108                         INDENT(indent+2,outfile);
6109                         fprintf(outfile,"COND EXPR ");
6110                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
6111                 }
6112                 if (AST_FOR( tree, loopExpr)) {
6113                         INDENT(indent+2,outfile);
6114                         fprintf(outfile,"LOOP EXPR ");
6115                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
6116                 }
6117                 fprintf(outfile,"FOR LOOP BODY \n");
6118                 ast_print(tree->left,outfile,indent+2);
6119                 return ;
6120         case CRITICAL:
6121                 fprintf(outfile,"CRITICAL (%p) \n",tree);
6122                 ast_print(tree->left,outfile,indent+2);
6123         default:
6124             return ;
6125         }
6126 }
6127
6128 void PA(ast *t)
6129 {
6130         ast_print(t,stdout,0);
6131 }
6132
6133
6134
6135 /*-----------------------------------------------------------------*/
6136 /* astErrors : returns non-zero if errors present in tree          */
6137 /*-----------------------------------------------------------------*/
6138 int astErrors(ast *t)
6139 {
6140   int errors=0;
6141   
6142   if (t)
6143     {
6144       if (t->isError)
6145         errors++;
6146   
6147       if (t->type == EX_VALUE
6148           && t->opval.val->sym
6149           && t->opval.val->sym->undefined)
6150         errors++;
6151
6152       errors += astErrors(t->left);
6153       errors += astErrors(t->right);
6154     }
6155     
6156   return errors;
6157 }