NASM 0.95
[platform/upstream/nasm.git] / listing.c
1 /* listing.c    listing file generator for the Netwide Assembler
2  *
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.
7  *
8  * initial version 2/vii/97 by Simon Tatham
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stddef.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 #include "nasm.h"
18 #include "nasmlib.h"
19 #include "listing.h"
20
21 #define LIST_MAX_LEN 216               /* something sensible */
22 #define LIST_INDENT  40
23 #define LIST_HEXBIT  18
24
25 typedef struct MacroInhibit MacroInhibit;
26
27 static struct MacroInhibit {
28     MacroInhibit *next;
29     int level;
30     int inhibiting;
31 } *mistack;
32
33 static char xdigit[] = "0123456789ABCDEF";
34
35 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
36
37 static char listline[LIST_MAX_LEN];
38 static int listlinep;
39
40 static char listdata[2*LIST_INDENT];   /* we need less than that actually */
41 static long listoffset;
42
43 static long listlineno;
44
45 static long listp;
46
47 static int suppress;                   /* for INCBIN & TIMES special cases */
48
49 static int listlevel, listlevel_e;
50
51 static FILE *listfp;
52
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';
70 }
71
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;
77     }
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;
87 }
88
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);
96     }
97     list_emit();
98     fclose (listfp);
99 }
100
101 static void list_out (long offset, char *str) {
102     if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
103         strcat(listdata, "-");
104         list_emit();
105     }
106     if (!listdata[0])
107         listoffset = offset;
108     strcat(listdata, str);
109 }
110
111 static void list_output (long offset, void *data, unsigned long type) {
112     long typ, size;
113
114     if (!listp || suppress)
115         return;
116
117     typ = type & OUT_TYPMASK;
118     size = type & OUT_SIZMASK;
119
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++;
128         }
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);
147         }
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);
172     }
173 }
174
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);
185         }
186     }
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;
192 }
193
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;
201     }
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;
215     }
216 }
217
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;
224     }
225     listlevel--;
226     while (mistack && mistack->level > listlevel) {
227         MacroInhibit *temp = mistack;
228         mistack = temp->next;
229         nasm_free (temp);
230     }
231 }
232
233 ListGen nasmlist = {
234     list_init,
235     list_cleanup,
236     list_output,
237     list_line,
238     list_uplevel,
239     list_downlevel
240 };