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