Merge branch 'master' of git+ssh://repo.or.cz/srv/git/nasm
[nasm.git] / listing.c
blob97362d03ed66c3763710ebe9a26604fea78415e1
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * listing.c listing file generator for the Netwide Assembler
38 #include "compiler.h"
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stddef.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <inttypes.h>
47 #include "nasm.h"
48 #include "nasmlib.h"
49 #include "listing.h"
51 #define LIST_MAX_LEN 216 /* something sensible */
52 #define LIST_INDENT 40
53 #define LIST_HEXBIT 18
55 typedef struct MacroInhibit MacroInhibit;
57 static struct MacroInhibit {
58 MacroInhibit *next;
59 int level;
60 int inhibiting;
61 } *mistack;
63 static char xdigit[] = "0123456789ABCDEF";
65 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
67 static char listline[LIST_MAX_LEN];
68 static int listlinep;
70 static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
71 static int32_t listoffset;
73 static int32_t listlineno;
75 static int32_t listp;
77 static int suppress; /* for INCBIN & TIMES special cases */
79 static int listlevel, listlevel_e;
81 static FILE *listfp;
83 static void list_emit(void)
85 if (!listlinep && !listdata[0])
86 return;
88 fprintf(listfp, "%6"PRId32" ", ++listlineno);
90 if (listdata[0])
91 fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
92 listdata);
93 else
94 fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
96 if (listlevel_e)
97 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
98 listlevel_e);
99 else if (listlinep)
100 fprintf(listfp, " ");
102 if (listlinep)
103 fprintf(listfp, " %s", listline);
105 putc('\n', listfp);
106 listlinep = false;
107 listdata[0] = '\0';
110 static void list_init(char *fname, efunc error)
112 listfp = fopen(fname, "w");
113 if (!listfp) {
114 error(ERR_NONFATAL, "unable to open listing file `%s'", fname);
115 return;
118 *listline = '\0';
119 listlineno = 0;
120 listp = true;
121 listlevel = 0;
122 suppress = 0;
123 mistack = nasm_malloc(sizeof(MacroInhibit));
124 mistack->next = NULL;
125 mistack->level = 0;
126 mistack->inhibiting = true;
129 static void list_cleanup(void)
131 if (!listp)
132 return;
134 while (mistack) {
135 MacroInhibit *temp = mistack;
136 mistack = temp->next;
137 nasm_free(temp);
140 list_emit();
141 fclose(listfp);
144 static void list_out(int32_t offset, char *str)
146 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
147 strcat(listdata, "-");
148 list_emit();
150 if (!listdata[0])
151 listoffset = offset;
152 strcat(listdata, str);
155 static void list_output(int32_t offset, const void *data,
156 enum out_type type, uint64_t size)
158 if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
159 return;
161 switch (type) {
162 case OUT_RAWDATA:
164 uint8_t const *p = data;
165 char q[3];
166 if (size == 0 && !listdata[0])
167 listoffset = offset;
168 while (size--) {
169 HEX(q, *p);
170 q[2] = '\0';
171 list_out(offset++, q);
172 p++;
174 break;
176 case OUT_ADDRESS:
178 uint64_t d = *(int64_t *)data;
179 char q[20];
180 uint8_t p[8], *r = p;
181 if (size == 4) {
182 q[0] = '[';
183 q[9] = ']';
184 q[10] = '\0';
185 WRITELONG(r, d);
186 HEX(q + 1, p[0]);
187 HEX(q + 3, p[1]);
188 HEX(q + 5, p[2]);
189 HEX(q + 7, p[3]);
190 list_out(offset, q);
191 } else if (size == 8) {
192 q[0] = '[';
193 q[17] = ']';
194 q[18] = '\0';
195 WRITEDLONG(r, d);
196 HEX(q + 1, p[0]);
197 HEX(q + 3, p[1]);
198 HEX(q + 5, p[2]);
199 HEX(q + 7, p[3]);
200 HEX(q + 9, p[4]);
201 HEX(q + 11, p[5]);
202 HEX(q + 13, p[6]);
203 HEX(q + 15, p[7]);
204 list_out(offset, q);
205 } else {
206 q[0] = '[';
207 q[5] = ']';
208 q[6] = '\0';
209 WRITESHORT(r, d);
210 HEX(q + 1, p[0]);
211 HEX(q + 3, p[1]);
212 list_out(offset, q);
214 break;
216 case OUT_REL2ADR:
218 uint32_t d = *(int32_t *)data;
219 char q[11];
220 uint8_t p[4], *r = p;
221 q[0] = '(';
222 q[5] = ')';
223 q[6] = '\0';
224 WRITESHORT(r, d);
225 HEX(q + 1, p[0]);
226 HEX(q + 3, p[1]);
227 list_out(offset, q);
228 break;
230 case OUT_REL4ADR:
232 uint32_t d = *(int32_t *)data;
233 char q[11];
234 uint8_t p[4], *r = p;
235 q[0] = '(';
236 q[9] = ')';
237 q[10] = '\0';
238 WRITELONG(r, d);
239 HEX(q + 1, p[0]);
240 HEX(q + 3, p[1]);
241 HEX(q + 5, p[2]);
242 HEX(q + 7, p[3]);
243 list_out(offset, q);
244 break;
246 case OUT_REL8ADR:
248 uint64_t d = *(int64_t *)data;
249 char q[19];
250 uint8_t p[8], *r = p;
251 q[0] = '(';
252 q[17] = ')';
253 q[18] = '\0';
254 WRITEDLONG(r, d);
255 HEX(q + 1, p[0]);
256 HEX(q + 3, p[1]);
257 HEX(q + 5, p[2]);
258 HEX(q + 7, p[3]);
259 HEX(q + 9, p[4]);
260 HEX(q + 11, p[5]);
261 HEX(q + 13, p[6]);
262 HEX(q + 15, p[7]);
263 list_out(offset, q);
264 break;
266 case OUT_RESERVE:
268 char q[20];
269 snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
270 list_out(offset, q);
271 break;
276 static void list_line(int type, char *line)
278 if (!listp)
279 return;
280 if (user_nolist) { /* fbk - 9/2/00 */
281 listlineno++;
282 return;
285 if (mistack && mistack->inhibiting) {
286 if (type == LIST_MACRO)
287 return;
288 else { /* pop the m i stack */
289 MacroInhibit *temp = mistack;
290 mistack = temp->next;
291 nasm_free(temp);
294 list_emit();
295 listlinep = true;
296 strncpy(listline, line, LIST_MAX_LEN - 1);
297 listline[LIST_MAX_LEN - 1] = '\0';
298 listlevel_e = listlevel;
301 static void list_uplevel(int type)
303 if (!listp)
304 return;
305 if (type == LIST_INCBIN || type == LIST_TIMES) {
306 suppress |= (type == LIST_INCBIN ? 1 : 2);
307 list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
308 return;
311 listlevel++;
313 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
314 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
315 temp->next = mistack;
316 temp->level = listlevel;
317 temp->inhibiting = false;
318 mistack = temp;
319 } else if (type == LIST_MACRO_NOLIST) {
320 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
321 temp->next = mistack;
322 temp->level = listlevel;
323 temp->inhibiting = true;
324 mistack = temp;
328 static void list_downlevel(int type)
330 if (!listp)
331 return;
333 if (type == LIST_INCBIN || type == LIST_TIMES) {
334 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
335 return;
338 listlevel--;
339 while (mistack && mistack->level > listlevel) {
340 MacroInhibit *temp = mistack;
341 mistack = temp->next;
342 nasm_free(temp);
346 ListGen nasmlist = {
347 list_init,
348 list_cleanup,
349 list_output,
350 list_line,
351 list_uplevel,
352 list_downlevel