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