OP_SYMBOL and OP_VALUE check their parameters are the proper type
[fw/sdcc] / src / SDCCmacro.c
1 /*-------------------------------------------------------------------------
2   SDCCmain.c - Macro support code.
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26
27 enum 
28   {
29     MAX_STRING_LENGTH     = 2048,
30     MAX_MACRO_NAME_LENGTH = 128
31   };
32
33 void
34 _evalMacros(char *apinto, hTab *pvals, const char *pfrom, size_t alen)
35 {
36   bool  fdidsomething = FALSE;
37   char  *pinto = apinto;
38   size_t plen = alen;
39
40   assert(pinto);
41   assert(pvals);
42   assert(pfrom);
43
44   while (plen && *pfrom)
45     {
46       if (*pfrom == '{')
47         {
48           const char *pend = ++pfrom;
49           char name[MAX_MACRO_NAME_LENGTH];
50           const char *pval;
51
52           while (*pend && *pend != '}')
53             {
54               pend++;
55             }
56           if (*pend != '}')
57             {
58               wassertl(0, "Unterminated macro expansion");
59             }
60           /* Pull out the macro name */
61           if (pend - pfrom >= MAX_MACRO_NAME_LENGTH)
62           {
63               wassertl(0, "macro name too long");
64           }
65             
66           strncpy(name, pfrom, pend-pfrom);
67           name[pend-pfrom] = '\0';
68
69           /* Look up the value in the hash table */
70           pval = shash_find (pvals, name);
71           
72           if (pval == NULL)
73             {
74               fprintf (stderr, "Cant find macro \"%s\"\n", name);
75               wassertl (0, "Invalid macro name");
76             }
77             else
78             {
79                 /* Replace */
80                 strncpy(pinto, pval, plen);
81                 pinto += strlen(pval);
82                 plen -= plen > strlen(pval) ? strlen(pval) : plen;
83                 fdidsomething = TRUE;
84             }
85
86           pfrom = pend+1;
87         }
88       else
89         {
90           /* Pass through */
91           *pinto++ = *pfrom++;
92           plen--;
93         }
94     }
95
96   if (!plen)
97   {
98       wassertl(0, "macro expansion too long");
99   }
100     
101   *pinto = '\0';
102
103   /* If we did something then recursivly expand any expanded macros */
104   if (fdidsomething)
105     {
106       char ainto[MAX_STRING_LENGTH];
107       _evalMacros(ainto, pvals, apinto, MAX_STRING_LENGTH);
108       strncpyz(apinto, ainto, alen);
109     }
110 }
111
112 char *
113 mvsprintf(hTab *pvals, const char *pformat, va_list ap)
114 {
115   char ainto[MAX_STRING_LENGTH];
116   char atmp[MAX_STRING_LENGTH];
117
118   /* Recursivly evaluate all the macros in the string */
119   _evalMacros(ainto, pvals, pformat, MAX_STRING_LENGTH);
120   /* Evaluate all the arguments */
121 #if defined(HAVE_VSNPRINTF)
122     if (vsnprintf(atmp, MAX_STRING_LENGTH, ainto, ap) >= MAX_STRING_LENGTH)
123     {
124         fprintf(stderr, "Internal error: mvsprintf output truncated.\n");
125     }
126 #else    
127     {   
128         int wlen; 
129         
130         wlen = vsprintf(atmp, ainto, ap);
131         
132         if (wlen < 0 || wlen >= MAX_STRING_LENGTH)
133         {
134             wassertl(0, "mvsprintf overflowed.");
135         }
136     }
137 #endif    
138     
139   /* Recursivly evaluate any macros that were used as arguments */
140   _evalMacros(ainto, pvals, atmp, MAX_STRING_LENGTH);
141
142   /* Return a copy of the evaluated string. */
143   return Safe_strdup(ainto);
144 }
145
146 char *msprintf(hTab *pvals, const char *pformat, ...)
147 {
148   va_list ap;
149   char *pret;
150
151   va_start(ap, pformat);
152
153   pret = mvsprintf(pvals, pformat, ap);
154
155   va_end(ap);
156
157   return pret;
158 }
159
160 void
161 mfprintf(FILE *fp, hTab *pvals, const char *pformat, ...)
162 {
163   va_list ap;
164   char *p;
165
166   va_start(ap, pformat);
167
168   p = mvsprintf(pvals, pformat, ap);
169
170   va_end(ap);
171
172   fputs(p, fp);
173   Safe_free(p);
174 }