Update documentation
[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 #include <inttypes.h>
17
18 #include "nasm.h"
19 #include "nasmlib.h"
20 #include "listing.h"
21
22 #define LIST_MAX_LEN 216        /* something sensible */
23 #define LIST_INDENT  40
24 #define LIST_HEXBIT  18
25
26 typedef struct MacroInhibit MacroInhibit;
27
28 static struct MacroInhibit {
29     MacroInhibit *next;
30     int level;
31     int inhibiting;
32 } *mistack;
33
34 static char xdigit[] = "0123456789ABCDEF";
35
36 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
37
38 static char listline[LIST_MAX_LEN];
39 static int listlinep;
40
41 static char listdata[2 * LIST_INDENT];  /* we need less than that actually */
42 static int32_t listoffset;
43
44 static int32_t listlineno;
45
46 static int32_t listp;
47
48 static int suppress;            /* for INCBIN & TIMES special cases */
49
50 static int listlevel, listlevel_e;
51
52 static FILE *listfp;
53
54 static void list_emit(void)
55 {
56     if (!listlinep && !listdata[0])
57         return;
58
59     fprintf(listfp, "%6"PRId32" ", ++listlineno);
60
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, "");
66
67     if (listlevel_e)
68         fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
69                 listlevel_e);
70     else if (listlinep)
71         fprintf(listfp, "    ");
72
73     if (listlinep)
74         fprintf(listfp, " %s", listline);
75
76     fputc('\n', listfp);
77     listlinep = FALSE;
78     listdata[0] = '\0';
79 }
80
81 static void list_init(char *fname, efunc error)
82 {
83     listfp = fopen(fname, "w");
84     if (!listfp) {
85         error(ERR_NONFATAL, "unable to open listing file `%s'", fname);
86         return;
87     }
88
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;
98 }
99
100 static void list_cleanup(void)
101 {
102     if (!listp)
103         return;
104
105     while (mistack) {
106         MacroInhibit *temp = mistack;
107         mistack = temp->next;
108         nasm_free(temp);
109     }
110
111     list_emit();
112     fclose(listfp);
113 }
114
115 static void list_out(int32_t offset, char *str)
116 {
117     if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
118         strcat(listdata, "-");
119         list_emit();
120     }
121     if (!listdata[0])
122         listoffset = offset;
123     strcat(listdata, str);
124 }
125
126 static void list_output(int32_t offset, const void *data, uint32_t type)
127 {
128     uint32_t typ, size;
129
130     if (!listp || suppress || user_nolist)      /* fbk - 9/2/00 */
131         return;
132
133     typ = type & OUT_TYPMASK;
134     size = type & OUT_SIZMASK;
135
136
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++;
145         }
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);
182         }
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);
211     }
212 }
213
214 static void list_line(int type, char *line)
215 {
216     if (!listp)
217         return;
218     if (user_nolist) {          /* fbk - 9/2/00 */
219         listlineno++;
220         return;
221     }
222
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);
230         }
231     }
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;
237 }
238
239 static void list_uplevel(int type)
240 {
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;
247     }
248
249     listlevel++;
250
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;
263     }
264 }
265
266 static void list_downlevel(int type)
267 {
268     if (!listp)
269         return;
270
271     if (type == LIST_INCBIN || type == LIST_TIMES) {
272         suppress &= ~(type == LIST_INCBIN ? 1 : 2);
273         return;
274     }
275
276     listlevel--;
277     while (mistack && mistack->level > listlevel) {
278         MacroInhibit *temp = mistack;
279         mistack = temp->next;
280         nasm_free(temp);
281     }
282 }
283
284 ListGen nasmlist = {
285     list_init,
286     list_cleanup,
287     list_output,
288     list_line,
289     list_uplevel,
290     list_downlevel
291 };