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