constVal() now returns the cheapest val as possible
[fw/sdcc] / src / SDCCval.c
1 /*----------------------------------------------------------------------
2     SDCCval.c :- has routine to do all kinds of fun stuff with the
3                 value wrapper & with initialiser lists.
4
5     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6
7     This program is free software; you can redistribute it and/or modify it
8     under the terms of the GNU General Public License as published by the
9     Free Software Foundation; either version 2, or (at your option) any
10     later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21     In other words, you are welcome to use, share and improve this program.
22     You are forbidden to forbid anyone else to use, share and improve
23     what you give them.   Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
25
26 #include "common.h"
27 #include <math.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include "newalloc.h"
31
32 int cNestLevel;
33
34 /*-----------------------------------------------------------------*/
35 /* newValue - allocates and returns a new value        */
36 /*-----------------------------------------------------------------*/
37 value *
38 newValue ()
39 {
40   value *val;
41
42   val = Safe_calloc (1, sizeof (value));
43
44   return val;
45 }
46
47 /*-----------------------------------------------------------------*/
48 /* newiList - new initializer list                                 */
49 /*-----------------------------------------------------------------*/
50 initList *
51 newiList (int type, void *ilist)
52 {
53   initList *nilist;
54
55
56   nilist = Safe_calloc (1, sizeof (initList));
57
58   nilist->type = type;
59   nilist->lineno = yylineno;
60
61   switch (type)
62     {
63     case INIT_NODE:
64       nilist->init.node = (struct ast *) ilist;
65       break;
66
67     case INIT_DEEP:
68       nilist->init.deep = (struct initList *) ilist;
69       break;
70     }
71
72   return nilist;
73 }
74
75 /*------------------------------------------------------------------*/
76 /* revinit   - reverses the initial values for a value  chain        */
77 /*------------------------------------------------------------------*/
78 initList *
79 revinit (initList * val)
80 {
81   initList *prev, *curr, *next;
82
83   if (!val)
84     return NULL;
85
86   prev = val;
87   curr = val->next;
88
89   while (curr)
90     {
91       next = curr->next;
92       curr->next = prev;
93       prev = curr;
94       curr = next;
95     }
96   val->next = (void *) NULL;
97   return prev;
98 }
99
100 bool
101 convertIListToConstList(initList *src, literalList **lList)
102 {
103     initList    *iLoop;
104     literalList *head, *last, *newL;
105     
106     head = last = NULL;
107     
108     if (!src || src->type != INIT_DEEP)
109     {
110         return FALSE;
111     }
112     
113     iLoop =  src->init.deep;
114     
115     while (iLoop)
116     {
117         if (iLoop->type != INIT_NODE)
118         {
119             return FALSE;
120         }
121         
122         if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node))))
123         {
124             return FALSE;
125         }
126         iLoop = iLoop->next;
127     }
128     
129     // We've now established that the initializer list contains only literal values.
130     
131     iLoop = src->init.deep;
132     while (iLoop)
133     {
134         double val = AST_LIT_VALUE(iLoop->init.node);
135         
136         if (last && last->literalValue == val)
137         {
138             last->count++;
139         }
140         else
141         {
142             newL = Safe_malloc(sizeof(literalList));
143             newL->literalValue = val;
144             newL->count = 1;
145             newL->next = NULL;
146             
147             if (last)
148             {
149                 last->next = newL;
150             }
151             else
152             {
153                 head = newL;
154             }
155             last = newL;
156         }
157         iLoop = iLoop->next;
158     }
159     
160     if (!head)    
161     {
162         return FALSE;
163     }
164     
165     *lList = head;
166     return TRUE;
167 }
168
169 literalList *
170 copyLiteralList(literalList *src)
171 {
172     literalList *head, *prev, *newL;
173     
174     head = prev = NULL;
175     
176     while (src)
177     {
178         newL = Safe_malloc(sizeof(literalList));
179         
180         newL->literalValue = src->literalValue;
181         newL->count = src->count;
182         newL->next = NULL;
183         
184         if (prev)
185         {
186             prev->next = newL;
187         }
188         else
189         {
190             head = newL;
191         }
192         prev = newL;
193         src = src->next;
194     }
195     
196     return head;
197 }
198
199
200
201 /*------------------------------------------------------------------*/
202 /* copyIlist - copy initializer list            */
203 /*------------------------------------------------------------------*/
204 initList *
205 copyIlist (initList * src)
206 {
207   initList *dest = NULL;
208
209   if (!src)
210     return NULL;
211
212   switch (src->type)
213     {
214     case INIT_DEEP:
215       dest = newiList (INIT_DEEP, copyIlist (src->init.deep));
216       break;
217     case INIT_NODE:
218       dest = newiList (INIT_NODE, copyAst (src->init.node));
219       break;
220     }
221
222   if (src->next)
223     dest->next = copyIlist (src->next);
224
225   return dest;
226 }
227
228 /*------------------------------------------------------------------*/
229 /* list2int - converts the first element of the list to value       */
230 /*------------------------------------------------------------------*/
231 double 
232 list2int (initList * val)
233 {
234   initList *i = val;
235
236   if (i->type == INIT_DEEP)
237     return list2int (val->init.deep);
238
239   return floatFromVal (constExprValue (val->init.node, TRUE));
240 }
241
242 /*------------------------------------------------------------------*/
243 /* list2val - converts the first element of the list to value       */
244 /*------------------------------------------------------------------*/
245 value *
246 list2val (initList * val)
247 {
248   if (!val)
249     return NULL;
250
251   if (val->type == INIT_DEEP)
252     return list2val (val->init.deep);
253
254   return constExprValue (val->init.node, TRUE);
255 }
256
257 /*------------------------------------------------------------------*/
258 /* list2expr - returns the first expression in the initializer list */
259 /*------------------------------------------------------------------*/
260 ast *
261 list2expr (initList * ilist)
262 {
263   if (ilist->type == INIT_DEEP)
264     return list2expr (ilist->init.deep);
265   return ilist->init.node;
266 }
267
268 /*------------------------------------------------------------------*/
269 /* resolveIvalSym - resolve symbols in initial values               */
270 /*------------------------------------------------------------------*/
271 void 
272 resolveIvalSym (initList * ilist)
273 {
274   if (!ilist)
275     return;
276
277   if (ilist->type == INIT_NODE)
278     ilist->init.node = decorateType (resolveSymbols (ilist->init.node));
279
280   if (ilist->type == INIT_DEEP)
281     resolveIvalSym (ilist->init.deep);
282
283   resolveIvalSym (ilist->next);
284 }
285
286 /*-----------------------------------------------------------------*/
287 /* symbolVal - creates a value for a symbol              */
288 /*-----------------------------------------------------------------*/
289 value *
290 symbolVal (symbol * sym)
291 {
292   value *val;
293
294   if (!sym)
295     return NULL;
296
297   val = newValue ();
298   val->sym = sym;
299
300   if (sym->type)
301     {
302       val->type = sym->type;
303       val->etype = getSpec (val->type);
304     }
305
306   if (*sym->rname)
307     sprintf (val->name, "%s", sym->rname);
308   else
309     sprintf (val->name, "_%s", sym->name);
310
311
312   return val;
313 }
314
315 /*-----------------------------------------------------------------*/
316 /* valueFromLit - creates a value from a literal                   */
317 /*-----------------------------------------------------------------*/
318 value *
319 valueFromLit (double lit)
320 {
321   char buffer[50];
322
323   if ((((long) lit) - lit) == 0)
324     {
325       sprintf (buffer, "%ld", (long) lit);
326       return constVal (buffer);
327     }
328
329   sprintf (buffer, "%f", lit);
330   return constFloatVal (buffer);
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* constFloatVal - converts a FLOAT constant to value              */
335 /*-----------------------------------------------------------------*/
336 value *
337 constFloatVal (char *s)
338 {
339   value *val = newValue ();
340   float sval;
341
342   if (sscanf (s, "%f", &sval) != 1)
343     {
344       werror (E_INVALID_FLOAT_CONST, s);
345       return constVal ("0");
346     }
347
348   val->type = val->etype = newLink ();
349   val->type->class = SPECIFIER;
350   SPEC_NOUN (val->type) = V_FLOAT;
351   SPEC_SCLS (val->type) = S_LITERAL;
352   SPEC_CVAL (val->type).v_float = sval;
353
354   return val;
355 }
356
357 /*-----------------------------------------------------------------*/
358 /* constVal - converts an INTEGER constant into a cheapest value   */
359 /*-----------------------------------------------------------------*/
360 value *constVal (char *s)
361 {
362   value *val;
363   short hex = 0, octal = 0;
364   char scanFmt[10];
365   int scI = 0;
366   unsigned long sval;
367
368   val = newValue ();            /* alloc space for value   */
369
370   val->type = val->etype = newLink ();  /* create the spcifier */
371   val->type->class = SPECIFIER;
372   SPEC_SCLS (val->type) = S_LITERAL;
373   // let's start with an unsigned char
374   SPEC_NOUN (val->type) = V_CHAR;
375   SPEC_USIGN (val->type) = 1;
376
377   /* set the _long flag if 'lL' is found */
378   if (strchr (s, 'l') || strchr (s, 'L'))
379     SPEC_LONG (val->type) = 1;
380
381   hex = ((strchr (s, 'x') || strchr (s, 'X')) ? 1 : 0);
382
383   /* set the octal flag   */
384   if (!hex && *s == '0' && *(s + 1))
385     octal = 1;
386
387   /* create the scan string */
388   scanFmt[scI++] = '%';
389
390   if (octal)
391     scanFmt[scI++] = 'o';
392   else if (hex)
393     scanFmt[scI++] = 'x';
394   else
395     scanFmt[scI++] = 'd';
396
397   scanFmt[scI++] = 'L';
398   scanFmt[scI++] = '\0';
399
400   sscanf (s, scanFmt, &sval);
401
402   if (sval<0) { // "-28u" will still be signed and negative
403     SPEC_USIGN (val->type) = 0;
404     if (sval<-32768) { // check if have to promote to long
405       SPEC_NOUN (val->type) = V_INT;
406       SPEC_LONG (val->type) = 1;
407       SPEC_CVAL (val->type).v_long=sval;
408     } else {
409       SPEC_CVAL (val->type).v_int=sval;
410       if (sval<-128) { // check if we have to promote to int
411         SPEC_NOUN (val->type) = V_INT;
412       }
413     }
414   } else {
415     if (sval>0xffff) { // check if we have to promote to long
416       SPEC_NOUN (val->type) = V_INT;
417       SPEC_LONG (val->type) = 1;
418       SPEC_CVAL (val->type).v_ulong=sval;
419     } else {
420       SPEC_CVAL (val->type).v_uint=sval;
421       if (sval>0xff) { // check if we have to promote to int
422         SPEC_NOUN (val->type) = V_INT;
423       }
424     }
425   }
426
427   return val;
428 }
429
430 /*! /fn char hexEscape(char **src)
431
432     /param src Pointer to 'x' from start of hex character value
433 */
434
435 char hexEscape(char **src)
436
437 {
438 char *s ;
439 unsigned long value ;
440
441 (*src)++ ;      /* Skip over the 'x' */
442 s = *src ;      /* Save for error detection */
443
444 value = strtol (*src, src, 16);
445
446 if (s == *src) 
447   {
448   // no valid hex found
449   werror(E_INVALID_HEX);
450   } 
451
452 else 
453   {
454   if (value > 255) 
455     {
456     werror(W_ESC_SEQ_OOR_FOR_CHAR);
457     }
458   }
459
460 return (char) value;
461 }
462 /*------------------------------------------------------------------*/
463 /* octalEscape - process an octal constant of max three digits      */
464 /* return the octal value, throw a warning for illegal octal        */
465 /* adjust src to point at the last proccesed char                   */
466 /*------------------------------------------------------------------*/
467
468 char octalEscape (char **str) {
469   int digits;
470   unsigned value=0;
471
472   for (digits=0; digits<3; digits++) {
473     if (**str>='0' && **str<='7') {
474       value = value*8 + (**str-'0');
475       (*str)++;
476     } else {
477       break;
478     }
479   }
480   if (digits) {
481     if (value > 255 /* || (**str>='0' && **str<='7') */ ) {
482       werror (W_ESC_SEQ_OOR_FOR_CHAR);
483     }
484   }
485   return value;
486 }
487
488 /*! 
489   /fn int copyStr (char *dest, char *src)
490   
491   Copies a source string to a dest buffer interpreting escape sequences
492   and special characters
493
494   /param dest Buffer to receive the resultant string
495   /param src  Buffer containing the source string with escape sequecnes
496   /return Number of characters in output string
497
498 */
499
500 int 
501 copyStr (char *dest, char *src)
502
503 {
504   char *OriginalDest = dest ;
505
506   while (*src)
507     {
508       if (*src == '\"')
509         src++;
510       else if (*src == '\\')
511         {
512           src++;
513           switch (*src)
514             {
515             case 'n':
516               *dest++ = '\n';
517               break;
518             case 't':
519               *dest++ = '\t';
520               break;
521             case 'v':
522               *dest++ = '\v';
523               break;
524             case 'b':
525               *dest++ = '\b';
526               break;
527             case 'r':
528               *dest++ = '\r';
529               break;
530             case 'f':
531               *dest++ = '\f';
532               break;
533             case 'a':
534               *dest++ = '\a';
535               break;
536
537             case '0':
538             case '1':
539             case '2':
540             case '3':
541             case '4':
542             case '5':
543             case '6':
544             case '7':
545               *dest++ = octalEscape(&src);
546               src-- ;
547               break;
548
549             case 'x': 
550               *dest++ = hexEscape(&src) ;
551               src-- ;
552               break ;
553
554             case '\\':
555               *dest++ = '\\';
556               break;
557             case '\?':
558               *dest++ = '\?';
559               break;
560             case '\'':
561               *dest++ = '\'';
562               break;
563             case '\"':
564               *dest++ = '\"';
565               break;
566             default:
567               *dest++ = *src;
568             }
569           src++;
570         }
571       else
572         *dest++ = *src++;
573     }
574
575   *dest++ = '\0';
576
577   return dest - OriginalDest ;
578 }
579
580 /*------------------------------------------------------------------*/
581 /* strVal - converts a string constant to a value       */
582 /*------------------------------------------------------------------*/
583 value *
584 strVal (char *s)
585 {
586   value *val;
587
588   val = newValue ();            /* get a new one */
589
590   /* get a declarator */
591   val->type = newLink ();
592   DCL_TYPE (val->type) = ARRAY;
593   val->type->next = val->etype = newLink ();
594   val->etype->class = SPECIFIER;
595   SPEC_NOUN (val->etype) = V_CHAR;
596   SPEC_SCLS (val->etype) = S_LITERAL;
597
598   SPEC_CVAL (val->etype).v_char = Safe_calloc (1, strlen (s) + 1);
599   DCL_ELEM (val->type) = copyStr (SPEC_CVAL (val->etype).v_char, s);
600
601   return val;
602 }
603
604
605 /*------------------------------------------------------------------*/
606 /* reverseValWithType - reverses value chain with type & etype      */
607 /*------------------------------------------------------------------*/
608 value *
609 reverseValWithType (value * val)
610 {
611   sym_link *type;
612   sym_link *etype;
613
614   if (!val)
615     return NULL;
616
617   /* save the type * etype chains */
618   type = val->type;
619   etype = val->etype;
620
621   /* set the current one 2b null */
622   val->type = val->etype = NULL;
623   val = reverseVal (val);
624
625   /* restore type & etype */
626   val->type = type;
627   val->etype = etype;
628
629   return val;
630 }
631
632 /*------------------------------------------------------------------*/
633 /* reverseVal - reverses the values for a value  chain        */
634 /*------------------------------------------------------------------*/
635 value *
636 reverseVal (value * val)
637 {
638   value *prev, *curr, *next;
639
640   if (!val)
641     return NULL;
642
643   prev = val;
644   curr = val->next;
645
646   while (curr)
647     {
648       next = curr->next;
649       curr->next = prev;
650       prev = curr;
651       curr = next;
652     }
653   val->next = (void *) NULL;
654   return prev;
655 }
656
657 /*------------------------------------------------------------------*/
658 /* copyValueChain - will copy a chain of values                     */
659 /*------------------------------------------------------------------*/
660 value *
661 copyValueChain (value * src)
662 {
663   value *dest;
664
665   if (!src)
666     return NULL;
667
668   dest = copyValue (src);
669   dest->next = copyValueChain (src->next);
670
671   return dest;
672 }
673
674 /*------------------------------------------------------------------*/
675 /* copyValue - copies contents of a vlue to a fresh one             */
676 /*------------------------------------------------------------------*/
677 value *
678 copyValue (value * src)
679 {
680   value *dest;
681
682   dest = newValue ();
683   dest->sym = copySymbol (src->sym);
684   strcpy (dest->name, src->name);
685   dest->type = (src->type ? copyLinkChain (src->type) : NULL);
686   dest->etype = (src->type ? getSpec (dest->type) : NULL);
687
688   return dest;
689 }
690
691 /*------------------------------------------------------------------*/
692 /* charVal - converts a character constant to a value       */
693 /*------------------------------------------------------------------*/
694 value *
695 charVal (char *s)
696 {
697   value *val;
698 //  unsigned uValue ;
699
700   val = newValue ();
701
702   val->type = val->etype = newLink ();
703   val->type->class = SPECIFIER;
704   SPEC_NOUN (val->type) = V_CHAR;
705   SPEC_USIGN(val->type) = 1;
706   SPEC_SCLS (val->type) = S_LITERAL;
707
708   s++;                          /* get rid of quotation */
709   /* if \ then special processing */
710   if (*s == '\\')
711     {
712       s++;                      /* go beyond the backslash  */
713       switch (*s)
714         {
715         case 'n':
716           SPEC_CVAL (val->type).v_int = '\n';
717           break;
718         case 't':
719           SPEC_CVAL (val->type).v_int = '\t';
720           break;
721         case 'v':
722           SPEC_CVAL (val->type).v_int = '\v';
723           break;
724         case 'b':
725           SPEC_CVAL (val->type).v_int = '\b';
726           break;
727         case 'r':
728           SPEC_CVAL (val->type).v_int = '\r';
729           break;
730         case 'f':
731           SPEC_CVAL (val->type).v_int = '\f';
732           break;
733         case 'a':
734           SPEC_CVAL (val->type).v_int = '\a';
735           break;
736         case '\\':
737           SPEC_CVAL (val->type).v_int = '\\';
738           break;
739         case '\?':
740           SPEC_CVAL (val->type).v_int = '\?';
741           break;
742         case '\'':
743           SPEC_CVAL (val->type).v_int = '\'';
744           break;
745         case '\"':
746           SPEC_CVAL (val->type).v_int = '\"';
747           break;
748
749         case '0' :
750         case '1' :
751         case '2' :
752         case '3' :
753         case '4' :
754         case '5' :
755         case '6' :
756         case '7' :
757           SPEC_CVAL (val->type).v_int = octalEscape(&s);
758           break;
759
760         case 'x':
761           SPEC_CVAL (val->type).v_int = hexEscape(&s) ;
762           break;
763
764         default:
765           SPEC_CVAL (val->type).v_int = *s;
766           break;
767         }
768     }
769   else                          /* not a backslash */
770     SPEC_CVAL (val->type).v_int = *s;
771
772   return val;
773 }
774
775 /*------------------------------------------------------------------*/
776 /* valFromType - creates a value from type given                    */
777 /*------------------------------------------------------------------*/
778 value *
779 valFromType (sym_link * type)
780 {
781   value *val = newValue ();
782   val->type = copyLinkChain (type);
783   val->etype = getSpec (val->type);
784   return val;
785 }
786
787 /*------------------------------------------------------------------*/
788 /* floatFromVal - value to unsinged integer conversion        */
789 /*------------------------------------------------------------------*/
790 double 
791 floatFromVal (value * val)
792 {
793   if (!val)
794     return 0;
795
796   if (val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
797     {
798       werror (E_CONST_EXPECTED, val->name);
799       return 0;
800     }
801
802   /* if it is not a specifier then we can assume that */
803   /* it will be an unsigned long                      */
804   if (!IS_SPEC (val->type))
805     return (double) SPEC_CVAL (val->etype).v_ulong;
806
807   if (SPEC_NOUN (val->etype) == V_FLOAT)
808     return (double) SPEC_CVAL (val->etype).v_float;
809   else
810     {
811       if (SPEC_LONG (val->etype))
812         {
813           if (SPEC_USIGN (val->etype))
814             return (double) SPEC_CVAL (val->etype).v_ulong;
815           else
816             return (double) SPEC_CVAL (val->etype).v_long;
817         }
818       else
819         {
820           if (SPEC_USIGN (val->etype))
821             return (double) SPEC_CVAL (val->etype).v_uint;
822           else
823             return (double) SPEC_CVAL (val->etype).v_int;
824         }
825     }
826 }
827
828
829 /*------------------------------------------------------------------*/
830 /* valUnaryPM - dones the unary +/- operation on a constant         */
831 /*------------------------------------------------------------------*/
832 value *
833 valUnaryPM (value * val)
834 {
835   /* depending on type */
836   if (SPEC_NOUN (val->etype) == V_FLOAT)
837     SPEC_CVAL (val->etype).v_float = -1.0 * SPEC_CVAL (val->etype).v_float;
838   else
839     {
840       if (SPEC_LONG (val->etype))
841         {
842           if (SPEC_USIGN (val->etype))
843             SPEC_CVAL (val->etype).v_ulong = 0-SPEC_CVAL (val->etype).v_ulong;
844           else
845             SPEC_CVAL (val->etype).v_long = -SPEC_CVAL (val->etype).v_long;
846         }
847       else
848         {
849           if (SPEC_USIGN (val->etype))
850             SPEC_CVAL (val->etype).v_uint = 0-SPEC_CVAL (val->etype).v_uint;
851           else
852             SPEC_CVAL (val->etype).v_int = -SPEC_CVAL (val->etype).v_int;
853         }
854     }
855   return val;
856
857 }
858
859 /*------------------------------------------------------------------*/
860 /* valueComplement - complements a constant                         */
861 /*------------------------------------------------------------------*/
862 value *
863 valComplement (value * val)
864 {
865   /* depending on type */
866   if (SPEC_LONG (val->etype))
867     {
868       if (SPEC_USIGN (val->etype))
869         SPEC_CVAL (val->etype).v_ulong = ~SPEC_CVAL (val->etype).v_ulong;
870       else
871         SPEC_CVAL (val->etype).v_long = ~SPEC_CVAL (val->etype).v_long;
872     }
873   else
874     {
875       if (SPEC_USIGN (val->etype))
876         SPEC_CVAL (val->etype).v_uint = ~SPEC_CVAL (val->etype).v_uint;
877       else
878         SPEC_CVAL (val->etype).v_int = ~SPEC_CVAL (val->etype).v_int;
879     }
880   return val;
881 }
882
883 /*------------------------------------------------------------------*/
884 /* valueNot - complements a constant                                */
885 /*------------------------------------------------------------------*/
886 value *
887 valNot (value * val)
888 {
889   /* depending on type */
890   if (SPEC_LONG (val->etype))
891     {
892       if (SPEC_USIGN (val->etype))
893         SPEC_CVAL (val->etype).v_ulong = !SPEC_CVAL (val->etype).v_ulong;
894       else
895         SPEC_CVAL (val->etype).v_long = !SPEC_CVAL (val->etype).v_long;
896     }
897   else
898     {
899       if (SPEC_USIGN (val->etype))
900         SPEC_CVAL (val->etype).v_uint = !SPEC_CVAL (val->etype).v_uint;
901       else
902         SPEC_CVAL (val->etype).v_int = !SPEC_CVAL (val->etype).v_int;
903     }
904   return val;
905 }
906
907 /*------------------------------------------------------------------*/
908 /* valMult - multiply constants                                     */
909 /*------------------------------------------------------------------*/
910 value *
911 valMult (value * lval, value * rval)
912 {
913   value *val;
914
915   /* create a new value */
916   val = newValue ();
917   val->type = val->etype = newLink ();
918   val->type->class = SPECIFIER;
919   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
920                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
921   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
922   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
923   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
924
925   if (IS_FLOAT (val->type))
926     SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
927   else
928     {
929       if (SPEC_LONG (val->type))
930         {
931           if (SPEC_USIGN (val->type))
932             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) *
933               (unsigned long) floatFromVal (rval);
934           else
935             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) *
936               (long) floatFromVal (rval);
937         }
938       else
939         {
940           if (SPEC_USIGN (val->type))
941             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) *
942               (unsigned) floatFromVal (rval);
943           else
944             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) *
945               (int) floatFromVal (rval);
946         }
947     }
948   return val;
949 }
950
951 /*------------------------------------------------------------------*/
952 /* valDiv  - Divide   constants                                     */
953 /*------------------------------------------------------------------*/
954 value *
955 valDiv (value * lval, value * rval)
956 {
957   value *val;
958
959   if (floatFromVal (rval) == 0)
960     {
961       werror (E_DIVIDE_BY_ZERO);
962       return rval;
963     }
964
965   /* create a new value */
966   val = newValue ();
967   val->type = val->etype = newLink();
968   val->type->class = SPECIFIER;
969   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
970                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
971   SPEC_SCLS (val->etype) = S_LITERAL;
972   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
973   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
974
975   if (IS_FLOAT (val->type))
976     SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
977   else
978     {
979       if (SPEC_LONG (val->type))
980         {
981           if (SPEC_USIGN (val->type))
982             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) /
983               (unsigned long) floatFromVal (rval);
984           else
985             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) /
986               (long) floatFromVal (rval);
987         }
988       else
989         {
990           if (SPEC_USIGN (val->type)) {
991             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) /
992               (unsigned) floatFromVal (rval);
993             if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
994                 (SPEC_CVAL (val->type).v_uint <=255)) {
995               SPEC_NOUN (val->type) = V_CHAR;
996             }
997           } else {
998             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) /
999               (int) floatFromVal (rval);
1000             if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1001                 (SPEC_CVAL (val->type).v_int >=-128) &&
1002                 (SPEC_CVAL (val->type).v_int <=127)) {
1003               SPEC_NOUN (val->type) = V_CHAR;
1004             }
1005           }
1006         }
1007     }
1008   return val;
1009 }
1010
1011 /*------------------------------------------------------------------*/
1012 /* valMod  - Modulus  constants                                     */
1013 /*------------------------------------------------------------------*/
1014 value *
1015 valMod (value * lval, value * rval)
1016 {
1017   value *val;
1018
1019   /* create a new value */
1020   val = newValue ();
1021   val->type = val->etype = newLink ();
1022   val->type->class = SPECIFIER;
1023   SPEC_NOUN (val->type) = V_INT;        /* type is int */
1024   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1025   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
1026   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1027
1028   if (SPEC_LONG (val->type))
1029     {
1030       if (SPEC_USIGN (val->type))
1031         SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) %
1032           (unsigned long) floatFromVal (rval);
1033       else
1034         SPEC_CVAL (val->type).v_long = (unsigned long) floatFromVal (lval) %
1035           (unsigned long) floatFromVal (rval);
1036     }
1037   else
1038     {
1039       if (SPEC_USIGN (val->type)) {
1040         SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) %
1041           (unsigned) floatFromVal (rval);
1042         if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1043             (SPEC_CVAL (val->type).v_uint <=255)) {
1044           SPEC_NOUN (val->type) = V_CHAR;
1045         }
1046       } else {
1047         SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) %
1048           (unsigned) floatFromVal (rval);
1049         if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1050             (SPEC_CVAL (val->type).v_int >=-128) &&
1051             (SPEC_CVAL (val->type).v_int <=127)) {
1052           SPEC_NOUN (val->type) = V_CHAR;
1053         }
1054       }
1055     }
1056
1057   return val;
1058 }
1059
1060 /*------------------------------------------------------------------*/
1061 /* valPlus - Addition constants                                     */
1062 /*------------------------------------------------------------------*/
1063 value *
1064 valPlus (value * lval, value * rval)
1065 {
1066   value *val;
1067
1068   /* create a new value */
1069   val = newValue ();
1070   val->type = val->etype = newLink ();
1071   val->type->class = SPECIFIER;
1072   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1073                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1074   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1075   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
1076   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1077
1078   if (IS_FLOAT (val->type))
1079     SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval);
1080   else
1081     {
1082       if (SPEC_LONG (val->type))
1083         {
1084           if (SPEC_USIGN (val->type))
1085             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) +
1086               (unsigned long) floatFromVal (rval);
1087           else
1088             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) +
1089               (long) floatFromVal (rval);
1090         }
1091       else
1092         {
1093           if (SPEC_USIGN (val->type)) {
1094             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) +
1095               (unsigned) floatFromVal (rval);
1096             if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1097                 (SPEC_CVAL (val->type).v_uint <=255)) {
1098               SPEC_NOUN (val->type) = V_CHAR;
1099             }
1100           } else {
1101             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) +
1102               (int) floatFromVal (rval);
1103             if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1104                 (SPEC_CVAL (val->type).v_int >=-128) &&
1105                 (SPEC_CVAL (val->type).v_int <=127)) {
1106               SPEC_NOUN (val->type) = V_CHAR;
1107             }
1108           }
1109         }
1110     }
1111   return val;
1112 }
1113
1114 /*------------------------------------------------------------------*/
1115 /* valMinus - Addition constants                                    */
1116 /*------------------------------------------------------------------*/
1117 value *
1118 valMinus (value * lval, value * rval)
1119 {
1120   value *val;
1121
1122   /* create a new value */
1123   val = newValue ();
1124   val->type = val->etype = newLink ();
1125   val->type->class = SPECIFIER;
1126   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1127                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1128   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1129   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
1130   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1131
1132   if (IS_FLOAT (val->type))
1133     SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval);
1134   else
1135     {
1136       if (SPEC_LONG (val->type))
1137         {
1138           if (SPEC_USIGN (val->type)) {
1139             SPEC_CVAL (val->type).v_ulong = 
1140               (unsigned long) floatFromVal (lval) -
1141               (unsigned long) floatFromVal (rval);
1142           } else {
1143             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) -
1144               (long) floatFromVal (rval);
1145           }
1146         }
1147       else
1148         {
1149           if (SPEC_USIGN (val->type)) {
1150             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) -
1151               (unsigned) floatFromVal (rval);
1152             if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1153                 (SPEC_CVAL (val->type).v_uint <=255)) {
1154               SPEC_NOUN (val->type) = V_CHAR;
1155             }
1156           } else {
1157             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - (int) floatFromVal (rval);
1158             if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1159                 (SPEC_CVAL (val->type).v_int >=-128) &&
1160                 (SPEC_CVAL (val->type).v_int <=127)) {
1161               SPEC_NOUN (val->type) = V_CHAR;
1162             }
1163           }
1164         }
1165     }
1166   return val;
1167 }
1168
1169 /*------------------------------------------------------------------*/
1170 /* valShift - Shift left or right                                   */
1171 /*------------------------------------------------------------------*/
1172 value *
1173 valShift (value * lval, value * rval, int lr)
1174 {
1175   value *val;
1176
1177   /* create a new value */
1178   val = newValue ();
1179   val->type = val->etype = newIntLink ();
1180   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1181   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
1182   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1183
1184   if (SPEC_LONG (val->type))
1185     {
1186       if (SPEC_USIGN (val->type))
1187         SPEC_CVAL (val->type).v_ulong = lr ? 
1188           (unsigned long) floatFromVal (lval) << (unsigned long) floatFromVal (rval) : \
1189           (unsigned long) floatFromVal (lval) >> (unsigned long) floatFromVal (rval);
1190       else
1191         SPEC_CVAL (val->type).v_long = lr ?
1192           (long) floatFromVal (lval) << (long) floatFromVal (rval) : \
1193           (long) floatFromVal (lval) >> (long) floatFromVal (rval);
1194     }
1195   else
1196     {
1197       if (SPEC_USIGN (val->type)) {
1198         SPEC_CVAL (val->type).v_uint = lr ? 
1199           (unsigned) floatFromVal (lval) << (unsigned) floatFromVal (rval) :\
1200           (unsigned) floatFromVal (lval) >> (unsigned) floatFromVal (rval);
1201         if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1202             (SPEC_CVAL (val->type).v_uint <=255)) {
1203           SPEC_NOUN (val->type) = V_CHAR;
1204         }
1205       } else {
1206         SPEC_CVAL (val->type).v_int = lr ?
1207           (int) floatFromVal (lval) << (int) floatFromVal (rval) : \
1208           (int) floatFromVal (lval) >> (int) floatFromVal (rval);
1209         if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
1210             (SPEC_CVAL (val->type).v_int >=-128) &&
1211             (SPEC_CVAL (val->type).v_int <=127)) {
1212           SPEC_NOUN (val->type) = V_CHAR;
1213         }
1214       }
1215     }
1216
1217   return val;
1218 }
1219
1220 /*------------------------------------------------------------------*/
1221 /* valCompare- Compares two literal                                 */
1222 /*------------------------------------------------------------------*/
1223 value *
1224 valCompare (value * lval, value * rval, int ctype)
1225 {
1226   value *val;
1227
1228   /* create a new value */
1229   val = newValue ();
1230   val->type = val->etype = newCharLink ();
1231   val->type->class = SPECIFIER;
1232   SPEC_NOUN (val->type) = V_INT;        /* type is int */
1233   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1234
1235   switch (ctype)
1236     {
1237     case '<':
1238       SPEC_CVAL (val->type).v_int = floatFromVal (lval) < floatFromVal (rval);
1239       break;
1240
1241     case '>':
1242       SPEC_CVAL (val->type).v_int = floatFromVal (lval) > floatFromVal (rval);
1243       break;
1244
1245     case LE_OP:
1246       SPEC_CVAL (val->type).v_int = floatFromVal (lval) <= floatFromVal (rval);
1247       break;
1248
1249     case GE_OP:
1250       SPEC_CVAL (val->type).v_int = floatFromVal (lval) >= floatFromVal (rval);
1251       break;
1252
1253     case EQ_OP:
1254       SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval);
1255       break;
1256
1257     case NE_OP:
1258       SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval);
1259       break;
1260
1261     }
1262
1263   return val;
1264 }
1265
1266 /*------------------------------------------------------------------*/
1267 /* valBitwise - Bitwise operation                                   */
1268 /*------------------------------------------------------------------*/
1269 value *
1270 valBitwise (value * lval, value * rval, int op)
1271 {
1272   value *val;
1273
1274   /* create a new value */
1275   val = newValue ();
1276   val->type = copyLinkChain (lval->type);
1277   val->etype = getSpec (val->type);
1278
1279   switch (op)
1280     {
1281     case '&':
1282       if (SPEC_LONG (val->type))
1283         {
1284           if (SPEC_USIGN (val->type))
1285             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) &
1286               (unsigned long) floatFromVal (rval);
1287           else
1288             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) &
1289               (long) floatFromVal (rval);
1290         }
1291       else
1292         {
1293           if (SPEC_USIGN (val->type))
1294             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) &
1295               (unsigned) floatFromVal (rval);
1296           else
1297             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) & (int) floatFromVal (rval);
1298         }
1299       break;
1300
1301     case '|':
1302       if (SPEC_LONG (val->type))
1303         {
1304           if (SPEC_USIGN (val->type))
1305             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) |
1306               (unsigned long) floatFromVal (rval);
1307           else
1308             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) |
1309               (long) floatFromVal (rval);
1310         }
1311       else
1312         {
1313           if (SPEC_USIGN (val->type))
1314             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) |
1315               (unsigned) floatFromVal (rval);
1316           else
1317             SPEC_CVAL (val->type).v_int =
1318               (int) floatFromVal (lval) | (int) floatFromVal (rval);
1319         }
1320
1321       break;
1322
1323     case '^':
1324       if (SPEC_LONG (val->type))
1325         {
1326           if (SPEC_USIGN (val->type))
1327             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) ^
1328               (unsigned long) floatFromVal (rval);
1329           else
1330             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) ^
1331               (long) floatFromVal (rval);
1332         }
1333       else
1334         {
1335           if (SPEC_USIGN (val->type))
1336             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) ^
1337               (unsigned) floatFromVal (rval);
1338           else
1339             SPEC_CVAL (val->type).v_int =
1340               (int) floatFromVal (lval) ^ (int) floatFromVal (rval);
1341         }
1342       break;
1343     }
1344
1345   return val;
1346 }
1347
1348 /*------------------------------------------------------------------*/
1349 /* valAndOr   - Generates code for and / or operation               */
1350 /*------------------------------------------------------------------*/
1351 value *
1352 valLogicAndOr (value * lval, value * rval, int op)
1353 {
1354   value *val;
1355
1356   /* create a new value */
1357   val = newValue ();
1358   val->type = val->etype = newCharLink ();
1359   val->type->class = SPECIFIER;
1360   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1361
1362   switch (op)
1363     {
1364     case AND_OP:
1365       SPEC_CVAL (val->type).v_int = floatFromVal (lval) && floatFromVal (rval);
1366       break;
1367
1368     case OR_OP:
1369       SPEC_CVAL (val->type).v_int = floatFromVal (lval) || floatFromVal (rval);
1370       break;
1371     }
1372
1373
1374   return val;
1375 }
1376
1377 /*------------------------------------------------------------------*/
1378 /* valCastLiteral - casts a literal value to another type           */
1379 /*------------------------------------------------------------------*/
1380 value *
1381 valCastLiteral (sym_link * dtype, double fval)
1382 {
1383   value *val;
1384
1385   if (!dtype)
1386     return NULL;
1387
1388   val = newValue ();
1389   val->etype = getSpec (val->type = copyLinkChain (dtype));
1390   SPEC_SCLS (val->etype) = S_LITERAL;
1391   /* if it is not a specifier then we can assume that */
1392   /* it will be an unsigned long                      */
1393   if (!IS_SPEC (val->type))
1394     {
1395       SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1396       return val;
1397     }
1398
1399   if (SPEC_NOUN (val->etype) == V_FLOAT)
1400     SPEC_CVAL (val->etype).v_float = fval;
1401   else
1402     {
1403       if (SPEC_LONG (val->etype))
1404         {
1405           if (SPEC_USIGN (val->etype))
1406             SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1407           else
1408             SPEC_CVAL (val->etype).v_long = (long) fval;
1409         }
1410       else
1411         {
1412           if (SPEC_USIGN (val->etype))
1413             SPEC_CVAL (val->etype).v_uint = (unsigned int) fval;
1414           else
1415             SPEC_CVAL (val->etype).v_int = (int) fval;
1416         }
1417     }
1418   return val;
1419 }
1420
1421 /*------------------------------------------------------------------*/
1422 /* getNelements - determines # of elements from init list           */
1423 /*------------------------------------------------------------------*/
1424 int 
1425 getNelements (sym_link * type, initList * ilist)
1426 {
1427   sym_link *etype = getSpec (type);
1428   int i;
1429
1430   if (!ilist)
1431     return 0;
1432
1433   if (ilist->type == INIT_DEEP)
1434     ilist = ilist->init.deep;
1435
1436   /* if type is a character array and there is only one
1437      (string) initialiser then get the length of the string */
1438   if (IS_ARRAY (type) && IS_CHAR (etype) && !ilist->next)
1439     {
1440       ast *iast = ilist->init.node;
1441       value *v = (iast->type == EX_VALUE ? iast->opval.val : NULL);
1442       if (!v)
1443         {
1444           werror (W_INIT_WRONG);
1445           return 0;
1446         }
1447
1448       if (IS_ARRAY (v->type) && IS_CHAR (v->etype))
1449         // yep, it's a string
1450         {
1451           return DCL_ELEM (v->type);
1452         }
1453     }
1454
1455   i = 0;
1456   while (ilist)
1457     {
1458       i++;
1459       ilist = ilist->next;
1460     }
1461
1462   return i;
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* valForArray - returns a value with name of array index          */
1467 /*-----------------------------------------------------------------*/
1468 value *
1469 valForArray (ast * arrExpr)
1470 {
1471   value *val, *lval = NULL;
1472   char buffer[128];
1473   int size = getSize (arrExpr->left->ftype->next);
1474   /* if the right or left is an array
1475      resolve it first */
1476   if (IS_AST_OP (arrExpr->left))
1477     {
1478       if (arrExpr->left->opval.op == '[')
1479         lval = valForArray (arrExpr->left);
1480       else if (arrExpr->left->opval.op == '.')
1481         lval = valForStructElem (arrExpr->left->left,
1482                                  arrExpr->left->right);
1483       else if (arrExpr->left->opval.op == PTR_OP &&
1484                IS_ADDRESS_OF_OP (arrExpr->left->left))
1485         lval = valForStructElem (arrExpr->left->left->left,
1486                                  arrExpr->left->right);
1487       else
1488         return NULL;
1489
1490     }
1491   else if (!IS_AST_SYM_VALUE (arrExpr->left))
1492     return NULL;
1493
1494   if (!IS_AST_LIT_VALUE (arrExpr->right))
1495     return NULL;
1496
1497   val = newValue ();
1498   if (!lval)
1499     sprintf (buffer, "%s", AST_SYMBOL (arrExpr->left)->rname);
1500   else
1501     sprintf (buffer, "%s", lval->name);
1502
1503   sprintf (val->name, "(%s + %d)", buffer,
1504            (int) AST_LIT_VALUE (arrExpr->right) * size);
1505
1506   val->type = newLink ();
1507   if (SPEC_SCLS (arrExpr->left->etype) == S_CODE)
1508     {
1509       DCL_TYPE (val->type) = CPOINTER;
1510       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1511     }
1512   else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA)
1513     DCL_TYPE (val->type) = FPOINTER;
1514   else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK)
1515     DCL_TYPE (val->type) = PPOINTER;
1516   else if (SPEC_SCLS (arrExpr->left->etype) == S_IDATA)
1517     DCL_TYPE (val->type) = IPOINTER;
1518   else if (SPEC_SCLS (arrExpr->left->etype) == S_EEPROM)
1519     DCL_TYPE (val->type) = EEPPOINTER;
1520   else
1521     DCL_TYPE (val->type) = POINTER;
1522   val->type->next = arrExpr->left->ftype;
1523   val->etype = getSpec (val->type);
1524   return val;
1525 }
1526
1527 /*-----------------------------------------------------------------*/
1528 /* valForStructElem - returns value with name of struct element    */
1529 /*-----------------------------------------------------------------*/
1530 value *
1531 valForStructElem (ast * structT, ast * elemT)
1532 {
1533   value *val, *lval = NULL;
1534   char buffer[128];
1535   symbol *sym;
1536
1537   /* left could be furthur derefed */
1538   if (IS_AST_OP (structT))
1539     {
1540       if (structT->opval.op == '[')
1541         lval = valForArray (structT);
1542       else if (structT->opval.op == '.')
1543         lval = valForStructElem (structT->left, structT->right);
1544       else if (structT->opval.op == PTR_OP &&
1545                IS_ADDRESS_OF_OP (structT->left))
1546         lval = valForStructElem (structT->left->left,
1547                                  structT->right);
1548       else
1549         return NULL;
1550     }
1551
1552   if (!IS_AST_SYM_VALUE (elemT))
1553     return NULL;
1554
1555   if (!IS_STRUCT (structT->etype))
1556     return NULL;
1557
1558   if ((sym = getStructElement (SPEC_STRUCT (structT->etype),
1559                                AST_SYMBOL (elemT))) == NULL)
1560     {
1561       return NULL;
1562     }
1563
1564   val = newValue ();
1565   if (!lval)
1566     sprintf (buffer, "%s", AST_SYMBOL (structT)->rname);
1567   else
1568     sprintf (buffer, "%s", lval->name);
1569
1570   sprintf (val->name, "(%s + %d)", buffer,
1571            (int) sym->offset);
1572
1573   val->type = newLink ();
1574   if (SPEC_SCLS (structT->etype) == S_CODE)
1575     {
1576       DCL_TYPE (val->type) = CPOINTER;
1577       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1578     }
1579   else if (SPEC_SCLS (structT->etype) == S_XDATA)
1580     DCL_TYPE (val->type) = FPOINTER;
1581   else if (SPEC_SCLS (structT->etype) == S_XSTACK)
1582     DCL_TYPE (val->type) = PPOINTER;
1583   else if (SPEC_SCLS (structT->etype) == S_IDATA)
1584     DCL_TYPE (val->type) = IPOINTER;
1585   else if (SPEC_SCLS (structT->etype) == S_EEPROM)
1586     DCL_TYPE (val->type) = EEPPOINTER;
1587   else
1588     DCL_TYPE (val->type) = POINTER;
1589   val->type->next = sym->type;
1590   val->etype = getSpec (val->type);
1591   return val;
1592 }
1593
1594 /*-----------------------------------------------------------------*/
1595 /* valForCastAggr - will return value for a cast of an aggregate   */
1596 /*                  plus minus a constant                          */
1597 /*-----------------------------------------------------------------*/
1598 value *
1599 valForCastAggr (ast * aexpr, sym_link * type, ast * cnst, int op)
1600 {
1601   value *val;
1602
1603   if (!IS_AST_SYM_VALUE (aexpr))
1604     return NULL;
1605   if (!IS_AST_LIT_VALUE (cnst))
1606     return NULL;
1607
1608   val = newValue ();
1609
1610   sprintf (val->name, "(%s %c %d)",
1611            AST_SYMBOL (aexpr)->rname, op,
1612            getSize (type->next) * (int) AST_LIT_VALUE (cnst));
1613
1614   val->type = type;
1615   val->etype = getSpec (val->type);
1616   return val;
1617 }
1618
1619 /*-----------------------------------------------------------------*/
1620 /* valForCastAggr - will return value for a cast of an aggregate   */
1621 /*                  with no constant                               */
1622 /*-----------------------------------------------------------------*/
1623 value *
1624 valForCastArr (ast * aexpr, sym_link * type)
1625 {
1626   value *val;
1627
1628   if (!IS_AST_SYM_VALUE (aexpr))
1629     return NULL;
1630
1631   val = newValue ();
1632
1633   sprintf (val->name, "(%s)",
1634            AST_SYMBOL (aexpr)->rname);
1635
1636   val->type = type;
1637   val->etype = getSpec (val->type);
1638   return val;
1639 }