preproc_init: Just clean include path
[nasm.git] / asm / listing.c
blob6c459e132af693bdb2ca215b1e431ed8cd43a507
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2018 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>
46 #include "nasm.h"
47 #include "nasmlib.h"
48 #include "error.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 bool listlinep;
70 static char listerror[LIST_MAX_LEN];
72 static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
73 static int32_t listoffset;
75 static int32_t listlineno;
77 static int32_t listp;
79 static int suppress; /* for INCBIN & TIMES special cases */
81 static int listlevel, listlevel_e;
83 static FILE *listfp;
85 static void list_emit(void)
87 int i;
89 if (!listlinep && !listdata[0])
90 return;
92 fprintf(listfp, "%6"PRId32" ", listlineno);
94 if (listdata[0])
95 fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
96 listdata);
97 else
98 fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
100 if (listlevel_e)
101 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
102 listlevel_e);
103 else if (listlinep)
104 fprintf(listfp, " ");
106 if (listlinep)
107 fprintf(listfp, " %s", listline);
109 putc('\n', listfp);
110 listlinep = false;
111 listdata[0] = '\0';
113 if (listerror[0]) {
114 fprintf(listfp, "%6"PRId32" ", listlineno);
115 for (i = 0; i < LIST_HEXBIT; i++)
116 putc('*', listfp);
118 if (listlevel_e)
119 fprintf(listfp, " %s<%d>", (listlevel < 10 ? " " : ""),
120 listlevel_e);
121 else
122 fprintf(listfp, " ");
124 fprintf(listfp, " %s\n", listerror);
125 listerror[0] = '\0';
129 static void list_init(const char *fname)
131 if (!fname || fname[0] == '\0') {
132 listfp = NULL;
133 return;
136 listfp = nasm_open_write(fname, NF_TEXT);
137 if (!listfp) {
138 nasm_error(ERR_NONFATAL, "unable to open listing file `%s'",
139 fname);
140 return;
143 *listline = '\0';
144 listlineno = 0;
145 *listerror = '\0';
146 listp = true;
147 listlevel = 0;
148 suppress = 0;
149 mistack = nasm_malloc(sizeof(MacroInhibit));
150 mistack->next = NULL;
151 mistack->level = 0;
152 mistack->inhibiting = true;
155 static void list_cleanup(void)
157 if (!listp)
158 return;
160 while (mistack) {
161 MacroInhibit *temp = mistack;
162 mistack = temp->next;
163 nasm_free(temp);
166 list_emit();
167 fclose(listfp);
170 static void list_out(int64_t offset, char *str)
172 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
173 strcat(listdata, "-");
174 list_emit();
176 if (!listdata[0])
177 listoffset = offset;
178 strcat(listdata, str);
181 static void list_address(int64_t offset, const char *brackets,
182 int64_t addr, int size)
184 char q[20];
185 char *r = q;
187 nasm_assert(size <= 8);
189 *r++ = brackets[0];
190 while (size--) {
191 HEX(r, addr);
192 addr >>= 8;
193 r += 2;
195 *r++ = brackets[1];
196 *r = '\0';
197 list_out(offset, q);
200 static void list_output(const struct out_data *data)
202 char q[24];
203 uint64_t size = data->size;
204 uint64_t offset = data->offset;
205 const uint8_t *p = data->data;
208 if (!listp || suppress || user_nolist)
209 return;
211 switch (data->type) {
212 case OUT_ZERODATA:
213 if (size > 16) {
214 snprintf(q, sizeof(q), "<zero %08"PRIX64">", size);
215 list_out(offset, q);
216 break;
217 } else {
218 p = zero_buffer;
220 /* fall through */
221 case OUT_RAWDATA:
223 if (size == 0 && !listdata[0])
224 listoffset = data->offset;
225 while (size--) {
226 HEX(q, *p);
227 q[2] = '\0';
228 list_out(offset++, q);
229 p++;
231 break;
233 case OUT_ADDRESS:
234 list_address(offset, "[]", data->toffset, size);
235 break;
236 case OUT_SEGMENT:
237 q[0] = '[';
238 memset(q+1, 's', size << 1);
239 q[(size << 1)+1] = ']';
240 q[(size << 1)+2] = '\0';
241 list_out(offset, q);
242 offset += size;
243 break;
244 case OUT_RELADDR:
245 list_address(offset, "()", data->toffset, size);
246 break;
247 case OUT_RESERVE:
249 snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
250 list_out(offset, q);
251 break;
253 default:
254 panic();
258 static void list_line(int type, char *line)
260 if (!listp)
261 return;
263 if (user_nolist)
264 return;
266 if (mistack && mistack->inhibiting) {
267 if (type == LIST_MACRO)
268 return;
269 else { /* pop the m i stack */
270 MacroInhibit *temp = mistack;
271 mistack = temp->next;
272 nasm_free(temp);
275 list_emit();
276 listlineno = src_get_linnum();
277 listlinep = true;
278 strncpy(listline, line, LIST_MAX_LEN - 1);
279 listline[LIST_MAX_LEN - 1] = '\0';
280 listlevel_e = listlevel;
283 static void list_uplevel(int type)
285 if (!listp)
286 return;
287 if (type == LIST_INCBIN || type == LIST_TIMES) {
288 suppress |= (type == LIST_INCBIN ? 1 : 2);
289 list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
290 return;
293 listlevel++;
295 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
296 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
297 temp->next = mistack;
298 temp->level = listlevel;
299 temp->inhibiting = false;
300 mistack = temp;
301 } else if (type == LIST_MACRO_NOLIST) {
302 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
303 temp->next = mistack;
304 temp->level = listlevel;
305 temp->inhibiting = true;
306 mistack = temp;
310 static void list_downlevel(int type)
312 if (!listp)
313 return;
315 if (type == LIST_INCBIN || type == LIST_TIMES) {
316 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
317 return;
320 listlevel--;
321 while (mistack && mistack->level > listlevel) {
322 MacroInhibit *temp = mistack;
323 mistack = temp->next;
324 nasm_free(temp);
328 static void list_error(int severity, const char *pfx, const char *msg)
330 if (!listfp)
331 return;
333 snprintf(listerror, sizeof listerror, "%s%s", pfx, msg);
335 if ((severity & ERR_MASK) >= ERR_FATAL)
336 list_emit();
339 static void list_set_offset(uint64_t offset)
341 listoffset = offset;
344 static const struct lfmt nasm_list = {
345 list_init,
346 list_cleanup,
347 list_output,
348 list_line,
349 list_uplevel,
350 list_downlevel,
351 list_error,
352 list_set_offset
355 const struct lfmt *lfmt = &nasm_list;