listing: change the line numbers to match the source code
[nasm.git] / listing.c
blob4fcf91f8424e8b7f079c5bd236545405dddd4fa3
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;
76 static const char *listfn;
78 static int32_t listp;
80 static int suppress; /* for INCBIN & TIMES special cases */
82 static int listlevel, listlevel_e;
84 static FILE *listfp;
86 static void list_emit(void)
88 int i;
90 if (!listlinep && !listdata[0])
91 return;
93 fprintf(listfp, "%6"PRId32" ", listlineno);
95 if (listdata[0])
96 fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
97 listdata);
98 else
99 fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
101 if (listlevel_e)
102 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
103 listlevel_e);
104 else if (listlinep)
105 fprintf(listfp, " ");
107 if (listlinep)
108 fprintf(listfp, " %s", listline);
110 putc('\n', listfp);
111 listlinep = false;
112 listdata[0] = '\0';
114 if (listerror[0]) {
115 fprintf(listfp, "%6"PRId32" ", listlineno);
116 for (i = 0; i < LIST_HEXBIT; i++)
117 putc('*', listfp);
119 if (listlevel_e)
120 fprintf(listfp, " %s<%d>", (listlevel < 10 ? " " : ""),
121 listlevel_e);
122 else
123 fprintf(listfp, " ");
125 fprintf(listfp, " %s\n", listerror);
126 listerror[0] = '\0';
130 static void list_init(char *fname, efunc error)
132 listfp = fopen(fname, "w");
133 if (!listfp) {
134 error(ERR_NONFATAL, "unable to open listing file `%s'",
135 fname);
136 return;
139 *listline = '\0';
140 listlineno = 0;
141 *listerror = '\0';
142 listp = true;
143 listlevel = 0;
144 suppress = 0;
145 mistack = nasm_malloc(sizeof(MacroInhibit));
146 mistack->next = NULL;
147 mistack->level = 0;
148 mistack->inhibiting = true;
151 static void list_cleanup(void)
153 if (!listp)
154 return;
156 while (mistack) {
157 MacroInhibit *temp = mistack;
158 mistack = temp->next;
159 nasm_free(temp);
162 list_emit();
163 fclose(listfp);
166 static void list_out(int32_t offset, char *str)
168 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
169 strcat(listdata, "-");
170 list_emit();
172 if (!listdata[0])
173 listoffset = offset;
174 strcat(listdata, str);
177 static void list_address(int32_t offset, const char *brackets,
178 int64_t addr, int size)
180 char q[20];
181 char *r = q;
183 nasm_assert(size <= 8);
185 *r++ = brackets[0];
186 while (size--) {
187 HEX(r, addr);
188 addr >>= 8;
189 r += 2;
191 *r++ = brackets[1];
192 *r = '\0';
193 list_out(offset, q);
196 static void list_output(int32_t offset, const void *data,
197 enum out_type type, uint64_t size)
199 char q[20];
201 if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
202 return;
204 switch (type) {
205 case OUT_RAWDATA:
207 uint8_t const *p = data;
209 if (size == 0 && !listdata[0])
210 listoffset = offset;
211 while (size--) {
212 HEX(q, *p);
213 q[2] = '\0';
214 list_out(offset++, q);
215 p++;
217 break;
219 case OUT_ADDRESS:
220 list_address(offset, "[]", *(int64_t *)data, abs((int)size));
221 break;
222 case OUT_REL1ADR:
223 list_address(offset, "()", *(int64_t *)data, 1);
224 break;
225 case OUT_REL2ADR:
226 list_address(offset, "()", *(int64_t *)data, 2);
227 break;
228 case OUT_REL4ADR:
229 list_address(offset, "()", *(int64_t *)data, 4);
230 break;
231 case OUT_REL8ADR:
232 list_address(offset, "()", *(int64_t *)data, 8);
233 break;
234 case OUT_RESERVE:
236 snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
237 list_out(offset, q);
238 break;
243 static void list_line(int type, char *line)
245 if (!listp)
246 return;
248 if (user_nolist)
249 return;
251 if (mistack && mistack->inhibiting) {
252 if (type == LIST_MACRO)
253 return;
254 else { /* pop the m i stack */
255 MacroInhibit *temp = mistack;
256 mistack = temp->next;
257 nasm_free(temp);
260 list_emit();
261 listlineno = src_get_linnum();
262 listlinep = true;
263 strncpy(listline, line, LIST_MAX_LEN - 1);
264 listline[LIST_MAX_LEN - 1] = '\0';
265 listlevel_e = listlevel;
268 static void list_uplevel(int type)
270 if (!listp)
271 return;
272 if (type == LIST_INCBIN || type == LIST_TIMES) {
273 suppress |= (type == LIST_INCBIN ? 1 : 2);
274 list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
275 return;
278 listlevel++;
280 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
281 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
282 temp->next = mistack;
283 temp->level = listlevel;
284 temp->inhibiting = false;
285 mistack = temp;
286 } else if (type == LIST_MACRO_NOLIST) {
287 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
288 temp->next = mistack;
289 temp->level = listlevel;
290 temp->inhibiting = true;
291 mistack = temp;
295 static void list_downlevel(int type)
297 if (!listp)
298 return;
300 if (type == LIST_INCBIN || type == LIST_TIMES) {
301 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
302 return;
305 listlevel--;
306 while (mistack && mistack->level > listlevel) {
307 MacroInhibit *temp = mistack;
308 mistack = temp->next;
309 nasm_free(temp);
313 static void list_error(int severity, const char *pfx, const char *msg)
315 if (!listfp)
316 return;
318 snprintf(listerror, sizeof listerror, "%s%s", pfx, msg);
320 if ((severity & ERR_MASK) >= ERR_FATAL)
321 list_emit();
325 ListGen nasmlist = {
326 list_init,
327 list_cleanup,
328 list_output,
329 list_line,
330 list_uplevel,
331 list_downlevel,
332 list_error