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