NASM 0.95
[nasm.git] / listing.c
blob89b722a627069797eb854e0ca40a45af46ba283f
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>
17 #include "nasm.h"
18 #include "nasmlib.h"
19 #include "listing.h"
21 #define LIST_MAX_LEN 216 /* something sensible */
22 #define LIST_INDENT 40
23 #define LIST_HEXBIT 18
25 typedef struct MacroInhibit MacroInhibit;
27 static struct MacroInhibit {
28 MacroInhibit *next;
29 int level;
30 int inhibiting;
31 } *mistack;
33 static char xdigit[] = "0123456789ABCDEF";
35 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
37 static char listline[LIST_MAX_LEN];
38 static int listlinep;
40 static char listdata[2*LIST_INDENT]; /* we need less than that actually */
41 static long listoffset;
43 static long listlineno;
45 static long listp;
47 static int suppress; /* for INCBIN & TIMES special cases */
49 static int listlevel, listlevel_e;
51 static FILE *listfp;
53 static void list_emit (void) {
54 if (!listlinep && !listdata[0])
55 return;
56 fprintf(listfp, "%6ld ", ++listlineno);
57 if (listdata[0])
58 fprintf(listfp, "%08lX %-*s", listoffset, LIST_HEXBIT+1, listdata);
59 else
60 fprintf(listfp, "%*s", LIST_HEXBIT+10, "");
61 if (listlevel_e)
62 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""), listlevel_e);
63 else if (listlinep)
64 fprintf(listfp, " ");
65 if (listlinep)
66 fprintf(listfp, " %s", listline);
67 fputc('\n', listfp);
68 listlinep = FALSE;
69 listdata[0] = '\0';
72 static void list_init (char *fname, efunc error) {
73 listfp = fopen (fname, "w");
74 if (!listfp) {
75 error (ERR_NONFATAL, "unable to open listing file `%s'", fname);
76 return;
78 *listline = '\0';
79 listlineno = 0;
80 listp = TRUE;
81 listlevel = 0;
82 suppress = 0;
83 mistack = nasm_malloc(sizeof(MacroInhibit));
84 mistack->next = NULL;
85 mistack->level = 0;
86 mistack->inhibiting = TRUE;
89 static void list_cleanup (void) {
90 if (!listp)
91 return;
92 while (mistack) {
93 MacroInhibit *temp = mistack;
94 mistack = temp->next;
95 nasm_free (temp);
97 list_emit();
98 fclose (listfp);
101 static void list_out (long offset, char *str) {
102 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
103 strcat(listdata, "-");
104 list_emit();
106 if (!listdata[0])
107 listoffset = offset;
108 strcat(listdata, str);
111 static void list_output (long offset, void *data, unsigned long type) {
112 long typ, size;
114 if (!listp || suppress)
115 return;
117 typ = type & OUT_TYPMASK;
118 size = type & OUT_SIZMASK;
120 if (typ == OUT_RAWDATA) {
121 unsigned char *p = data;
122 char q[3];
123 while (size--) {
124 HEX (q, *p);
125 q[2] = '\0';
126 list_out (offset++, q);
127 p++;
129 } else if (typ == OUT_ADDRESS) {
130 unsigned long d = *(long *)data;
131 char q[11];
132 unsigned char p[4], *r = p;
133 if (size == 4) {
134 q[0] = '['; q[9] = ']'; q[10] = '\0';
135 WRITELONG (r, d);
136 HEX (q+1, p[0]);
137 HEX (q+3, p[1]);
138 HEX (q+5, p[2]);
139 HEX (q+7, p[3]);
140 list_out (offset, q);
141 } else {
142 q[0] = '['; q[5] = ']'; q[6] = '\0';
143 WRITESHORT (r, d);
144 HEX (q+1, p[0]);
145 HEX (q+3, p[1]);
146 list_out (offset, q);
148 } else if (typ == OUT_REL2ADR) {
149 unsigned long d = *(long *)data;
150 char q[11];
151 unsigned char p[4], *r = p;
152 q[0] = '('; q[5] = ')'; q[6] = '\0';
153 WRITESHORT (r, d);
154 HEX (q+1, p[0]);
155 HEX (q+3, p[1]);
156 list_out (offset, q);
157 } else if (typ == OUT_REL4ADR) {
158 unsigned long d = *(long *)data;
159 char q[11];
160 unsigned char p[4], *r = p;
161 q[0] = '('; q[9] = ')'; q[10] = '\0';
162 WRITELONG (r, d);
163 HEX (q+1, p[0]);
164 HEX (q+3, p[1]);
165 HEX (q+5, p[2]);
166 HEX (q+7, p[3]);
167 list_out (offset, q);
168 } else if (typ == OUT_RESERVE) {
169 char q[20];
170 sprintf(q, "<res %08lX>", size);
171 list_out (offset, q);
175 static void list_line (int type, char *line) {
176 if (!listp)
177 return;
178 if (mistack && mistack->inhibiting) {
179 if (type == LIST_MACRO)
180 return;
181 else { /* pop the m i stack */
182 MacroInhibit *temp = mistack;
183 mistack = temp->next;
184 nasm_free (temp);
187 list_emit();
188 listlinep = TRUE;
189 strncpy (listline, line, LIST_MAX_LEN-1);
190 listline[LIST_MAX_LEN-1] = '\0';
191 listlevel_e = listlevel;
194 static void list_uplevel (int type) {
195 if (!listp)
196 return;
197 if (type == LIST_INCBIN || type == LIST_TIMES) {
198 suppress |= (type == LIST_INCBIN ? 1 : 2);
199 list_out (listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
200 return;
202 listlevel++;
203 if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
204 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
205 temp->next = mistack;
206 temp->level = listlevel;
207 temp->inhibiting = FALSE;
208 mistack = temp;
209 } else if (type == LIST_MACRO_NOLIST) {
210 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
211 temp->next = mistack;
212 temp->level = listlevel;
213 temp->inhibiting = TRUE;
214 mistack = temp;
218 static void list_downlevel (int type) {
219 if (!listp)
220 return;
221 if (type == LIST_INCBIN || type == LIST_TIMES) {
222 suppress &= ~(type == LIST_INCBIN ? 1 : 2);
223 return;
225 listlevel--;
226 while (mistack && mistack->level > listlevel) {
227 MacroInhibit *temp = mistack;
228 mistack = temp->next;
229 nasm_free (temp);
233 ListGen nasmlist = {
234 list_init,
235 list_cleanup,
236 list_output,
237 list_line,
238 list_uplevel,
239 list_downlevel