changes inline asm buffers from static to dynamic size
[fw/sdcc] / src / asm.c
1 /** @file asm.c
2     Provides output functions that modify the output string
3     based on the input tokens and the assembler token mapping
4     specification loaded.
5
6     Note that the functions below only handle digit format modifiers.
7     eg %02X is ok, but %lu and %.4u will fail.
8 */
9 #include "common.h"
10 #include "asm.h"
11
12 /* A 'token' is like !blah or %24f and is under the programmers
13    control. */
14 #define MAX_TOKEN_LEN           64
15
16 static hTab *_h;
17
18 char *
19 FileBaseName (char *fileFullName)
20 {
21   char *p = fileFullName;
22
23   if (!fileFullName) {
24     return "unknown";
25   }
26
27   while (*fileFullName)
28     {
29       if ((*fileFullName == '/') || (*fileFullName == '\\') || (*fileFullName == ':'))
30         {
31           p = fileFullName;
32           p++;
33         }
34       fileFullName++;
35     }
36   return p;
37 }
38
39 static const char *
40 _findMapping (const char *szKey)
41 {
42   return shash_find (_h, szKey);
43 }
44
45 #if 0
46 static void 
47 _iprintf (char *pInto, const char *sz, va_list * pap)
48 {
49   char format[MAX_TOKEN_LEN];
50   char *pStart = pInto;
51   static int count;
52
53   while (*sz)
54     {
55       if (*sz == '%')
56         {
57           switch (*++sz)
58             {
59               /* See if it's a special emitter */
60             case 'r':
61               wassert (0);
62               break;
63               /* Name of the code segment */
64             case 'C':
65               strcpy (pInto, CODE_NAME);
66               pInto = pStart + strlen (pStart);
67               sz++;
68               break;
69             case 'F':
70               strcpy (pInto, srcFileName);
71               pInto = pStart + strlen (pStart);
72               sz++;
73               break;
74             case 'I':
75               sprintf (pInto, "%u", ++count);
76               pInto = pStart + strlen (pStart);
77               sz++;
78               break;
79             default:
80               {
81                 /* Scan out the arg and pass it on to sprintf */
82                 char *p = format;
83                 *p++ = '%';
84                 while (isdigit (*sz))
85                   *p++ = *sz++;
86                 *p++ = *sz++;
87                 *p = '\0';
88                 vsprintf (pInto, format, *pap);
89                 /* PENDING: Assume that the arg length was an int */
90                 (void) va_arg (*pap, int);
91               }
92             }
93           pInto = pStart + strlen (pStart);
94         }
95       else
96         {
97           *pInto++ = *sz++;
98         }
99     }
100   *pInto = '\0';
101 }
102
103 void 
104 tvsprintf (char *buffer, const char *sz, va_list ap)
105 {
106   char *pInto = buffer;
107   char *p;
108   char token[MAX_TOKEN_LEN];
109
110   buffer[0] = '\0';
111
112   while (*sz)
113     {
114       if (*sz == '!')
115         {
116           /* Start of a token.  Search until the first
117              [non alplha, *] and call it a token. */
118           const char *t;
119           p = token;
120           sz++;
121           while (isalpha (*sz) || *sz == '*')
122             {
123               *p++ = *sz++;
124             }
125           *p = '\0';
126           /* Now find the token in the token list */
127           if ((t = _findMapping (token)))
128             {
129               printf ("tvsprintf: found token \"%s\" to \"%s\"\n", token, t);
130               _iprintf (pInto, t, &ap);
131               pInto = buffer + strlen (buffer);
132             }
133           else
134             {
135               fprintf (stderr, "Cant find token \"%s\"\n", token);
136               wassert (0);
137             }
138         }
139       else if (*sz == '%')
140         {
141           p = token;
142           *p++ = *sz++;
143           while (!isalpha (*sz))
144             {
145               *p++ = *sz++;
146             }
147           *p++ = *sz++;
148           *p = '\0';
149           vsprintf (pInto, token, ap);
150           pInto = buffer + strlen (buffer);
151           (void) va_arg (ap, int);
152         }
153       else
154         {
155           *pInto++ = *sz++;
156         }
157     }
158   *pInto = '\0';
159 }
160 #else
161 // Append a string onto another, and update the pointer to the end of
162 // the new string.
163 static char *
164 _appendAt (char *at, char *onto, const char *sz)
165 {
166   wassert (at && onto && sz);
167   strcpy (at, sz);
168   return at + strlen (sz);
169 }
170
171 void 
172 tvsprintf (char *buffer, const char *format, va_list ap)
173 {
174   // Under Linux PPC va_list is a structure instead of a primitive type,
175   // and doesnt like being passed around.  This version turns everything
176   // into one function.
177
178   // Supports:
179   //  !tokens
180   //  %[CIF] - special formats with no argument (ie list isnt touched)
181   //  All of the system formats
182
183   // This is acheived by expanding the tokens and zero arg formats into
184   // one big format string, which is passed to the native printf.
185   static int count;
186   char newformat[INITIAL_INLINEASM];
187   char *pInto = newformat;
188   char *p;
189   char token[MAX_TOKEN_LEN];
190   const char *sz = format;
191
192   // NULL terminate it to let strlen work.
193   *pInto = '\0';
194
195   while (*sz)
196     {
197       if (*sz == '!')
198         {
199           /* Start of a token.  Search until the first
200              [non alpha, *] and call it a token. */
201           const char *t;
202           p = token;
203           sz++;
204           while (isalpha (*sz) || *sz == '*')
205             {
206               *p++ = *sz++;
207             }
208           *p = '\0';
209           /* Now find the token in the token list */
210           if ((t = _findMapping (token)))
211             {
212               pInto = _appendAt (pInto, newformat, t);
213             }
214           else
215             {
216               fprintf (stderr, "Cant find token \"%s\"\n", token);
217               wassert (0);
218             }
219         }
220       else if (*sz == '%')
221         {
222           // See if its one that we handle.
223           sz++;
224           switch (*sz)
225             {
226             case 'C':
227               // Code segment name.
228               pInto = _appendAt (pInto, newformat, CODE_NAME);
229               break;
230             case 'F':
231               // Source file name.
232               pInto = _appendAt (pInto, newformat, srcFileName);
233               break;
234             case 'I':
235               {
236                 // Unique ID.
237                 char id[20];
238                 sprintf (id, "%u", ++count);
239                 pInto = _appendAt (pInto, newformat, id);
240                 break;
241               }
242             default:
243               // Not one of ours.  Copy until the end.
244               *pInto++ = '%';
245               while (!isalpha (*sz))
246                 {
247                   *pInto++ = *sz++;
248                 }
249               *pInto++ = *sz++;
250             }
251         }
252       else
253         {
254           *pInto++ = *sz++;
255         }
256     }
257   *pInto = '\0';
258
259   // Now do the actual printing
260   vsprintf (buffer, newformat, ap);
261 }
262 #endif
263
264 void 
265 tfprintf (FILE * fp, const char *szFormat,...)
266 {
267   va_list ap;
268   char buffer[INITIAL_INLINEASM];
269
270   va_start (ap, szFormat);
271   tvsprintf (buffer, szFormat, ap);
272   fputs (buffer, fp);
273 }
274
275 void 
276 tsprintf (char *buffer, const char *szFormat,...)
277 {
278   va_list ap;
279   va_start (ap, szFormat);
280   tvsprintf (buffer, szFormat, ap);
281 }
282
283 void 
284 asm_addTree (const ASM_MAPPINGS * pMappings)
285 {
286   const ASM_MAPPING *pMap;
287
288   /* Traverse down first */
289   if (pMappings->pParent)
290     asm_addTree (pMappings->pParent);
291   pMap = pMappings->pMappings;
292   while (pMap->szKey && pMap->szValue) {
293       shash_add (&_h, pMap->szKey, pMap->szValue);
294       pMap++;
295   }
296 }
297
298 static const ASM_MAPPING _asxxxx_mapping[] =
299 {
300   {"labeldef", "%s::"},
301   {"slabeldef", "%s:"},
302   {"tlabeldef", "%05d$:"},
303   {"tlabel", "%05d$"},
304   {"immed", "#"},
305   {"zero", "#0x00"},
306   {"one", "#0x01"},
307   {"area", ".area %s"},
308   {"areacode", ".area %s"},
309   {"areadata", ".area %s"},
310   {"areahome", ".area %s"},
311   {"ascii", ".ascii \"%s\""},
312   {"ds", ".ds %d"},
313   {"db", ".db"},
314   {"dbs", ".db %s"},
315   {"dw", ".dw"},
316   {"dws", ".dw %s"},
317   {"constbyte", "0x%02X"},
318   {"constword", "0x%04X"},
319   {"immedword", "#0x%04X"},
320   {"immedbyte", "#0x%02X"},
321   {"hashedstr", "#%s"},
322   {"lsbimmeds", "#<%s"},
323   {"msbimmeds", "#>%s"},
324   {"module", ".module %s"},
325   {"global", ".globl %s"},
326   {"fileprelude", ""},
327   {"functionheader",
328    "; ---------------------------------\n"
329    "; Function %s\n"
330    "; ---------------------------------"
331   },
332   {"functionlabeldef", "%s:"},
333   {"bankimmeds", "0     ; PENDING: bank support"},
334   {NULL, NULL}
335 };
336
337 static const ASM_MAPPING _gas_mapping[] =
338 {
339   {"labeldef", "%s::"},
340   {"slabeldef", "%s:"},
341   {"tlabeldef", "%05d$:"},
342   {"tlabel", "%05d$"},
343   {"immed", "#"},
344   {"zero", "#0x00"},
345   {"one", "#0x01"},
346   {"area", ".section %s"},
347   {"areacode", ".section %s"},
348   {"areadata", ".section %s"},
349   {"areahome", ".section %s"},
350   {"ascii", ".ascii \"%s\""},
351   {"ds", ".ds %d"},
352   {"db", ".db"},
353   {"dbs", ".db %s"},
354   {"dw", ".dw"},
355   {"dws", ".dw %s"},
356   {"constbyte", "0x%02X"},
357   {"constword", "0x%04X"},
358   {"immedword", "#0x%04X"},
359   {"immedbyte", "#0x%02X"},
360   {"hashedstr", "#%s"},
361   {"lsbimmeds", "#<%s"},
362   {"msbimmeds", "#>%s"},
363   {"module", ".file \"%s.c\""},
364   {"global", ".globl %s"},
365   {"fileprelude", ""},
366   {"functionheader",
367    "; ---------------------------------\n"
368    "; Function %s\n"
369    "; ---------------------------------"
370   },
371   {"functionlabeldef", "%s:"},
372   {"bankimmeds", "0     ; PENDING: bank support"},
373   {NULL, NULL}
374 };
375
376 const ASM_MAPPINGS asm_asxxxx_mapping =
377 {
378   NULL,
379   _asxxxx_mapping
380 };
381
382 const ASM_MAPPINGS asm_gas_mapping =
383 {
384   NULL,
385   _gas_mapping
386 };