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