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