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