Formatting: kill off "stealth whitespace"
[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 licence given in the file "Licence"
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     fputc('\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, uint32_t type)
129 {
130     uint32_t typ, size;
131
132     if (!listp || suppress || user_nolist)      /* fbk - 9/2/00 */
133         return;
134
135     typ = type & OUT_TYPMASK;
136     size = type & OUT_SIZMASK;
137
138
139     if (typ == OUT_RAWDATA) {
140         uint8_t const *p = data;
141         char q[3];
142         while (size--) {
143             HEX(q, *p);
144             q[2] = '\0';
145             list_out(offset++, q);
146             p++;
147         }
148     } else if (typ == OUT_ADDRESS) {
149         uint64_t d = *(int64_t *)data;
150         char q[20];
151         uint8_t p[8], *r = p;
152         if (size == 4) {
153             q[0] = '[';
154             q[9] = ']';
155             q[10] = '\0';
156             WRITELONG(r, d);
157             HEX(q + 1, p[0]);
158             HEX(q + 3, p[1]);
159             HEX(q + 5, p[2]);
160             HEX(q + 7, p[3]);
161             list_out(offset, q);
162         } else if (size == 8) {
163             q[0] = '[';
164             q[17] = ']';
165             q[18] = '\0';
166             WRITEDLONG(r, d);
167             HEX(q + 1,  p[0]);
168             HEX(q + 3,  p[1]);
169             HEX(q + 5,  p[2]);
170             HEX(q + 7,  p[3]);
171             HEX(q + 9,  p[4]);
172             HEX(q + 11, p[5]);
173             HEX(q + 13, p[6]);
174             HEX(q + 15, p[7]);
175             list_out(offset, q);
176         } else {
177             q[0] = '[';
178             q[5] = ']';
179             q[6] = '\0';
180             WRITESHORT(r, d);
181             HEX(q + 1, p[0]);
182             HEX(q + 3, p[1]);
183             list_out(offset, q);
184         }
185     } else if (typ == OUT_REL2ADR) {
186         uint32_t d = *(int32_t *)data;
187         char q[11];
188         uint8_t p[4], *r = p;
189         q[0] = '(';
190         q[5] = ')';
191         q[6] = '\0';
192         WRITESHORT(r, d);
193         HEX(q + 1, p[0]);
194         HEX(q + 3, p[1]);
195         list_out(offset, q);
196     } else if (typ == OUT_REL4ADR) {
197         uint32_t d = *(int32_t *)data;
198         char q[11];
199         uint8_t p[4], *r = p;
200         q[0] = '(';
201         q[9] = ')';
202         q[10] = '\0';
203         WRITELONG(r, d);
204         HEX(q + 1, p[0]);
205         HEX(q + 3, p[1]);
206         HEX(q + 5, p[2]);
207         HEX(q + 7, p[3]);
208         list_out(offset, q);
209     } else if (typ == OUT_RESERVE) {
210         char q[20];
211         snprintf(q, sizeof(q), "<res %08"PRIX32">", size);
212         list_out(offset, q);
213     }
214 }
215
216 static void list_line(int type, char *line)
217 {
218     if (!listp)
219         return;
220     if (user_nolist) {          /* fbk - 9/2/00 */
221         listlineno++;
222         return;
223     }
224
225     if (mistack && mistack->inhibiting) {
226         if (type == LIST_MACRO)
227             return;
228         else {                  /* pop the m i stack */
229             MacroInhibit *temp = mistack;
230             mistack = temp->next;
231             nasm_free(temp);
232         }
233     }
234     list_emit();
235     listlinep = true;
236     strncpy(listline, line, LIST_MAX_LEN - 1);
237     listline[LIST_MAX_LEN - 1] = '\0';
238     listlevel_e = listlevel;
239 }
240
241 static void list_uplevel(int type)
242 {
243     if (!listp)
244         return;
245     if (type == LIST_INCBIN || type == LIST_TIMES) {
246         suppress |= (type == LIST_INCBIN ? 1 : 2);
247         list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
248         return;
249     }
250
251     listlevel++;
252
253     if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
254         MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
255         temp->next = mistack;
256         temp->level = listlevel;
257         temp->inhibiting = false;
258         mistack = temp;
259     } else if (type == LIST_MACRO_NOLIST) {
260         MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
261         temp->next = mistack;
262         temp->level = listlevel;
263         temp->inhibiting = true;
264         mistack = temp;
265     }
266 }
267
268 static void list_downlevel(int type)
269 {
270     if (!listp)
271         return;
272
273     if (type == LIST_INCBIN || type == LIST_TIMES) {
274         suppress &= ~(type == LIST_INCBIN ? 1 : 2);
275         return;
276     }
277
278     listlevel--;
279     while (mistack && mistack->level > listlevel) {
280         MacroInhibit *temp = mistack;
281         mistack = temp->next;
282         nasm_free(temp);
283     }
284 }
285
286 ListGen nasmlist = {
287     list_init,
288     list_cleanup,
289     list_output,
290     list_line,
291     list_uplevel,
292     list_downlevel
293 };