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