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