removed gcc warning: 'c' may be used uninitialized in this function
[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 <errno.h>
10
11 #include "common.h"
12 #include "asm.h"
13 #include "dbuf_string.h"
14
15 /* A 'token' is like !blah or %24f and is under the programmers
16    control. */
17 #define MAX_TOKEN_LEN           64
18
19 static hTab *_h;
20
21 char *
22 FileBaseName (char *fileFullName)
23 {
24   char *p = fileFullName;
25
26   if (!fileFullName) {
27     return "unknown";
28   }
29
30   while (*fileFullName)
31     {
32       if ((*fileFullName == '/') || (*fileFullName == '\\') || (*fileFullName == ':'))
33         {
34           p = fileFullName;
35           p++;
36         }
37       fileFullName++;
38     }
39   return p;
40 }
41
42 void
43 dbuf_tvprintf (struct dbuf_s *dbuf, const char *format, va_list ap)
44 {
45   // Under Linux PPC va_list is a structure instead of a primitive type,
46   // and doesnt like being passed around.  This version turns everything
47   // into one function.
48
49   // Supports:
50   //  !tokens
51   //  %[CIFN] - special formats with no argument (ie list isnt touched)
52   //  All of the system formats
53
54   // This is acheived by expanding the tokens and zero arg formats into
55   // one big format string, which is passed to the native printf.
56   static int count;
57   struct dbuf_s tmpDBuf;
58   const char *noTokens;
59   char *p;
60   char token[MAX_TOKEN_LEN];
61   const char *sz = format;
62
63   dbuf_init(&tmpDBuf, INITIAL_INLINEASM);
64
65   /* First pass: expand all of the macros */
66   while (*sz)
67     {
68       if (*sz == '!')
69         {
70           /* Start of a token.  Search until the first
71              [non alpha, *] and call it a token. */
72           const char *t;
73           p = token;
74           sz++;
75           while (isalpha ((unsigned char)*sz) || *sz == '*')
76             {
77               *p++ = *sz++;
78             }
79           *p = '\0';
80           /* Now find the token in the token list */
81           if ((t = shash_find (_h, token)))
82             {
83               dbuf_append_str(&tmpDBuf, t);
84             }
85           else
86             {
87               fprintf (stderr, "Cant find token \"%s\"\n", token);
88               wassert (0);
89             }
90         }
91       else
92         {
93           dbuf_append_char(&tmpDBuf, *sz++);
94         }
95     }
96
97   /* Second pass: Expand any macros that we own */
98   noTokens = dbuf_c_str(&tmpDBuf);
99   sz = noTokens;
100
101   /* recycle tmpDBuf */
102   dbuf_init(&tmpDBuf, INITIAL_INLINEASM);
103
104   while (*sz)
105     {
106       if (*sz == '%')
107         {
108           // See if its one that we handle.
109           sz++;
110           switch (*sz)
111             {
112             case 'C':
113               // Code segment name.
114               dbuf_append_str(&tmpDBuf, CODE_NAME);
115               sz++;
116               break;
117
118             case 'F':
119               // Source file name.
120               dbuf_append_str(&tmpDBuf, fullSrcFileName);
121               sz++;
122               break;
123
124             case 'N':
125               // Current function name.
126               dbuf_append_str(&tmpDBuf, currFunc->rname);
127               sz++;
128               break;
129
130             case 'I':
131               // Unique ID.
132               dbuf_printf(&tmpDBuf, "%u", ++count);
133               sz++;
134               break;
135
136             default:
137               // Not one of ours.  Copy until the end.
138               dbuf_append_char(&tmpDBuf, '%');
139               while (!isalpha ((unsigned char)*sz))
140                 dbuf_append_char(&tmpDBuf, *sz++);
141
142               dbuf_append_char(&tmpDBuf, *sz++);
143             }
144         }
145       else
146         {
147           dbuf_append_char(&tmpDBuf, *sz++);
148         }
149     }
150
151   dbuf_free(noTokens);
152
153   sz = dbuf_c_str(&tmpDBuf);
154
155   dbuf_vprintf(dbuf, sz, ap);
156
157   dbuf_destroy(&tmpDBuf);
158 }
159
160 void
161 dbuf_tprintf (struct dbuf_s *dbuf, const char *szFormat,...)
162 {
163   va_list ap;
164   va_start (ap, szFormat);
165   dbuf_tvprintf (dbuf, szFormat, ap);
166   va_end(ap);
167 }
168
169 void
170 tsprintf (char *buffer, size_t len, const char *szFormat,...)
171 {
172   va_list ap;
173   struct dbuf_s dbuf;
174   size_t copyLen;
175
176   dbuf_init(&dbuf, INITIAL_INLINEASM);
177
178   va_start (ap, szFormat);
179   dbuf_tvprintf (&dbuf, szFormat, ap);
180   va_end(ap);
181
182   copyLen = min(len - 1, dbuf_get_length(&dbuf));
183   memcpy(buffer, dbuf_get_buf(&dbuf), copyLen);
184   buffer[copyLen] = '\0';
185   dbuf_destroy(&dbuf);
186 }
187
188 void
189 tfprintf (FILE *fp, const char *szFormat,...)
190 {
191   va_list ap;
192   struct dbuf_s dbuf;
193   size_t len;
194
195   dbuf_init(&dbuf, INITIAL_INLINEASM);
196
197   va_start (ap, szFormat);
198   dbuf_tvprintf (&dbuf, szFormat, ap);
199   va_end(ap);
200
201   len = dbuf_get_length(&dbuf);
202   fwrite(dbuf_get_buf(&dbuf), 1, len, fp);
203   dbuf_destroy(&dbuf);
204 }
205
206 void
207 asm_addTree (const ASM_MAPPINGS * pMappings)
208 {
209   const ASM_MAPPING *pMap;
210
211   /* Traverse down first */
212   if (pMappings->pParent)
213     asm_addTree (pMappings->pParent);
214   pMap = pMappings->pMappings;
215   while (pMap->szKey && pMap->szValue) {
216       shash_add (&_h, pMap->szKey, pMap->szValue);
217       pMap++;
218   }
219 }
220
221 /*-----------------------------------------------------------------*/
222 /* printILine - return the readable i-code for this ic             */
223 /*-----------------------------------------------------------------*/
224 char *
225 printILine (iCode *ic)
226 {
227   char *verbalICode;
228   struct dbuf_s tmpBuf;
229   iCodeTable *icTab=getTableEntry(ic->op);
230
231   dbuf_init(&tmpBuf, 1024);
232
233   if (INLINEASM == ic->op)
234     dbuf_append (&tmpBuf, "inline", (sizeof "inline") - 1);
235   else {
236     /* stuff the temporary file with the readable icode */
237     icTab->iCodePrint(&tmpBuf, ic, icTab->printName);
238   }
239
240   /* null terminate the buffer */
241   dbuf_c_str(&tmpBuf);
242   verbalICode = dbuf_detach(&tmpBuf);
243
244   /* kill the trailing NL */
245   if ('\n' == verbalICode[strlen(verbalICode) - 1])
246     verbalICode[strlen(verbalICode) - 1] = '\0';
247
248   /* and throw it up */
249   return verbalICode;
250 }
251
252 /*-----------------------------------------------------------------*/
253 /* printCLine - return the c-code for this lineno                  */
254 /*-----------------------------------------------------------------*/
255 /* int rewinds=0; */
256 char *
257 printCLine (char *srcFile, int lineno)
258 {
259   static FILE *inFile=NULL;
260   static char inLineString[1024];
261   static int inLineNo=0;
262   static char lastSrcFile[PATH_MAX];
263   char *ilsP=inLineString;
264
265   if (inFile) {
266     if (strcmp (lastSrcFile, srcFile) != 0) {
267       fclose (inFile);
268       inFile = NULL;
269       inLineNo = 0;
270       strncpyz (lastSrcFile, srcFile, PATH_MAX);
271     }
272   }
273   if (!inFile && !(inFile = fopen(srcFile, "r"))) {
274     /* can't open the file:
275        don't panic, just return the error message */
276     SDCCsnprintf(inLineString, sizeof(inLineString), "ERROR: %s", strerror(errno));
277   }
278   else {
279     if (lineno<inLineNo) {
280       fseek (inFile, 0, SEEK_SET);
281       inLineNo=0;
282       /* rewinds++; */
283     }
284     while (fgets (inLineString, 1024, inFile)) {
285       inLineNo++;
286       if (inLineNo==lineno) {
287         // remove the trailing NL
288         inLineString[strlen(inLineString)-1]='\0';
289         break;
290       }
291     }
292   }
293
294   while (isspace ((unsigned char)*ilsP))
295     ilsP++;
296
297   return ilsP;
298 }
299
300 static const ASM_MAPPING _asxxxx_mapping[] =
301 {
302   {"labeldef", "%s::"},
303   {"slabeldef", "%s:"},
304   {"tlabeldef", "%05d$:"},
305   {"tlabel", "%05d$"},
306   {"immed", "#"},
307   {"zero", "#0x00"},
308   {"one", "#0x01"},
309   {"area", ".area %s"},
310   {"areacode", ".area %s"},
311   {"areadata", ".area %s"},
312   {"areahome", ".area %s"},
313   {"ascii", ".ascii \"%s\""},
314   {"ds", ".ds %d"},
315   {"db", ".db"},
316   {"dbs", ".db %s"},
317   {"dw", ".dw"},
318   {"dws", ".dw %s"},
319   {"constbyte", "0x%02X"},
320   {"constword", "0x%04X"},
321   {"immedword", "#0x%04X"},
322   {"immedbyte", "#0x%02X"},
323   {"hashedstr", "#%s"},
324   {"lsbimmeds", "#<%s"},
325   {"msbimmeds", "#>%s"},
326   {"module", ".module %s"},
327   {"global", ".globl %s"},
328   {"fileprelude", ""},
329   {"functionheader",
330    "; ---------------------------------\n"
331    "; Function %s\n"
332    "; ---------------------------------"
333   },
334   {"functionlabeldef", "%s:"},
335   {"bankimmeds", "0     ; PENDING: bank support"},
336   {"los","(%s & 0xFF)"},
337   {"his","(%s >> 8)"},
338   {"hihis","(%s >> 16)"},
339   {"hihihis","(%s >> 24)"},
340   {"lod","(%d & 0xFF)"},
341   {"hid","(%d >> 8)"},
342   {"hihid","(%d >> 16)"},
343   {"hihihid","(%d >> 24)"},
344   {"lol","(%05d$ & 0xFF)"},
345   {"hil","(%05d$ >> 8)"},
346   {"hihil","(%05d$ >> 16)"},
347   {"hihihil","(%05d$ >> 24)"},
348   {"equ","="},
349   {"org", ".org 0x%04X"},
350   {NULL, NULL}
351 };
352
353 static const ASM_MAPPING _gas_mapping[] =
354 {
355   {"labeldef", "%s::"},
356   {"slabeldef", "%s:"},
357   {"tlabeldef", "%05d$:"},
358   {"tlabel", "%05d$"},
359   {"immed", "#"},
360   {"zero", "#0x00"},
361   {"one", "#0x01"},
362   {"area", ".section %s"},
363   {"areacode", ".section %s"},
364   {"areadata", ".section %s"},
365   {"areahome", ".section %s"},
366   {"ascii", ".ascii \"%s\""},
367   {"ds", ".ds %d"},
368   {"db", ".db"},
369   {"dbs", ".db %s"},
370   {"dw", ".dw"},
371   {"dws", ".dw %s"},
372   {"constbyte", "0x%02X"},
373   {"constword", "0x%04X"},
374   {"immedword", "#0x%04X"},
375   {"immedbyte", "#0x%02X"},
376   {"hashedstr", "#%s"},
377   {"lsbimmeds", "#<%s"},
378   {"msbimmeds", "#>%s"},
379   {"module", ".file \"%s.c\""},
380   {"global", ".globl %s"},
381   {"extern", ".globl %s"},
382   {"fileprelude", ""},
383   {"functionheader",
384    "; ---------------------------------\n"
385    "; Function %s\n"
386    "; ---------------------------------"
387   },
388   {"functionlabeldef", "%s:"},
389   {"bankimmeds", "0     ; PENDING: bank support"},
390   {NULL, NULL}
391 };
392
393 static const ASM_MAPPING _a390_mapping[] =
394 {
395   {"labeldef", "%s:"},
396   {"slabeldef", "%s:"},
397   {"tlabeldef", "L%05d:"},
398   {"tlabel", "L%05d"},
399   {"immed", "#"},
400   {"zero", "#0"},
401   {"one", "#1"},
402   {"area", "; SECTION NOT SUPPORTED"},
403   {"areacode", "; SECTION NOT SUPPORTED"},
404   {"areadata", "; SECTION NOT SUPPORTED"},
405   {"areahome", "; SECTION NOT SUPPORTED"},
406   {"ascii", "db \"%s\""},
407   {"ds", "; STORAGE NOT SUPPORTED"},
408   {"db", "db"},
409   {"dbs", "db \"%s\""},
410   {"dw", "dw"},
411   {"dws", "dw %s"},
412   {"constbyte", "0%02xh"},
413   {"constword", "0%04xh"},
414   {"immedword", "#0%04Xh"},
415   {"immedbyte", "#0%02Xh"},
416   {"hashedstr", "#%s"},
417   {"lsbimmeds", "#<%s"},
418   {"msbimmeds", "#>%s"},
419   {"module", "; .file \"%s.c\""},
420   {"global", "; .globl %s"},
421   {"fileprelude", ""},
422   {"functionheader",
423    "; ---------------------------------\n"
424    "; Function %s\n"
425    "; ---------------------------------"
426   },
427   {"functionlabeldef", "%s:"},
428   {"bankimmeds", "0     ; PENDING: bank support"},
429   {"los","(%s & 0FFh)"},
430   {"his","((%s / 256) & 0FFh)"},
431   {"hihis","((%s / 65536) & 0FFh)"},
432   {"hihihis","((%s / 16777216) & 0FFh)"},
433   {"lod","(%d & 0FFh)"},
434   {"hid","((%d / 256) & 0FFh)"},
435   {"hihid","((%d / 65536) & 0FFh)"},
436   {"hihihid","((%d / 16777216) & 0FFh)"},
437   {"lol","(L%05d & 0FFh)"},
438   {"hil","((L%05d / 256) & 0FFh)"},
439   {"hihil","((L%05d / 65536) & 0FFh)"},
440   {"hihihil","((L%09d / 16777216) & 0FFh)"},
441   {"equ"," equ"},
442   {"org", ".org 0x%04X"},
443   {NULL, NULL}
444 };
445
446 static const ASM_MAPPING _xa_asm_mapping[] =
447 {
448   {"labeldef", "%s:"},
449   {"slabeldef", "%s:"},
450   {"tlabeldef", "L%05d:"},
451   {"tlabel", "L%05d"},
452   {"immed", "#"},
453   {"zero", "#0"},
454   {"one", "#1"},
455   {"area", ".area %s"},
456   {"areacode", ".area %s"},
457   {"areadata", ".area %s"},
458   {"areahome", ".area %s"},
459   {"ascii", ".db \"%s\""},
460   {"ds", ".ds %d"},
461   {"db", ".db"},
462   {"dbs", ".db \"%s\""},
463   {"dw", ".dw"},
464   {"dws", ".dw %s"},
465   {"constbyte", "0x%02x"},
466   {"constword", "0x%04x"},
467   {"immedword", "0x%04x"},
468   {"immedbyte", "0x%02x"},
469   {"hashedstr", "#%s"},
470   {"lsbimmeds", "#<%s"},
471   {"msbimmeds", "#>%s"},
472   {"module", "; .module %s"},
473   {"global", ".globl %s"},
474   {"fileprelude", ""},
475   {"functionheader",
476    "; ---------------------------------\n"
477    "; Function %s\n"
478    "; ---------------------------------"
479   },
480   {"functionlabeldef", "%s:"},
481   {"bankimmeds", "0     ; PENDING: bank support"},
482   {"los","(%s & 0FFh)"},
483   {"his","((%s / 256) & 0FFh)"},
484   {"hihis","((%s / 65536) & 0FFh)"},
485   {"hihihis","((%s / 16777216) & 0FFh)"},
486   {"lod","(%d & 0FFh)"},
487   {"hid","((%d / 256) & 0FFh)"},
488   {"hihid","((%d / 65536) & 0FFh)"},
489   {"hihihid","((%d / 16777216) & 0FFh)"},
490   {"lol","(L%05d & 0FFh)"},
491   {"hil","((L%05d / 256) & 0FFh)"},
492   {"hihil","((L%05d / 65536) & 0FFh)"},
493   {"hihihil","((L%09d / 16777216) & 0FFh)"},
494   {"equ"," equ"},
495   {NULL, NULL}
496 };
497
498 const ASM_MAPPINGS asm_asxxxx_mapping =
499 {
500   NULL,
501   _asxxxx_mapping
502 };
503
504 const ASM_MAPPINGS asm_gas_mapping =
505 {
506   NULL,
507   _gas_mapping
508 };
509
510 const ASM_MAPPINGS asm_a390_mapping =
511 {
512   NULL,
513   _a390_mapping
514 };
515
516 const ASM_MAPPINGS asm_xa_asm_mapping =
517 {
518   NULL,
519   _xa_asm_mapping
520 };