more efficient constant value operations
[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 /* cheapestVal - convert a val to the cheapest as possible value      */
317 /*--------------------------------------------------------------------*/
318 value *cheapestVal (value *val) {
319   long sval=0;
320   unsigned long uval=0;
321
322   if (IS_FLOAT(val->type) || IS_CHAR(val->type))
323     return val;
324
325   if (SPEC_LONG(val->type)) {
326     if (SPEC_USIGN(val->type)) {
327       uval=SPEC_CVAL(val->type).v_ulong;
328     } else {
329       sval=SPEC_CVAL(val->type).v_long;
330     }
331   } else {
332     if (SPEC_USIGN(val->type)) {
333       uval=SPEC_CVAL(val->type).v_uint;
334     } else {
335       sval=SPEC_CVAL(val->type).v_int;
336     }
337   }
338
339   if (SPEC_USIGN(val->type)) {
340     if (uval<=0xff) {
341       SPEC_NOUN(val->type)=V_CHAR;
342       SPEC_LONG(val->type)=0;
343     } else {
344       if (uval<=0xffff) {
345         SPEC_LONG(val->type)=0;
346       }
347     }
348   } else {
349     if (sval<0) {
350       if (sval>=-128) {
351         SPEC_NOUN(val->type)=V_CHAR;
352         SPEC_LONG(val->type)=0;
353       } else {
354         if (sval>=-32768) {
355           SPEC_LONG(val->type)=0;
356         }
357       }
358     } else {
359       if (sval<=127) {
360         SPEC_NOUN(val->type)=V_CHAR;
361         SPEC_LONG(val->type)=0;
362       } else {
363         if (sval<=32767) {
364           SPEC_LONG(val->type)=0;
365         }
366       }
367     }
368   }
369   return val;
370 }
371
372 /*-----------------------------------------------------------------*/
373 /* valueFromLit - creates a value from a literal                   */
374 /*-----------------------------------------------------------------*/
375 value *
376 valueFromLit (double lit)
377 {
378   char buffer[50];
379
380   if ((((long) lit) - lit) == 0)
381     {
382       sprintf (buffer, "%ld", (long) lit);
383       return constVal (buffer);
384     }
385
386   sprintf (buffer, "%f", lit);
387   return constFloatVal (buffer);
388 }
389
390 /*-----------------------------------------------------------------*/
391 /* constFloatVal - converts a FLOAT constant to value              */
392 /*-----------------------------------------------------------------*/
393 value *
394 constFloatVal (char *s)
395 {
396   value *val = newValue ();
397   float sval;
398
399   if (sscanf (s, "%f", &sval) != 1)
400     {
401       werror (E_INVALID_FLOAT_CONST, s);
402       return constVal ("0");
403     }
404
405   val->type = val->etype = newLink ();
406   val->type->class = SPECIFIER;
407   SPEC_NOUN (val->type) = V_FLOAT;
408   SPEC_SCLS (val->type) = S_LITERAL;
409   SPEC_CVAL (val->type).v_float = sval;
410
411   return val;
412 }
413
414 /*-----------------------------------------------------------------*/
415 /* constVal - converts an INTEGER constant into a cheapest value   */
416 /*-----------------------------------------------------------------*/
417 value *constVal (char *s)
418 {
419   value *val;
420   short hex = 0, octal = 0;
421   char scanFmt[10];
422   int scI = 0;
423   unsigned long sval;
424
425   val = newValue ();            /* alloc space for value   */
426
427   val->type = val->etype = newLink ();  /* create the spcifier */
428   val->type->class = SPECIFIER;
429   SPEC_SCLS (val->type) = S_LITERAL;
430   // let's start with an unsigned char
431   SPEC_NOUN (val->type) = V_CHAR;
432   SPEC_USIGN (val->type) = 1;
433
434   /* set the _long flag if 'lL' is found */
435   if (strchr (s, 'l') || strchr (s, 'L'))
436     SPEC_LONG (val->type) = 1;
437
438   hex = ((strchr (s, 'x') || strchr (s, 'X')) ? 1 : 0);
439
440   /* set the octal flag   */
441   if (!hex && *s == '0' && *(s + 1))
442     octal = 1;
443
444   /* create the scan string */
445   scanFmt[scI++] = '%';
446
447   if (octal)
448     scanFmt[scI++] = 'o';
449   else if (hex)
450     scanFmt[scI++] = 'x';
451   else
452     scanFmt[scI++] = 'd';
453
454   scanFmt[scI++] = 'L';
455   scanFmt[scI++] = '\0';
456
457   sscanf (s, scanFmt, &sval);
458
459   if (sval<0) { // "-28u" will still be signed and negative
460     SPEC_USIGN (val->type) = 0;
461     if (sval<-32768) { // check if we have to promote to long
462       SPEC_NOUN (val->type) = V_INT;
463       SPEC_LONG (val->type) = 1;
464       SPEC_CVAL (val->type).v_long=sval;
465     } else {
466       SPEC_CVAL (val->type).v_int=sval;
467       if (sval<-128) { // check if we have to promote to int
468         SPEC_NOUN (val->type) = V_INT;
469       }
470     }
471   } else {
472     if (sval>0xffff) { // check if we have to promote to long
473       SPEC_NOUN (val->type) = V_INT;
474       SPEC_LONG (val->type) = 1;
475       SPEC_CVAL (val->type).v_ulong=sval;
476     } else {
477       SPEC_CVAL (val->type).v_uint=sval;
478       if (sval>0xff) { // check if we have to promote to int
479         SPEC_NOUN (val->type) = V_INT;
480       }
481     }
482   }
483
484   return val;
485 }
486
487 /*! /fn char hexEscape(char **src)
488
489     /param src Pointer to 'x' from start of hex character value
490 */
491
492 char hexEscape(char **src)
493
494 {
495 char *s ;
496 unsigned long value ;
497
498 (*src)++ ;      /* Skip over the 'x' */
499 s = *src ;      /* Save for error detection */
500
501 value = strtol (*src, src, 16);
502
503 if (s == *src) 
504   {
505   // no valid hex found
506   werror(E_INVALID_HEX);
507   } 
508
509 else 
510   {
511   if (value > 255) 
512     {
513     werror(W_ESC_SEQ_OOR_FOR_CHAR);
514     }
515   }
516
517 return (char) value;
518 }
519 /*------------------------------------------------------------------*/
520 /* octalEscape - process an octal constant of max three digits      */
521 /* return the octal value, throw a warning for illegal octal        */
522 /* adjust src to point at the last proccesed char                   */
523 /*------------------------------------------------------------------*/
524
525 char octalEscape (char **str) {
526   int digits;
527   unsigned value=0;
528
529   for (digits=0; digits<3; digits++) {
530     if (**str>='0' && **str<='7') {
531       value = value*8 + (**str-'0');
532       (*str)++;
533     } else {
534       break;
535     }
536   }
537   if (digits) {
538     if (value > 255 /* || (**str>='0' && **str<='7') */ ) {
539       werror (W_ESC_SEQ_OOR_FOR_CHAR);
540     }
541   }
542   return value;
543 }
544
545 /*! 
546   /fn int copyStr (char *dest, char *src)
547   
548   Copies a source string to a dest buffer interpreting escape sequences
549   and special characters
550
551   /param dest Buffer to receive the resultant string
552   /param src  Buffer containing the source string with escape sequecnes
553   /return Number of characters in output string
554
555 */
556
557 int 
558 copyStr (char *dest, char *src)
559
560 {
561   char *OriginalDest = dest ;
562
563   while (*src)
564     {
565       if (*src == '\"')
566         src++;
567       else if (*src == '\\')
568         {
569           src++;
570           switch (*src)
571             {
572             case 'n':
573               *dest++ = '\n';
574               break;
575             case 't':
576               *dest++ = '\t';
577               break;
578             case 'v':
579               *dest++ = '\v';
580               break;
581             case 'b':
582               *dest++ = '\b';
583               break;
584             case 'r':
585               *dest++ = '\r';
586               break;
587             case 'f':
588               *dest++ = '\f';
589               break;
590             case 'a':
591               *dest++ = '\a';
592               break;
593
594             case '0':
595             case '1':
596             case '2':
597             case '3':
598             case '4':
599             case '5':
600             case '6':
601             case '7':
602               *dest++ = octalEscape(&src);
603               src-- ;
604               break;
605
606             case 'x': 
607               *dest++ = hexEscape(&src) ;
608               src-- ;
609               break ;
610
611             case '\\':
612               *dest++ = '\\';
613               break;
614             case '\?':
615               *dest++ = '\?';
616               break;
617             case '\'':
618               *dest++ = '\'';
619               break;
620             case '\"':
621               *dest++ = '\"';
622               break;
623             default:
624               *dest++ = *src;
625             }
626           src++;
627         }
628       else
629         *dest++ = *src++;
630     }
631
632   *dest++ = '\0';
633
634   return dest - OriginalDest ;
635 }
636
637 /*------------------------------------------------------------------*/
638 /* strVal - converts a string constant to a value       */
639 /*------------------------------------------------------------------*/
640 value *
641 strVal (char *s)
642 {
643   value *val;
644
645   val = newValue ();            /* get a new one */
646
647   /* get a declarator */
648   val->type = newLink ();
649   DCL_TYPE (val->type) = ARRAY;
650   val->type->next = val->etype = newLink ();
651   val->etype->class = SPECIFIER;
652   SPEC_NOUN (val->etype) = V_CHAR;
653   SPEC_SCLS (val->etype) = S_LITERAL;
654
655   SPEC_CVAL (val->etype).v_char = Safe_calloc (1, strlen (s) + 1);
656   DCL_ELEM (val->type) = copyStr (SPEC_CVAL (val->etype).v_char, s);
657
658   return val;
659 }
660
661
662 /*------------------------------------------------------------------*/
663 /* reverseValWithType - reverses value chain with type & etype      */
664 /*------------------------------------------------------------------*/
665 value *
666 reverseValWithType (value * val)
667 {
668   sym_link *type;
669   sym_link *etype;
670
671   if (!val)
672     return NULL;
673
674   /* save the type * etype chains */
675   type = val->type;
676   etype = val->etype;
677
678   /* set the current one 2b null */
679   val->type = val->etype = NULL;
680   val = reverseVal (val);
681
682   /* restore type & etype */
683   val->type = type;
684   val->etype = etype;
685
686   return val;
687 }
688
689 /*------------------------------------------------------------------*/
690 /* reverseVal - reverses the values for a value  chain        */
691 /*------------------------------------------------------------------*/
692 value *
693 reverseVal (value * val)
694 {
695   value *prev, *curr, *next;
696
697   if (!val)
698     return NULL;
699
700   prev = val;
701   curr = val->next;
702
703   while (curr)
704     {
705       next = curr->next;
706       curr->next = prev;
707       prev = curr;
708       curr = next;
709     }
710   val->next = (void *) NULL;
711   return prev;
712 }
713
714 /*------------------------------------------------------------------*/
715 /* copyValueChain - will copy a chain of values                     */
716 /*------------------------------------------------------------------*/
717 value *
718 copyValueChain (value * src)
719 {
720   value *dest;
721
722   if (!src)
723     return NULL;
724
725   dest = copyValue (src);
726   dest->next = copyValueChain (src->next);
727
728   return dest;
729 }
730
731 /*------------------------------------------------------------------*/
732 /* copyValue - copies contents of a value to a fresh one            */
733 /*------------------------------------------------------------------*/
734 value *
735 copyValue (value * src)
736 {
737   value *dest;
738
739   dest = newValue ();
740   dest->sym = copySymbol (src->sym);
741   strcpy (dest->name, src->name);
742   dest->type = (src->type ? copyLinkChain (src->type) : NULL);
743   dest->etype = (src->type ? getSpec (dest->type) : NULL);
744
745   return dest;
746 }
747
748 /*------------------------------------------------------------------*/
749 /* charVal - converts a character constant to a value       */
750 /*------------------------------------------------------------------*/
751 value *
752 charVal (char *s)
753 {
754   value *val;
755 //  unsigned uValue ;
756
757   val = newValue ();
758
759   val->type = val->etype = newLink ();
760   val->type->class = SPECIFIER;
761   SPEC_NOUN (val->type) = V_CHAR;
762   SPEC_USIGN(val->type) = 1;
763   SPEC_SCLS (val->type) = S_LITERAL;
764
765   s++;                          /* get rid of quotation */
766   /* if \ then special processing */
767   if (*s == '\\')
768     {
769       s++;                      /* go beyond the backslash  */
770       switch (*s)
771         {
772         case 'n':
773           SPEC_CVAL (val->type).v_int = '\n';
774           break;
775         case 't':
776           SPEC_CVAL (val->type).v_int = '\t';
777           break;
778         case 'v':
779           SPEC_CVAL (val->type).v_int = '\v';
780           break;
781         case 'b':
782           SPEC_CVAL (val->type).v_int = '\b';
783           break;
784         case 'r':
785           SPEC_CVAL (val->type).v_int = '\r';
786           break;
787         case 'f':
788           SPEC_CVAL (val->type).v_int = '\f';
789           break;
790         case 'a':
791           SPEC_CVAL (val->type).v_int = '\a';
792           break;
793         case '\\':
794           SPEC_CVAL (val->type).v_int = '\\';
795           break;
796         case '\?':
797           SPEC_CVAL (val->type).v_int = '\?';
798           break;
799         case '\'':
800           SPEC_CVAL (val->type).v_int = '\'';
801           break;
802         case '\"':
803           SPEC_CVAL (val->type).v_int = '\"';
804           break;
805
806         case '0' :
807         case '1' :
808         case '2' :
809         case '3' :
810         case '4' :
811         case '5' :
812         case '6' :
813         case '7' :
814           SPEC_CVAL (val->type).v_int = octalEscape(&s);
815           break;
816
817         case 'x':
818           SPEC_CVAL (val->type).v_int = hexEscape(&s) ;
819           break;
820
821         default:
822           SPEC_CVAL (val->type).v_int = *s;
823           break;
824         }
825     }
826   else                          /* not a backslash */
827     SPEC_CVAL (val->type).v_int = *s;
828
829   return val;
830 }
831
832 /*------------------------------------------------------------------*/
833 /* valFromType - creates a value from type given                    */
834 /*------------------------------------------------------------------*/
835 value *
836 valFromType (sym_link * type)
837 {
838   value *val = newValue ();
839   val->type = copyLinkChain (type);
840   val->etype = getSpec (val->type);
841   return val;
842 }
843
844 /*------------------------------------------------------------------*/
845 /* floatFromVal - value to unsinged integer conversion        */
846 /*------------------------------------------------------------------*/
847 double 
848 floatFromVal (value * val)
849 {
850   if (!val)
851     return 0;
852
853   if (val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
854     {
855       werror (E_CONST_EXPECTED, val->name);
856       return 0;
857     }
858
859   /* if it is not a specifier then we can assume that */
860   /* it will be an unsigned long                      */
861   if (!IS_SPEC (val->type))
862     return (double) SPEC_CVAL (val->etype).v_ulong;
863
864   if (SPEC_NOUN (val->etype) == V_FLOAT)
865     return (double) SPEC_CVAL (val->etype).v_float;
866   else
867     {
868       if (SPEC_LONG (val->etype))
869         {
870           if (SPEC_USIGN (val->etype))
871             return (double) SPEC_CVAL (val->etype).v_ulong;
872           else
873             return (double) SPEC_CVAL (val->etype).v_long;
874         }
875       else
876         {
877           if (SPEC_USIGN (val->etype))
878             return (double) SPEC_CVAL (val->etype).v_uint;
879           else
880             return (double) SPEC_CVAL (val->etype).v_int;
881         }
882     }
883 }
884
885
886 /*------------------------------------------------------------------*/
887 /* valUnaryPM - does the unary +/- operation on a constant          */
888 /*------------------------------------------------------------------*/
889 value *
890 valUnaryPM (value * val)
891 {
892   /* depending on type */
893   if (SPEC_NOUN (val->etype) == V_FLOAT)
894     SPEC_CVAL (val->etype).v_float = -1.0 * SPEC_CVAL (val->etype).v_float;
895   else
896     {
897       if (SPEC_LONG (val->etype))
898         {
899           if (SPEC_USIGN (val->etype))
900             SPEC_CVAL (val->etype).v_ulong = 0-SPEC_CVAL (val->etype).v_ulong;
901           else
902             SPEC_CVAL (val->etype).v_long = -SPEC_CVAL (val->etype).v_long;
903         }
904       else
905         {
906           if (SPEC_USIGN (val->etype))
907             SPEC_CVAL (val->etype).v_uint = 0-SPEC_CVAL (val->etype).v_uint;
908           else
909             SPEC_CVAL (val->etype).v_int = -SPEC_CVAL (val->etype).v_int;
910         }
911     }
912   return val;
913 }
914
915 /*------------------------------------------------------------------*/
916 /* valueComplement - complements a constant                         */
917 /*------------------------------------------------------------------*/
918 value *
919 valComplement (value * val)
920 {
921   /* depending on type */
922   if (SPEC_LONG (val->etype))
923     {
924       if (SPEC_USIGN (val->etype))
925         SPEC_CVAL (val->etype).v_ulong = ~SPEC_CVAL (val->etype).v_ulong;
926       else
927         SPEC_CVAL (val->etype).v_long = ~SPEC_CVAL (val->etype).v_long;
928     }
929   else
930     {
931       if (SPEC_USIGN (val->etype))
932         SPEC_CVAL (val->etype).v_uint = ~SPEC_CVAL (val->etype).v_uint;
933       else
934         SPEC_CVAL (val->etype).v_int = ~SPEC_CVAL (val->etype).v_int;
935     }
936   return val;
937 }
938
939 /*------------------------------------------------------------------*/
940 /* valueNot - complements a constant                                */
941 /*------------------------------------------------------------------*/
942 value *
943 valNot (value * val)
944 {
945   /* depending on type */
946   if (SPEC_LONG (val->etype))
947     {
948       if (SPEC_USIGN (val->etype))
949         SPEC_CVAL (val->etype).v_ulong = !SPEC_CVAL (val->etype).v_ulong;
950       else
951         SPEC_CVAL (val->etype).v_long = !SPEC_CVAL (val->etype).v_long;
952     }
953   else
954     {
955       if (SPEC_USIGN (val->etype))
956         SPEC_CVAL (val->etype).v_uint = !SPEC_CVAL (val->etype).v_uint;
957       else
958         SPEC_CVAL (val->etype).v_int = !SPEC_CVAL (val->etype).v_int;
959     }
960   return val;
961 }
962
963 /*------------------------------------------------------------------*/
964 /* valMult - multiply constants                                     */
965 /*------------------------------------------------------------------*/
966 value *
967 valMult (value * lval, value * rval)
968 {
969   value *val;
970
971   /* create a new value */
972   val = newValue ();
973   val->type = val->etype = newLink ();
974   val->type->class = SPECIFIER;
975   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
976                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
977   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
978   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
979   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
980
981   if (IS_FLOAT (val->type))
982     SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
983   else
984     {
985       if (SPEC_LONG (val->type))
986         {
987           if (SPEC_USIGN (val->type))
988             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) *
989               (unsigned long) floatFromVal (rval);
990           else
991             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) *
992               (long) floatFromVal (rval);
993         }
994       else
995         {
996           if (SPEC_USIGN (val->type))
997             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) *
998               (unsigned) floatFromVal (rval);
999           else
1000             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) *
1001               (int) floatFromVal (rval);
1002         }
1003     }
1004   return cheapestVal(val);
1005 }
1006
1007 /*------------------------------------------------------------------*/
1008 /* valDiv  - Divide   constants                                     */
1009 /*------------------------------------------------------------------*/
1010 value *
1011 valDiv (value * lval, value * rval)
1012 {
1013   value *val;
1014
1015   if (floatFromVal (rval) == 0)
1016     {
1017       werror (E_DIVIDE_BY_ZERO);
1018       return rval;
1019     }
1020
1021   /* create a new value */
1022   val = newValue ();
1023   val->type = val->etype = newLink();
1024   val->type->class = SPECIFIER;
1025   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1026                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1027   SPEC_SCLS (val->etype) = S_LITERAL;
1028   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1029   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1030
1031   if (IS_FLOAT (val->type))
1032     SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
1033   else
1034     {
1035       if (SPEC_LONG (val->type))
1036         {
1037           if (SPEC_USIGN (val->type))
1038             SPEC_CVAL (val->type).v_ulong = 
1039               (unsigned long) floatFromVal (lval) /
1040               (unsigned long) floatFromVal (rval);
1041           else
1042             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) /
1043               (long) floatFromVal (rval);
1044         }
1045       else
1046         {
1047           if (SPEC_USIGN (val->type)) {
1048             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) /
1049               (unsigned) floatFromVal (rval);
1050           } else {
1051             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) /
1052               (int) floatFromVal (rval);
1053           }
1054         }
1055     }
1056   return cheapestVal(val);
1057 }
1058
1059 /*------------------------------------------------------------------*/
1060 /* valMod  - Modulus  constants                                     */
1061 /*------------------------------------------------------------------*/
1062 value *
1063 valMod (value * lval, value * rval)
1064 {
1065   value *val;
1066
1067   /* create a new value */
1068   val = newValue ();
1069   val->type = val->etype = newLink ();
1070   val->type->class = SPECIFIER;
1071   SPEC_NOUN (val->type) = V_INT;        /* type is int */
1072   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1073   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1074   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1075
1076   if (SPEC_LONG (val->type))
1077     {
1078       if (SPEC_USIGN (val->type))
1079         SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) %
1080           (unsigned long) floatFromVal (rval);
1081       else
1082         SPEC_CVAL (val->type).v_long = (unsigned long) floatFromVal (lval) %
1083           (unsigned long) floatFromVal (rval);
1084     }
1085   else
1086     {
1087       if (SPEC_USIGN (val->type)) {
1088         SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) %
1089           (unsigned) floatFromVal (rval);
1090       } else {
1091         SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) %
1092           (unsigned) floatFromVal (rval);
1093       }
1094     }
1095
1096   return cheapestVal(val);
1097 }
1098
1099 /*------------------------------------------------------------------*/
1100 /* valPlus - Addition constants                                     */
1101 /*------------------------------------------------------------------*/
1102 value *
1103 valPlus (value * lval, value * rval)
1104 {
1105   value *val;
1106
1107   /* create a new value */
1108   val = newValue ();
1109   val->type = val->etype = newLink ();
1110   val->type->class = SPECIFIER;
1111   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1112                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1113   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1114   SPEC_USIGN (val->type) = 
1115     SPEC_USIGN (lval->etype) &&
1116     SPEC_USIGN (rval->etype) &&
1117     (floatFromVal(lval)+floatFromVal(rval))>=0;
1118     
1119   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1120
1121   if (IS_FLOAT (val->type))
1122     SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval);
1123   else
1124     {
1125       if (SPEC_LONG (val->type))
1126         {
1127           if (SPEC_USIGN (val->type))
1128             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) +
1129               (unsigned long) floatFromVal (rval);
1130           else
1131             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) +
1132               (long) floatFromVal (rval);
1133         }
1134       else
1135         {
1136           if (SPEC_USIGN (val->type)) {
1137             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) +
1138               (unsigned) floatFromVal (rval);
1139           } else {
1140             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) +
1141               (int) floatFromVal (rval);
1142           }
1143         }
1144     }
1145   return cheapestVal(val);
1146 }
1147
1148 /*------------------------------------------------------------------*/
1149 /* valMinus - Addition constants                                    */
1150 /*------------------------------------------------------------------*/
1151 value *
1152 valMinus (value * lval, value * rval)
1153 {
1154   value *val;
1155
1156   /* create a new value */
1157   val = newValue ();
1158   val->type = val->etype = newLink ();
1159   val->type->class = SPECIFIER;
1160   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1161                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1162   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1163   SPEC_USIGN (val->type) = 
1164     SPEC_USIGN (lval->etype) &&
1165     SPEC_USIGN (rval->etype) &&
1166     (floatFromVal(lval)-floatFromVal(rval))>=0;
1167
1168   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1169
1170   if (IS_FLOAT (val->type))
1171     SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval);
1172   else
1173     {
1174       if (SPEC_LONG (val->type))
1175         {
1176           if (SPEC_USIGN (val->type)) {
1177             SPEC_CVAL (val->type).v_ulong = 
1178               (unsigned long) floatFromVal (lval) -
1179               (unsigned long) floatFromVal (rval);
1180           } else {
1181             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) -
1182               (long) floatFromVal (rval);
1183           }
1184         }
1185       else
1186         {
1187           if (SPEC_USIGN (val->type)) {
1188             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) -
1189               (unsigned) floatFromVal (rval);
1190           } else {
1191             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - 
1192               (int) floatFromVal (rval);
1193           }
1194         }
1195     }
1196   return cheapestVal(val);
1197 }
1198
1199 /*------------------------------------------------------------------*/
1200 /* valShift - Shift left or right                                   */
1201 /*------------------------------------------------------------------*/
1202 value *
1203 valShift (value * lval, value * rval, int lr)
1204 {
1205   value *val;
1206
1207   /* create a new value */
1208   val = newValue ();
1209   val->type = val->etype = newIntLink ();
1210   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1211   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1212   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1213
1214   if (SPEC_LONG (val->type))
1215     {
1216       if (SPEC_USIGN (val->type))
1217         SPEC_CVAL (val->type).v_ulong = lr ? 
1218           (unsigned long) floatFromVal (lval) << (unsigned long) floatFromVal (rval) : \
1219           (unsigned long) floatFromVal (lval) >> (unsigned long) floatFromVal (rval);
1220       else
1221         SPEC_CVAL (val->type).v_long = lr ?
1222           (long) floatFromVal (lval) << (long) floatFromVal (rval) : \
1223           (long) floatFromVal (lval) >> (long) floatFromVal (rval);
1224     }
1225   else
1226     {
1227       if (SPEC_USIGN (val->type)) {
1228         SPEC_CVAL (val->type).v_uint = lr ? 
1229           (unsigned) floatFromVal (lval) << (unsigned) floatFromVal (rval) :\
1230           (unsigned) floatFromVal (lval) >> (unsigned) floatFromVal (rval);
1231       } else {
1232         SPEC_CVAL (val->type).v_int = lr ?
1233           (int) floatFromVal (lval) << (int) floatFromVal (rval) : \
1234           (int) floatFromVal (lval) >> (int) floatFromVal (rval);
1235       }
1236     }
1237
1238   return cheapestVal(val);
1239 }
1240
1241 /*------------------------------------------------------------------*/
1242 /* valCompare- Compares two literal                                 */
1243 /*------------------------------------------------------------------*/
1244 value *
1245 valCompare (value * lval, value * rval, int ctype)
1246 {
1247   value *val;
1248
1249   /* create a new value */
1250   val = newValue ();
1251   val->type = val->etype = newCharLink ();
1252   val->type->class = SPECIFIER;
1253   SPEC_NOUN (val->type) = V_CHAR;       /* type is char */
1254   SPEC_USIGN (val->type) = 1;
1255   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1256
1257   switch (ctype)
1258     {
1259     case '<':
1260       SPEC_CVAL (val->type).v_int = floatFromVal (lval) < floatFromVal (rval);
1261       break;
1262
1263     case '>':
1264       SPEC_CVAL (val->type).v_int = floatFromVal (lval) > floatFromVal (rval);
1265       break;
1266
1267     case LE_OP:
1268       SPEC_CVAL (val->type).v_int = floatFromVal (lval) <= floatFromVal (rval);
1269       break;
1270
1271     case GE_OP:
1272       SPEC_CVAL (val->type).v_int = floatFromVal (lval) >= floatFromVal (rval);
1273       break;
1274
1275     case EQ_OP:
1276       SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval);
1277       break;
1278
1279     case NE_OP:
1280       SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval);
1281       break;
1282
1283     }
1284
1285   return val;
1286 }
1287
1288 /*------------------------------------------------------------------*/
1289 /* valBitwise - Bitwise operation                                   */
1290 /*------------------------------------------------------------------*/
1291 value *
1292 valBitwise (value * lval, value * rval, int op)
1293 {
1294   value *val;
1295
1296   /* create a new value */
1297   val = newValue ();
1298   val->type = copyLinkChain (lval->type);
1299   val->etype = getSpec (val->type);
1300
1301   switch (op)
1302     {
1303     case '&':
1304       if (SPEC_LONG (val->type))
1305         {
1306           if (SPEC_USIGN (val->type))
1307             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) &
1308               (unsigned long) floatFromVal (rval);
1309           else
1310             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) &
1311               (long) floatFromVal (rval);
1312         }
1313       else
1314         {
1315           if (SPEC_USIGN (val->type))
1316             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) &
1317               (unsigned) floatFromVal (rval);
1318           else
1319             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) & (int) floatFromVal (rval);
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
1343       break;
1344
1345     case '^':
1346       if (SPEC_LONG (val->type))
1347         {
1348           if (SPEC_USIGN (val->type))
1349             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) ^
1350               (unsigned long) floatFromVal (rval);
1351           else
1352             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) ^
1353               (long) floatFromVal (rval);
1354         }
1355       else
1356         {
1357           if (SPEC_USIGN (val->type))
1358             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) ^
1359               (unsigned) floatFromVal (rval);
1360           else
1361             SPEC_CVAL (val->type).v_int =
1362               (int) floatFromVal (lval) ^ (int) floatFromVal (rval);
1363         }
1364       break;
1365     }
1366
1367   return cheapestVal(val);
1368 }
1369
1370 /*------------------------------------------------------------------*/
1371 /* valAndOr   - Generates code for and / or operation               */
1372 /*------------------------------------------------------------------*/
1373 value *
1374 valLogicAndOr (value * lval, value * rval, int op)
1375 {
1376   value *val;
1377
1378   /* create a new value */
1379   val = newValue ();
1380   val->type = val->etype = newCharLink ();
1381   val->type->class = SPECIFIER;
1382   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1383   SPEC_USIGN (val->type) = 0;
1384
1385   switch (op)
1386     {
1387     case AND_OP:
1388       SPEC_CVAL (val->type).v_int = floatFromVal (lval) && floatFromVal (rval);
1389       break;
1390
1391     case OR_OP:
1392       SPEC_CVAL (val->type).v_int = floatFromVal (lval) || floatFromVal (rval);
1393       break;
1394     }
1395
1396
1397   return val;
1398 }
1399
1400 /*------------------------------------------------------------------*/
1401 /* valCastLiteral - casts a literal value to another type           */
1402 /*------------------------------------------------------------------*/
1403 value *
1404 valCastLiteral (sym_link * dtype, double fval)
1405 {
1406   value *val;
1407
1408   if (!dtype)
1409     return NULL;
1410
1411   val = newValue ();
1412   val->etype = getSpec (val->type = copyLinkChain (dtype));
1413   SPEC_SCLS (val->etype) = S_LITERAL;
1414   /* if it is not a specifier then we can assume that */
1415   /* it will be an unsigned long                      */
1416   if (!IS_SPEC (val->type))
1417     {
1418       SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1419       return val;
1420     }
1421
1422   if (SPEC_NOUN (val->etype) == V_FLOAT)
1423     SPEC_CVAL (val->etype).v_float = fval;
1424   else
1425     {
1426       if (SPEC_LONG (val->etype))
1427         {
1428           if (SPEC_USIGN (val->etype))
1429             SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1430           else
1431             SPEC_CVAL (val->etype).v_long = (long) fval;
1432         }
1433       else
1434         {
1435           if (SPEC_USIGN (val->etype))
1436             SPEC_CVAL (val->etype).v_uint = (unsigned int) fval;
1437           else
1438             SPEC_CVAL (val->etype).v_int = (int) fval;
1439         }
1440     }
1441   return val;
1442 }
1443
1444 /*------------------------------------------------------------------*/
1445 /* getNelements - determines # of elements from init list           */
1446 /*------------------------------------------------------------------*/
1447 int 
1448 getNelements (sym_link * type, initList * ilist)
1449 {
1450   sym_link *etype = getSpec (type);
1451   int i;
1452
1453   if (!ilist)
1454     return 0;
1455
1456   if (ilist->type == INIT_DEEP)
1457     ilist = ilist->init.deep;
1458
1459   /* if type is a character array and there is only one
1460      (string) initialiser then get the length of the string */
1461   if (IS_ARRAY (type) && IS_CHAR (etype) && !ilist->next)
1462     {
1463       ast *iast = ilist->init.node;
1464       value *v = (iast->type == EX_VALUE ? iast->opval.val : NULL);
1465       if (!v)
1466         {
1467           werror (W_INIT_WRONG);
1468           return 0;
1469         }
1470
1471       if (IS_ARRAY (v->type) && IS_CHAR (v->etype))
1472         // yep, it's a string
1473         {
1474           return DCL_ELEM (v->type);
1475         }
1476     }
1477
1478   i = 0;
1479   while (ilist)
1480     {
1481       i++;
1482       ilist = ilist->next;
1483     }
1484
1485   return i;
1486 }
1487
1488 /*-----------------------------------------------------------------*/
1489 /* valForArray - returns a value with name of array index          */
1490 /*-----------------------------------------------------------------*/
1491 value *
1492 valForArray (ast * arrExpr)
1493 {
1494   value *val, *lval = NULL;
1495   char buffer[128];
1496   int size = getSize (arrExpr->left->ftype->next);
1497   /* if the right or left is an array
1498      resolve it first */
1499   if (IS_AST_OP (arrExpr->left))
1500     {
1501       if (arrExpr->left->opval.op == '[')
1502         lval = valForArray (arrExpr->left);
1503       else if (arrExpr->left->opval.op == '.')
1504         lval = valForStructElem (arrExpr->left->left,
1505                                  arrExpr->left->right);
1506       else if (arrExpr->left->opval.op == PTR_OP &&
1507                IS_ADDRESS_OF_OP (arrExpr->left->left))
1508         lval = valForStructElem (arrExpr->left->left->left,
1509                                  arrExpr->left->right);
1510       else
1511         return NULL;
1512
1513     }
1514   else if (!IS_AST_SYM_VALUE (arrExpr->left))
1515     return NULL;
1516
1517   if (!IS_AST_LIT_VALUE (arrExpr->right))
1518     return NULL;
1519
1520   val = newValue ();
1521   if (!lval)
1522     sprintf (buffer, "%s", AST_SYMBOL (arrExpr->left)->rname);
1523   else
1524     sprintf (buffer, "%s", lval->name);
1525
1526   sprintf (val->name, "(%s + %d)", buffer,
1527            (int) AST_LIT_VALUE (arrExpr->right) * size);
1528
1529   val->type = newLink ();
1530   if (SPEC_SCLS (arrExpr->left->etype) == S_CODE)
1531     {
1532       DCL_TYPE (val->type) = CPOINTER;
1533       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1534     }
1535   else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA)
1536     DCL_TYPE (val->type) = FPOINTER;
1537   else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK)
1538     DCL_TYPE (val->type) = PPOINTER;
1539   else if (SPEC_SCLS (arrExpr->left->etype) == S_IDATA)
1540     DCL_TYPE (val->type) = IPOINTER;
1541   else if (SPEC_SCLS (arrExpr->left->etype) == S_EEPROM)
1542     DCL_TYPE (val->type) = EEPPOINTER;
1543   else
1544     DCL_TYPE (val->type) = POINTER;
1545   val->type->next = arrExpr->left->ftype;
1546   val->etype = getSpec (val->type);
1547   return val;
1548 }
1549
1550 /*-----------------------------------------------------------------*/
1551 /* valForStructElem - returns value with name of struct element    */
1552 /*-----------------------------------------------------------------*/
1553 value *
1554 valForStructElem (ast * structT, ast * elemT)
1555 {
1556   value *val, *lval = NULL;
1557   char buffer[128];
1558   symbol *sym;
1559
1560   /* left could be furthur derefed */
1561   if (IS_AST_OP (structT))
1562     {
1563       if (structT->opval.op == '[')
1564         lval = valForArray (structT);
1565       else if (structT->opval.op == '.')
1566         lval = valForStructElem (structT->left, structT->right);
1567       else if (structT->opval.op == PTR_OP &&
1568                IS_ADDRESS_OF_OP (structT->left))
1569         lval = valForStructElem (structT->left->left,
1570                                  structT->right);
1571       else
1572         return NULL;
1573     }
1574
1575   if (!IS_AST_SYM_VALUE (elemT))
1576     return NULL;
1577
1578   if (!IS_STRUCT (structT->etype))
1579     return NULL;
1580
1581   if ((sym = getStructElement (SPEC_STRUCT (structT->etype),
1582                                AST_SYMBOL (elemT))) == NULL)
1583     {
1584       return NULL;
1585     }
1586
1587   val = newValue ();
1588   if (!lval)
1589     sprintf (buffer, "%s", AST_SYMBOL (structT)->rname);
1590   else
1591     sprintf (buffer, "%s", lval->name);
1592
1593   sprintf (val->name, "(%s + %d)", buffer,
1594            (int) sym->offset);
1595
1596   val->type = newLink ();
1597   if (SPEC_SCLS (structT->etype) == S_CODE)
1598     {
1599       DCL_TYPE (val->type) = CPOINTER;
1600       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1601     }
1602   else if (SPEC_SCLS (structT->etype) == S_XDATA)
1603     DCL_TYPE (val->type) = FPOINTER;
1604   else if (SPEC_SCLS (structT->etype) == S_XSTACK)
1605     DCL_TYPE (val->type) = PPOINTER;
1606   else if (SPEC_SCLS (structT->etype) == S_IDATA)
1607     DCL_TYPE (val->type) = IPOINTER;
1608   else if (SPEC_SCLS (structT->etype) == S_EEPROM)
1609     DCL_TYPE (val->type) = EEPPOINTER;
1610   else
1611     DCL_TYPE (val->type) = POINTER;
1612   val->type->next = sym->type;
1613   val->etype = getSpec (val->type);
1614   return val;
1615 }
1616
1617 /*-----------------------------------------------------------------*/
1618 /* valForCastAggr - will return value for a cast of an aggregate   */
1619 /*                  plus minus a constant                          */
1620 /*-----------------------------------------------------------------*/
1621 value *
1622 valForCastAggr (ast * aexpr, sym_link * type, ast * cnst, int op)
1623 {
1624   value *val;
1625
1626   if (!IS_AST_SYM_VALUE (aexpr))
1627     return NULL;
1628   if (!IS_AST_LIT_VALUE (cnst))
1629     return NULL;
1630
1631   val = newValue ();
1632
1633   sprintf (val->name, "(%s %c %d)",
1634            AST_SYMBOL (aexpr)->rname, op,
1635            getSize (type->next) * (int) AST_LIT_VALUE (cnst));
1636
1637   val->type = type;
1638   val->etype = getSpec (val->type);
1639   return val;
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* valForCastAggr - will return value for a cast of an aggregate   */
1644 /*                  with no constant                               */
1645 /*-----------------------------------------------------------------*/
1646 value *
1647 valForCastArr (ast * aexpr, sym_link * type)
1648 {
1649   value *val;
1650
1651   if (!IS_AST_SYM_VALUE (aexpr))
1652     return NULL;
1653
1654   val = newValue ();
1655
1656   sprintf (val->name, "(%s)",
1657            AST_SYMBOL (aexpr)->rname);
1658
1659   val->type = type;
1660   val->etype = getSpec (val->type);
1661   return val;
1662 }