finally commit Mike Frysinger's "elf-visibility" patch
[nasm/autotest.git] / listing.c
blob1d432e5571370578c4170dfce944ddc4a4cc2eb7
1 /* listing.c listing file generator for the Netwide Assembler
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.
8 * initial version 2/vii/97 by Simon Tatham
9 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stddef.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <inttypes.h>
18 #include "nasm.h"
19 #include "nasmlib.h"
20 #include "listing.h"
22 #define LIST_MAX_LEN 216 /* something sensible */
23 #define LIST_INDENT 40
24 #define LIST_HEXBIT 18
26 typedef struct MacroInhibit MacroInhibit;
28 static struct MacroInhibit {
29 MacroInhibit *next;
30 int level;
31 int inhibiting;
32 } *mistack;
34 static char xdigit[] = "0123456789ABCDEF";
36 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
38 static char listline[LIST_MAX_LEN];
39 static int listlinep;
41 static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
42 static int32_t listoffset;
44 static int32_t listlineno;
46 static int32_t listp;
48 static int suppress; /* for INCBIN & TIMES special cases */
50 static int listlevel, listlevel_e;
52 static FILE *listfp;
54 static void list_emit(void)
56 if (!listlinep && !listdata[0])
57 return;
59 fprintf(listfp, "%6"PRId32" ", ++listlineno);
61 if (listdata[0])
62 fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
63 listdata);
64 else
65 fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
67 if (listlevel_e)
68 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
69 listlevel_e);
70 else if (listlinep)
71 fprintf(listfp, " ");
73 if (listlinep)
74 fprintf(listfp, " %s", listline);
76 fputc('\n', listfp);
77 listlinep = FALSE;
78 listdata[0] = '\0';
81 static void list_init(char *fname, efunc error)
83 listfp = fopen(fname, "w");
84 if (!listfp) {
85 error(ERR_NONFATAL, "unable to open listing file `%s'", fname);
86 return;
89 *listline = '\0';
90 listlineno = 0;
91 listp = TRUE;
92 listlevel = 0;
93 suppress = 0;
94 mistack = nasm_malloc(sizeof(MacroInhibit));
95 mistack->next = NULL;
96 mistack->level = 0;
97 mistack->inhibiting = TRUE;
100 static void list_cleanup(void)
102 if (!listp)
103 return;
105 while (mistack) {
106 MacroInhibit *temp = mistack;
107 mistack = temp->next;
108 nasm_free(temp);
111 list_emit();
112 fclose(listfp);
115 static void list_out(int32_t offset, char *str)
117 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
118 strcat(listdata, "-");
119 list_emit();
121 if (!listdata[0])
122 listoffset = offset;
123 strcat(listdata, str);
126 static void list_output(int32_t offset, const void *data, uint32_t type)
128 uint32_t typ, size;
130 if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
131 return;
133 typ = type & OUT_TYPMASK;
134 size = type & OUT_SIZMASK;
137 if (typ == OUT_RAWDATA) {
138 uint8_t const *p = data;
139 char q[3];
140 while (size--) {
141 HEX(q, *p);
142 q[2] = '\0';
143 list_out(offset++, q);
144 p++;
146 } else if (typ == OUT_ADDRESS) {
147 uint64_t d = *(int64_t *)data;
148 char q[20];
149 uint8_t p[8], *r = p;
150 if (size == 4) {
151 q[0] = '[';
152 q[9] = ']';
153 q[10] = '\0';
154 WRITELONG(r, d);
155 HEX(q + 1, p[0]);
156 HEX(q + 3, p[1]);
157 HEX(q + 5, p[2]);
158 HEX(q + 7, p[3]);
159 list_out(offset, q);
160 } else if (size == 8) {
161 q[0] = '[';
162 q[17] = ']';
163 q[18] = '\0';
164 WRITEDLONG(r, d);
165 HEX(q + 1, p[0]);
166 HEX(q + 3, p[1]);
167 HEX(q + 5, p[2]);
168 HEX(q + 7, p[3]);
169 HEX(q + 9, p[4]);
170 HEX(q + 11, p[5]);
171 HEX(q + 13, p[6]);
172 HEX(q + 15, p[7]);
173 list_out(offset, q);
174 } else {
175 q[0] = '[';
176 q[5] = ']';
177 q[6] = '\0';
178 WRITESHORT(r, d);
179 HEX(q + 1, p[0]);
180 HEX(q + 3, p[1]);
181 list_out(offset, q);
183 } else if (typ == OUT_REL2ADR) {
184 uint32_t d = *(int32_t *)data;
185 char q[11];
186 uint8_t p[4], *r = p;
187 q[0] = '(';
188 q[5] = ')';
189 q[6] = '\0';
190 WRITESHORT(r, d);
191 HEX(q + 1, p[0]);
192 HEX(q + 3, p[1]);
193 list_out(offset, q);
194 } else if (typ == OUT_REL4ADR) {
195 uint32_t d = *(int32_t *)data;
196 char q[11];
197 uint8_t p[4], *r = p;
198 q[0] = '(';
199 q[9] = ')';
200 q[10] = '\0';
201 WRITELONG(r, d);
202 HEX(q + 1, p[0]);
203 HEX(q + 3, p[1]);
204 HEX(q + 5, p[2]);
205 HEX(q + 7, p[3]);
206 list_out(offset, q);
207 } else if (typ == OUT_RESERVE) {
208 char q[20];
209 snprintf(q, sizeof(q), "<res %08"PRIX32">", size);
210 list_out(offset, q);
214 static void list_line(int type, char *line)
216 if (!listp)
217 return;
218 if (user_nolist) { /* fbk - 9/2/00 */
219 listlineno++;
220 return;
223 if (mistack && mistack->inhibiting) {
224 if (type == LIST_MACRO)
225 return;
226 else { /* pop the m i stack */
227 MacroInhibit *temp = mistack;
228 mistack = temp->next;
229 nasm_free(temp);
232 list_emit();
233 listlinep = TRUE;
234 strncpy(listline, line, LIST_MAX_LEN - 1);
235 listline[LIST_MAX_LEN - 1] = '\0';
236 listlevel_e = listlevel;
239 static void list_uplevel(int type)
241 if (!listp)
242 return;
243 if (type == LIST_INCBIN || type == LIST_TIMES) {
244 suppress |= (type == LIST_INCBIN ? 1 : 2);
245 list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
246 return;
249 listlevel++;
251 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
252 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
253 temp->next = mistack;
254 temp->level = listlevel;
255 temp->inhibiting = FALSE;
256 mistack = temp;
257 } else if (type == LIST_MACRO_NOLIST) {
258 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
259 temp->next = mistack;
260 temp->level = listlevel;
261 temp->inhibiting = TRUE;
262 mistack = temp;
266 static void list_downlevel(int type)
268 if (!listp)
269 return;
271 if (type == LIST_INCBIN || type == LIST_TIMES) {
272 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
273 return;
276 listlevel--;
277 while (mistack && mistack->level > listlevel) {
278 MacroInhibit *temp = mistack;
279 mistack = temp->next;
280 nasm_free(temp);
284 ListGen nasmlist = {
285 list_init,
286 list_cleanup,
287 list_output,
288 list_line,
289 list_uplevel,
290 list_downlevel