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