sim/ucsim/gui.src/Makefile.in: target "install" builds the same packages as target...
[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   char quote = '\0';
40
41   assert(pinto);
42   assert(pvals);
43   assert(pfrom);
44
45   while (plen && *pfrom) {
46     switch (*pfrom) {
47     case '"':
48     case '\'':
49       if (quote != '\0') {
50         /* write previous quote */
51         *pinto++ = quote;
52       }
53       quote = *pfrom;
54       ++pfrom;
55       break;
56
57     case '{':
58       {
59         const char *pend = ++pfrom;
60         char name[MAX_MACRO_NAME_LENGTH];
61         const char *pval;
62
63         /* Find the end of macro */
64         while (*pend && *pend != '}') {
65             pend++;
66         }
67         if (*pend != '}') {
68             wassertl(0, "Unterminated macro expansion");
69         }
70
71         /* Pull out the macro name */
72         if (pend - pfrom >= MAX_MACRO_NAME_LENGTH) {
73             wassertl(0, "macro name too long");
74         }
75
76         strncpy(name, pfrom, pend-pfrom);
77         name[pend-pfrom] = '\0';
78
79         /* Look up the value in the hash table */
80         pval = shash_find (pvals, name);
81         
82         if (pval == NULL) {
83           /* Empty macro value */
84           if (quote != '\0') {
85             /* It was a quote */
86             if (pend[1] == quote) {
87               /* Start quote equals end quote: skip both */
88               ++pend;
89             }
90             else {
91               /* Start quote not equals end quote: add both */
92               *pinto++ = quote;
93               --plen;
94             }
95           }
96         }
97         else {
98           if (quote != '\0') {
99             /* It was a quote, add it */
100             *pinto++ = quote;
101           }
102           if (--plen > 0) {
103             /* Replace macro*/
104             strncpy(pinto, pval, plen);
105             pinto += strlen(pval);
106             plen -= plen > strlen(pval) ? strlen(pval) : plen;
107             fdidsomething = TRUE;
108           }
109         }
110
111         quote = '\0';
112         pfrom = pend + 1;
113       }
114       break;
115
116     default:
117       if (quote != '\0') {
118         *pinto++ = quote;
119         quote = '\0';
120       }
121
122       if (--plen > 0) {
123         /* Pass through */
124         *pinto++ = *pfrom++;
125         --plen;
126       }
127     }
128   }
129
130   if (!plen) {
131     wassertl(0, "macro expansion too long");
132   }
133     
134   *pinto = '\0';
135
136   /* If we did something then recursivly expand any expanded macros */
137   if (fdidsomething) {
138     char ainto[MAX_STRING_LENGTH];
139     _evalMacros(ainto, pvals, apinto, MAX_STRING_LENGTH);
140     strncpyz(apinto, ainto, alen);
141   }
142 }
143
144 char *
145 mvsprintf(hTab *pvals, const char *pformat, va_list ap)
146 {
147   char ainto[MAX_STRING_LENGTH];
148   char atmp[MAX_STRING_LENGTH];
149
150   /* Recursivly evaluate all the macros in the string */
151   _evalMacros(ainto, pvals, pformat, MAX_STRING_LENGTH);
152   /* Evaluate all the arguments */
153 #if defined(HAVE_VSNPRINTF)
154     if (vsnprintf(atmp, MAX_STRING_LENGTH, ainto, ap) >= MAX_STRING_LENGTH)
155     {
156         fprintf(stderr, "Internal error: mvsprintf output truncated.\n");
157     }
158 #else    
159     {   
160         int wlen; 
161         
162         wlen = vsprintf(atmp, ainto, ap);
163         
164         if (wlen < 0 || wlen >= MAX_STRING_LENGTH)
165         {
166             wassertl(0, "mvsprintf overflowed.");
167         }
168     }
169 #endif    
170     
171   /* Recursivly evaluate any macros that were used as arguments */
172   _evalMacros(ainto, pvals, atmp, MAX_STRING_LENGTH);
173
174   /* Return a copy of the evaluated string. */
175   return Safe_strdup(ainto);
176 }
177
178 char *msprintf(hTab *pvals, const char *pformat, ...)
179 {
180   va_list ap;
181   char *pret;
182
183   va_start(ap, pformat);
184
185   pret = mvsprintf(pvals, pformat, ap);
186
187   va_end(ap);
188
189   return pret;
190 }
191
192 void
193 mfprintf(FILE *fp, hTab *pvals, const char *pformat, ...)
194 {
195   va_list ap;
196   char *p;
197
198   va_start(ap, pformat);
199
200   p = mvsprintf(pvals, pformat, ap);
201
202   va_end(ap);
203
204   fputs(p, fp);
205   Safe_free(p);
206 }