codeview: use nasm_realpath() to find the canonical name of the outfile
[nasm.git] / listing.c
blob828eceeb64058ed592aa614ef2bdc73eb4d92480
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2016 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 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 = fopen(fname, "w");
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(int32_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(int32_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(int32_t offset, const void *data,
201 enum out_type type, uint64_t size)
203 char q[20];
205 if (!listp || suppress || user_nolist)
206 return;
208 switch (type) {
209 case OUT_RAWDATA:
211 uint8_t const *p = data;
213 if (size == 0 && !listdata[0])
214 listoffset = offset;
215 while (size--) {
216 HEX(q, *p);
217 q[2] = '\0';
218 list_out(offset++, q);
219 p++;
221 break;
223 case OUT_ADDRESS:
224 list_address(offset, "[]", *(int64_t *)data, abs((int)size));
225 break;
226 case OUT_REL1ADR:
227 list_address(offset, "()", *(int64_t *)data, 1);
228 break;
229 case OUT_REL2ADR:
230 list_address(offset, "()", *(int64_t *)data, 2);
231 break;
232 case OUT_REL4ADR:
233 list_address(offset, "()", *(int64_t *)data, 4);
234 break;
235 case OUT_REL8ADR:
236 list_address(offset, "()", *(int64_t *)data, 8);
237 break;
238 case OUT_RESERVE:
240 snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
241 list_out(offset, q);
242 break;
247 static void list_line(int type, char *line)
249 if (!listp)
250 return;
252 if (user_nolist)
253 return;
255 if (mistack && mistack->inhibiting) {
256 if (type == LIST_MACRO)
257 return;
258 else { /* pop the m i stack */
259 MacroInhibit *temp = mistack;
260 mistack = temp->next;
261 nasm_free(temp);
264 list_emit();
265 listlineno = src_get_linnum();
266 listlinep = true;
267 strncpy(listline, line, LIST_MAX_LEN - 1);
268 listline[LIST_MAX_LEN - 1] = '\0';
269 listlevel_e = listlevel;
272 static void list_uplevel(int type)
274 if (!listp)
275 return;
276 if (type == LIST_INCBIN || type == LIST_TIMES) {
277 suppress |= (type == LIST_INCBIN ? 1 : 2);
278 list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
279 return;
282 listlevel++;
284 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
285 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
286 temp->next = mistack;
287 temp->level = listlevel;
288 temp->inhibiting = false;
289 mistack = temp;
290 } else if (type == LIST_MACRO_NOLIST) {
291 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
292 temp->next = mistack;
293 temp->level = listlevel;
294 temp->inhibiting = true;
295 mistack = temp;
299 static void list_downlevel(int type)
301 if (!listp)
302 return;
304 if (type == LIST_INCBIN || type == LIST_TIMES) {
305 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
306 return;
309 listlevel--;
310 while (mistack && mistack->level > listlevel) {
311 MacroInhibit *temp = mistack;
312 mistack = temp->next;
313 nasm_free(temp);
317 static void list_error(int severity, const char *pfx, const char *msg)
319 if (!listfp)
320 return;
322 snprintf(listerror, sizeof listerror, "%s%s", pfx, msg);
324 if ((severity & ERR_MASK) >= ERR_FATAL)
325 list_emit();
329 static const struct lfmt nasm_list = {
330 list_init,
331 list_cleanup,
332 list_output,
333 list_line,
334 list_uplevel,
335 list_downlevel,
336 list_error
339 const struct lfmt *lfmt = &nasm_list;