Add copyright headers to macro files
[nasm.git] / listing.c
blob95efd194303d9f78393c170f93dd8466e2a89fd9
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, Inc.,
10 * 51 Franklin St, Fifth Floor, Boston MA 02110-1301, USA; version 2.1,
11 * or, at your option, any later version, incorporated herein by
12 * reference.
14 * Patches submitted to this file are required to be dual licensed
15 * under the LGPL 2.1+ and the 2-clause BSD license:
17 * Copyright 1996-2009 the NASM Authors - All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following
21 * conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above
26 * copyright notice, this list of conditions and the following
27 * disclaimer in the documentation and/or other materials provided
28 * with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
41 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 * ----------------------------------------------------------------------- */
47 * listing.c listing file generator for the Netwide Assembler
50 #include "compiler.h"
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <stddef.h>
55 #include <string.h>
56 #include <ctype.h>
57 #include <inttypes.h>
59 #include "nasm.h"
60 #include "nasmlib.h"
61 #include "listing.h"
63 #define LIST_MAX_LEN 216 /* something sensible */
64 #define LIST_INDENT 40
65 #define LIST_HEXBIT 18
67 typedef struct MacroInhibit MacroInhibit;
69 static struct MacroInhibit {
70 MacroInhibit *next;
71 int level;
72 int inhibiting;
73 } *mistack;
75 static char xdigit[] = "0123456789ABCDEF";
77 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
79 static char listline[LIST_MAX_LEN];
80 static int listlinep;
82 static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
83 static int32_t listoffset;
85 static int32_t listlineno;
87 static int32_t listp;
89 static int suppress; /* for INCBIN & TIMES special cases */
91 static int listlevel, listlevel_e;
93 static FILE *listfp;
95 static void list_emit(void)
97 if (!listlinep && !listdata[0])
98 return;
100 fprintf(listfp, "%6"PRId32" ", ++listlineno);
102 if (listdata[0])
103 fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
104 listdata);
105 else
106 fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
108 if (listlevel_e)
109 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
110 listlevel_e);
111 else if (listlinep)
112 fprintf(listfp, " ");
114 if (listlinep)
115 fprintf(listfp, " %s", listline);
117 putc('\n', listfp);
118 listlinep = false;
119 listdata[0] = '\0';
122 static void list_init(char *fname, efunc error)
124 listfp = fopen(fname, "w");
125 if (!listfp) {
126 error(ERR_NONFATAL, "unable to open listing file `%s'", fname);
127 return;
130 *listline = '\0';
131 listlineno = 0;
132 listp = true;
133 listlevel = 0;
134 suppress = 0;
135 mistack = nasm_malloc(sizeof(MacroInhibit));
136 mistack->next = NULL;
137 mistack->level = 0;
138 mistack->inhibiting = true;
141 static void list_cleanup(void)
143 if (!listp)
144 return;
146 while (mistack) {
147 MacroInhibit *temp = mistack;
148 mistack = temp->next;
149 nasm_free(temp);
152 list_emit();
153 fclose(listfp);
156 static void list_out(int32_t offset, char *str)
158 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
159 strcat(listdata, "-");
160 list_emit();
162 if (!listdata[0])
163 listoffset = offset;
164 strcat(listdata, str);
167 static void list_output(int32_t offset, const void *data,
168 enum out_type type, uint64_t size)
170 if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
171 return;
173 switch (type) {
174 case OUT_RAWDATA:
176 uint8_t const *p = data;
177 char q[3];
178 if (size == 0 && !listdata[0])
179 listoffset = offset;
180 while (size--) {
181 HEX(q, *p);
182 q[2] = '\0';
183 list_out(offset++, q);
184 p++;
186 break;
188 case OUT_ADDRESS:
190 uint64_t d = *(int64_t *)data;
191 char q[20];
192 uint8_t p[8], *r = p;
193 if (size == 4) {
194 q[0] = '[';
195 q[9] = ']';
196 q[10] = '\0';
197 WRITELONG(r, d);
198 HEX(q + 1, p[0]);
199 HEX(q + 3, p[1]);
200 HEX(q + 5, p[2]);
201 HEX(q + 7, p[3]);
202 list_out(offset, q);
203 } else if (size == 8) {
204 q[0] = '[';
205 q[17] = ']';
206 q[18] = '\0';
207 WRITEDLONG(r, d);
208 HEX(q + 1, p[0]);
209 HEX(q + 3, p[1]);
210 HEX(q + 5, p[2]);
211 HEX(q + 7, p[3]);
212 HEX(q + 9, p[4]);
213 HEX(q + 11, p[5]);
214 HEX(q + 13, p[6]);
215 HEX(q + 15, p[7]);
216 list_out(offset, q);
217 } else {
218 q[0] = '[';
219 q[5] = ']';
220 q[6] = '\0';
221 WRITESHORT(r, d);
222 HEX(q + 1, p[0]);
223 HEX(q + 3, p[1]);
224 list_out(offset, q);
226 break;
228 case OUT_REL2ADR:
230 uint32_t d = *(int32_t *)data;
231 char q[11];
232 uint8_t p[4], *r = p;
233 q[0] = '(';
234 q[5] = ')';
235 q[6] = '\0';
236 WRITESHORT(r, d);
237 HEX(q + 1, p[0]);
238 HEX(q + 3, p[1]);
239 list_out(offset, q);
240 break;
242 case OUT_REL4ADR:
244 uint32_t d = *(int32_t *)data;
245 char q[11];
246 uint8_t p[4], *r = p;
247 q[0] = '(';
248 q[9] = ')';
249 q[10] = '\0';
250 WRITELONG(r, d);
251 HEX(q + 1, p[0]);
252 HEX(q + 3, p[1]);
253 HEX(q + 5, p[2]);
254 HEX(q + 7, p[3]);
255 list_out(offset, q);
256 break;
258 case OUT_REL8ADR:
260 uint64_t d = *(int64_t *)data;
261 char q[19];
262 uint8_t p[8], *r = p;
263 q[0] = '(';
264 q[17] = ')';
265 q[18] = '\0';
266 WRITEDLONG(r, d);
267 HEX(q + 1, p[0]);
268 HEX(q + 3, p[1]);
269 HEX(q + 5, p[2]);
270 HEX(q + 7, p[3]);
271 HEX(q + 9, p[4]);
272 HEX(q + 11, p[5]);
273 HEX(q + 13, p[6]);
274 HEX(q + 15, p[7]);
275 list_out(offset, q);
276 break;
278 case OUT_RESERVE:
280 char q[20];
281 snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
282 list_out(offset, q);
283 break;
288 static void list_line(int type, char *line)
290 if (!listp)
291 return;
292 if (user_nolist) { /* fbk - 9/2/00 */
293 listlineno++;
294 return;
297 if (mistack && mistack->inhibiting) {
298 if (type == LIST_MACRO)
299 return;
300 else { /* pop the m i stack */
301 MacroInhibit *temp = mistack;
302 mistack = temp->next;
303 nasm_free(temp);
306 list_emit();
307 listlinep = true;
308 strncpy(listline, line, LIST_MAX_LEN - 1);
309 listline[LIST_MAX_LEN - 1] = '\0';
310 listlevel_e = listlevel;
313 static void list_uplevel(int type)
315 if (!listp)
316 return;
317 if (type == LIST_INCBIN || type == LIST_TIMES) {
318 suppress |= (type == LIST_INCBIN ? 1 : 2);
319 list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
320 return;
323 listlevel++;
325 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
326 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
327 temp->next = mistack;
328 temp->level = listlevel;
329 temp->inhibiting = false;
330 mistack = temp;
331 } else if (type == LIST_MACRO_NOLIST) {
332 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
333 temp->next = mistack;
334 temp->level = listlevel;
335 temp->inhibiting = true;
336 mistack = temp;
340 static void list_downlevel(int type)
342 if (!listp)
343 return;
345 if (type == LIST_INCBIN || type == LIST_TIMES) {
346 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
347 return;
350 listlevel--;
351 while (mistack && mistack->level > listlevel) {
352 MacroInhibit *temp = mistack;
353 mistack = temp->next;
354 nasm_free(temp);
358 ListGen nasmlist = {
359 list_init,
360 list_cleanup,
361 list_output,
362 list_line,
363 list_uplevel,
364 list_downlevel