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