7455b69b3e6f91b7713eed8c39b0a69e6c6f7275
[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 static const char *_findMapping(const char *szKey)
19 {
20     return shash_find(_h, szKey);
21 }
22
23 static va_list _iprintf(char *pInto, const char *sz, va_list ap)
24 {
25     char format[MAX_TOKEN_LEN];
26     char *pStart = pInto;
27     static int count;
28
29     while (*sz) {
30         if (*sz == '%') {
31             switch (*++sz) {
32                 /* See if it's a special emitter */
33             case 'r':
34                 wassert(0);
35                 break;
36             /* Name of the code segment */
37             case 'C':
38                 strcpy(pInto, CODE_NAME);
39                 pInto = pStart + strlen(pStart);
40                 sz++;
41                 break;
42             case 'F':
43                 strcpy(pInto, srcFileName);
44                 pInto = pStart + strlen(pStart);        
45                 sz++;
46                 break;
47             case 'I':
48                 sprintf(pInto, "%u", ++count);
49                 pInto = pStart + strlen(pStart);
50                 sz++;
51                 break;
52             default:
53                 {
54                     /* Scan out the arg and pass it on to sprintf */
55                     char *p = format;
56                     *p++ = '%';
57                     while (isdigit(*sz))
58                         *p++ = *sz++;
59                     *p++ = *sz++;
60                     *p = '\0';
61                     vsprintf(pInto, format, ap);
62                     /* PENDING: Assume that the arg length was an int */
63                     (void)va_arg(ap, int);
64                 }
65             }
66             pInto = pStart + strlen(pStart);
67         }
68         else {
69             *pInto++ = *sz++;
70         }
71     }
72     *pInto = '\0';
73
74     return ap;
75 }
76
77 void tvsprintf(char *buffer, const char *sz, va_list ap)
78 {
79     char *pInto = buffer;
80     char *p;
81     char token[MAX_TOKEN_LEN];
82
83     buffer[0] = '\0';
84     
85     while (*sz) {
86         if (*sz == '!') {
87             /* Start of a token.  Search until the first
88                [non alplha, *] and call it a token. */
89             const char *t;
90             p = token;
91             sz++;
92             while (isalpha(*sz) || *sz == '*') {
93                 *p++ = *sz++;
94             }
95             *p = '\0';
96             /* Now find the token in the token list */
97             if ((t = _findMapping(token))) {
98                 ap = _iprintf(pInto, t, ap);
99                 pInto = buffer + strlen(buffer);
100             }
101             else {
102                 fprintf(stderr, "Cant find token \"%s\"\n", token);
103                 wassert(0);
104             }
105         }
106         else if (*sz == '%') {
107             p = token;
108             *p++ = *sz++;
109             while (!isalpha(*sz)) {
110                 *p++ = *sz++;
111             }
112             *p++ = *sz++;
113             *p = '\0';
114             vsprintf(pInto, token, ap);
115             pInto = buffer + strlen(buffer);
116             (void)va_arg(ap, int);
117         }
118         else {
119             *pInto++ = *sz++;
120         }
121     }
122     *pInto = '\0';
123 }
124
125 void tfprintf(FILE *fp, const char *szFormat, ...)
126 {
127     va_list ap;
128     char buffer[MAX_INLINEASM];
129
130     va_start(ap, szFormat);
131     tvsprintf(buffer, szFormat, ap);
132     fputs(buffer, fp);
133 }
134
135 void tsprintf(char *buffer, const char *szFormat, ...)
136 {
137     va_list ap;
138     va_start(ap, szFormat);
139     tvsprintf(buffer, szFormat, ap);
140 }
141
142 void asm_addTree(const ASM_MAPPINGS *pMappings)
143 {
144     const ASM_MAPPING *pMap;
145     /* Traverse down first */
146     if (pMappings->pParent)
147         asm_addTree(pMappings->pParent);
148     pMap = pMappings->pMappings;
149     while (pMap->szKey && pMap->szValue) {
150         shash_add(&_h, pMap->szKey, pMap->szValue);
151         pMap++;
152     }
153 }
154
155 static const ASM_MAPPING _asxxxx_mapping[] = {
156     { "labeldef", "%s::" },
157     { "slabeldef", "%s:" },
158     { "tlabeldef", "%05d$:" },
159     { "tlabel", "%05d$" },
160     { "immed", "#" },
161     { "zero", "#0x00" },
162     { "one", "#0x01" },
163     { "area", ".area %s" },
164     { "areacode", ".area %s" },
165     { "areadata", ".area %s" },
166     { "areahome", ".area %s" },
167     { "ascii", ".ascii \"%s\"" },
168     { "ds", ".ds %d" },
169     { "db", ".db" },
170     { "dbs", ".db %s" },
171     { "dw", ".dw" },
172     { "dws", ".dw %s" },
173     { "constbyte", "0x%02X" },
174     { "constword", "0x%04X" },
175     { "immedword", "#0x%04X" },
176     { "immedbyte", "#0x%02X" },
177     { "hashedstr", "#%s" },
178     { "lsbimmeds", "#<%s" },
179     { "msbimmeds", "#>%s" },
180     { "module", ".module %s" },
181     { "global", ".globl %s" },
182     { "fileprelude", "" },
183     { "functionheader", 
184       "; ---------------------------------\n"
185       "; Function %s\n"
186       "; ---------------------------------"
187     },
188     { "functionlabeldef", "%s:" },
189     { "bankimmeds", "0  ; PENDING: bank support" },
190     { NULL, NULL }
191 };
192
193 const ASM_MAPPINGS asm_asxxxx_mapping = {
194     NULL,
195     _asxxxx_mapping
196 };
197