Report dwarf as V2 for ELF32
[platform/upstream/nasm.git] / listing.c
1 /* listing.c    listing file generator for the Netwide Assembler
2  *
3  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4  * Julian Hall. All rights reserved. The software is
5  * redistributable under the license given in the file "LICENSE"
6  * distributed in the NASM archive.
7  *
8  * initial version 2/vii/97 by Simon Tatham
9  */
10
11 #include "compiler.h"
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stddef.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <inttypes.h>
19
20 #include "nasm.h"
21 #include "nasmlib.h"
22 #include "listing.h"
23
24 #define LIST_MAX_LEN 216        /* something sensible */
25 #define LIST_INDENT  40
26 #define LIST_HEXBIT  18
27
28 typedef struct MacroInhibit MacroInhibit;
29
30 static struct MacroInhibit {
31     MacroInhibit *next;
32     int level;
33     int inhibiting;
34 } *mistack;
35
36 static char xdigit[] = "0123456789ABCDEF";
37
38 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
39
40 static char listline[LIST_MAX_LEN];
41 static int listlinep;
42
43 static char listdata[2 * LIST_INDENT];  /* we need less than that actually */
44 static int32_t listoffset;
45
46 static int32_t listlineno;
47
48 static int32_t listp;
49
50 static int suppress;            /* for INCBIN & TIMES special cases */
51
52 static int listlevel, listlevel_e;
53
54 static FILE *listfp;
55
56 static void list_emit(void)
57 {
58     if (!listlinep && !listdata[0])
59         return;
60
61     fprintf(listfp, "%6"PRId32" ", ++listlineno);
62
63     if (listdata[0])
64         fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
65                 listdata);
66     else
67         fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
68
69     if (listlevel_e)
70         fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
71                 listlevel_e);
72     else if (listlinep)
73         fprintf(listfp, "    ");
74
75     if (listlinep)
76         fprintf(listfp, " %s", listline);
77
78     putc('\n', listfp);
79     listlinep = false;
80     listdata[0] = '\0';
81 }
82
83 static void list_init(char *fname, efunc error)
84 {
85     listfp = fopen(fname, "w");
86     if (!listfp) {
87         error(ERR_NONFATAL, "unable to open listing file `%s'", fname);
88         return;
89     }
90
91     *listline = '\0';
92     listlineno = 0;
93     listp = true;
94     listlevel = 0;
95     suppress = 0;
96     mistack = nasm_malloc(sizeof(MacroInhibit));
97     mistack->next = NULL;
98     mistack->level = 0;
99     mistack->inhibiting = true;
100 }
101
102 static void list_cleanup(void)
103 {
104     if (!listp)
105         return;
106
107     while (mistack) {
108         MacroInhibit *temp = mistack;
109         mistack = temp->next;
110         nasm_free(temp);
111     }
112
113     list_emit();
114     fclose(listfp);
115 }
116
117 static void list_out(int32_t offset, char *str)
118 {
119     if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
120         strcat(listdata, "-");
121         list_emit();
122     }
123     if (!listdata[0])
124         listoffset = offset;
125     strcat(listdata, str);
126 }
127
128 static void list_output(int32_t offset, const void *data,
129                         enum out_type type, uint64_t size)
130 {
131     if (!listp || suppress || user_nolist)      /* fbk - 9/2/00 */
132         return;
133
134     switch (type) {
135     case OUT_RAWDATA:
136     {
137         uint8_t const *p = data;
138         char q[3];
139         if (size == 0 && !listdata[0])
140             listoffset = offset;
141         while (size--) {
142             HEX(q, *p);
143             q[2] = '\0';
144             list_out(offset++, q);
145             p++;
146         }
147         break;
148     }
149     case OUT_ADDRESS:
150     {
151         uint64_t d = *(int64_t *)data;
152         char q[20];
153         uint8_t p[8], *r = p;
154         if (size == 4) {
155             q[0] = '[';
156             q[9] = ']';
157             q[10] = '\0';
158             WRITELONG(r, d);
159             HEX(q + 1, p[0]);
160             HEX(q + 3, p[1]);
161             HEX(q + 5, p[2]);
162             HEX(q + 7, p[3]);
163             list_out(offset, q);
164         } else if (size == 8) {
165             q[0] = '[';
166             q[17] = ']';
167             q[18] = '\0';
168             WRITEDLONG(r, d);
169             HEX(q + 1,  p[0]);
170             HEX(q + 3,  p[1]);
171             HEX(q + 5,  p[2]);
172             HEX(q + 7,  p[3]);
173             HEX(q + 9,  p[4]);
174             HEX(q + 11, p[5]);
175             HEX(q + 13, p[6]);
176             HEX(q + 15, p[7]);
177             list_out(offset, q);
178         } else {
179             q[0] = '[';
180             q[5] = ']';
181             q[6] = '\0';
182             WRITESHORT(r, d);
183             HEX(q + 1, p[0]);
184             HEX(q + 3, p[1]);
185             list_out(offset, q);
186         }
187         break;
188     }
189     case OUT_REL2ADR:
190     {
191         uint32_t d = *(int32_t *)data;
192         char q[11];
193         uint8_t p[4], *r = p;
194         q[0] = '(';
195         q[5] = ')';
196         q[6] = '\0';
197         WRITESHORT(r, d);
198         HEX(q + 1, p[0]);
199         HEX(q + 3, p[1]);
200         list_out(offset, q);
201         break;
202     }
203     case OUT_REL4ADR:
204     {
205         uint32_t d = *(int32_t *)data;
206         char q[11];
207         uint8_t p[4], *r = p;
208         q[0] = '(';
209         q[9] = ')';
210         q[10] = '\0';
211         WRITELONG(r, d);
212         HEX(q + 1, p[0]);
213         HEX(q + 3, p[1]);
214         HEX(q + 5, p[2]);
215         HEX(q + 7, p[3]);
216         list_out(offset, q);
217         break;
218     }
219     case OUT_REL8ADR:
220     {
221         uint64_t d = *(int64_t *)data;
222         char q[19];
223         uint8_t p[4], *r = p;
224         q[0] = '(';
225         q[17] = ')';
226         q[18] = '\0';
227         WRITEDLONG(r, d);
228         HEX(q + 1, p[0]);
229         HEX(q + 3, p[1]);
230         HEX(q + 5, p[2]);
231         HEX(q + 7, p[3]);
232         HEX(q + 9, p[4]);
233         HEX(q + 11, p[5]);
234         HEX(q + 13, p[6]);
235         HEX(q + 15, p[7]);
236         list_out(offset, q);
237         break;
238     }
239     case OUT_RESERVE:
240     {
241         char q[20];
242         snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
243         list_out(offset, q);
244         break;
245     }
246     }
247 }
248
249 static void list_line(int type, char *line)
250 {
251     if (!listp)
252         return;
253     if (user_nolist) {          /* fbk - 9/2/00 */
254         listlineno++;
255         return;
256     }
257
258     if (mistack && mistack->inhibiting) {
259         if (type == LIST_MACRO)
260             return;
261         else {                  /* pop the m i stack */
262             MacroInhibit *temp = mistack;
263             mistack = temp->next;
264             nasm_free(temp);
265         }
266     }
267     list_emit();
268     listlinep = true;
269     strncpy(listline, line, LIST_MAX_LEN - 1);
270     listline[LIST_MAX_LEN - 1] = '\0';
271     listlevel_e = listlevel;
272 }
273
274 static void list_uplevel(int type)
275 {
276     if (!listp)
277         return;
278     if (type == LIST_INCBIN || type == LIST_TIMES) {
279         suppress |= (type == LIST_INCBIN ? 1 : 2);
280         list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
281         return;
282     }
283
284     listlevel++;
285
286     if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
287         MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
288         temp->next = mistack;
289         temp->level = listlevel;
290         temp->inhibiting = false;
291         mistack = temp;
292     } else if (type == LIST_MACRO_NOLIST) {
293         MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
294         temp->next = mistack;
295         temp->level = listlevel;
296         temp->inhibiting = true;
297         mistack = temp;
298     }
299 }
300
301 static void list_downlevel(int type)
302 {
303     if (!listp)
304         return;
305
306     if (type == LIST_INCBIN || type == LIST_TIMES) {
307         suppress &= ~(type == LIST_INCBIN ? 1 : 2);
308         return;
309     }
310
311     listlevel--;
312     while (mistack && mistack->level > listlevel) {
313         MacroInhibit *temp = mistack;
314         mistack = temp->next;
315         nasm_free(temp);
316     }
317 }
318
319 ListGen nasmlist = {
320     list_init,
321     list_cleanup,
322     list_output,
323     list_line,
324     list_uplevel,
325     list_downlevel
326 };