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