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