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