]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
4f6e3300 A |
6 | * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.1 (the "License"). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
14c7c974 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
4f6e3300 | 15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
14c7c974 A |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
4f6e3300 A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
14c7c974 A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* listing.c listing file generator for the Netwide Assembler | |
25 | * | |
26 | * The Netwide Assembler is copyright (C) 1996 Simon Tatham and | |
27 | * Julian Hall. All rights reserved. The software is | |
28 | * redistributable under the licence given in the file "Licence" | |
29 | * distributed in the NASM archive. | |
30 | * | |
31 | * initial version 2/vii/97 by Simon Tatham | |
32 | */ | |
33 | ||
34 | #include <stdio.h> | |
35 | #include <stdlib.h> | |
36 | #include <stddef.h> | |
37 | #include <string.h> | |
38 | #include <ctype.h> | |
39 | ||
40 | #include "nasm.h" | |
41 | #include "nasmlib.h" | |
42 | #include "listing.h" | |
43 | ||
44 | #define LIST_MAX_LEN 216 /* something sensible */ | |
45 | #define LIST_INDENT 40 | |
46 | #define LIST_HEXBIT 18 | |
47 | ||
48 | typedef struct MacroInhibit MacroInhibit; | |
49 | ||
50 | static struct MacroInhibit { | |
51 | MacroInhibit *next; | |
52 | int level; | |
53 | int inhibiting; | |
54 | } *mistack; | |
55 | ||
56 | static char xdigit[] = "0123456789ABCDEF"; | |
57 | ||
58 | #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]); | |
59 | ||
60 | static char listline[LIST_MAX_LEN]; | |
61 | static int listlinep; | |
62 | ||
63 | static char listdata[2*LIST_INDENT]; /* we need less than that actually */ | |
64 | static long listoffset; | |
65 | ||
66 | static long listlineno; | |
67 | ||
68 | static long listp; | |
69 | ||
70 | static int suppress; /* for INCBIN & TIMES special cases */ | |
71 | ||
72 | static int listlevel, listlevel_e; | |
73 | ||
74 | static FILE *listfp; | |
75 | ||
76 | static void list_emit (void) { | |
77 | if (!listlinep && !listdata[0]) | |
78 | return; | |
79 | fprintf(listfp, "%6ld ", ++listlineno); | |
80 | if (listdata[0]) | |
81 | fprintf(listfp, "%08lX %-*s", listoffset, LIST_HEXBIT+1, listdata); | |
82 | else | |
83 | fprintf(listfp, "%*s", LIST_HEXBIT+10, ""); | |
84 | if (listlevel_e) | |
85 | fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""), listlevel_e); | |
86 | else if (listlinep) | |
87 | fprintf(listfp, " "); | |
88 | if (listlinep) | |
89 | fprintf(listfp, " %s", listline); | |
90 | fputc('\n', listfp); | |
91 | listlinep = FALSE; | |
92 | listdata[0] = '\0'; | |
93 | } | |
94 | ||
95 | static void list_init (char *fname, efunc error) { | |
96 | listfp = fopen (fname, "w"); | |
97 | if (!listfp) { | |
98 | error (ERR_NONFATAL, "unable to open listing file `%s'", fname); | |
99 | return; | |
100 | } | |
101 | *listline = '\0'; | |
102 | listlineno = 0; | |
103 | listp = TRUE; | |
104 | listlevel = 0; | |
105 | suppress = 0; | |
106 | mistack = nasm_malloc(sizeof(MacroInhibit)); | |
107 | mistack->next = NULL; | |
108 | mistack->level = 0; | |
109 | mistack->inhibiting = TRUE; | |
110 | } | |
111 | ||
112 | static void list_cleanup (void) { | |
113 | if (!listp) | |
114 | return; | |
115 | while (mistack) { | |
116 | MacroInhibit *temp = mistack; | |
117 | mistack = temp->next; | |
118 | nasm_free (temp); | |
119 | } | |
120 | list_emit(); | |
121 | fclose (listfp); | |
122 | } | |
123 | ||
124 | static void list_out (long offset, char *str) { | |
125 | if (strlen(listdata) + strlen(str) > LIST_HEXBIT) { | |
126 | strcat(listdata, "-"); | |
127 | list_emit(); | |
128 | } | |
129 | if (!listdata[0]) | |
130 | listoffset = offset; | |
131 | strcat(listdata, str); | |
132 | } | |
133 | ||
134 | static void list_output (long offset, void *data, unsigned long type) { | |
135 | long typ, size; | |
136 | ||
137 | if (!listp || suppress) | |
138 | return; | |
139 | ||
140 | typ = type & OUT_TYPMASK; | |
141 | size = type & OUT_SIZMASK; | |
142 | ||
143 | if (typ == OUT_RAWDATA) { | |
144 | unsigned char *p = data; | |
145 | char q[3]; | |
146 | while (size--) { | |
147 | HEX (q, *p); | |
148 | q[2] = '\0'; | |
149 | list_out (offset++, q); | |
150 | p++; | |
151 | } | |
152 | } else if (typ == OUT_ADDRESS) { | |
153 | unsigned long d = *(long *)data; | |
154 | char q[11]; | |
155 | unsigned char p[4], *r = p; | |
156 | if (size == 4) { | |
157 | q[0] = '['; q[9] = ']'; q[10] = '\0'; | |
158 | WRITELONG (r, d); | |
159 | HEX (q+1, p[0]); | |
160 | HEX (q+3, p[1]); | |
161 | HEX (q+5, p[2]); | |
162 | HEX (q+7, p[3]); | |
163 | list_out (offset, q); | |
164 | } else { | |
165 | q[0] = '['; q[5] = ']'; q[6] = '\0'; | |
166 | WRITESHORT (r, d); | |
167 | HEX (q+1, p[0]); | |
168 | HEX (q+3, p[1]); | |
169 | list_out (offset, q); | |
170 | } | |
171 | } else if (typ == OUT_REL2ADR) { | |
172 | unsigned long d = *(long *)data; | |
173 | char q[11]; | |
174 | unsigned char p[4], *r = p; | |
175 | q[0] = '('; q[5] = ')'; q[6] = '\0'; | |
176 | WRITESHORT (r, d); | |
177 | HEX (q+1, p[0]); | |
178 | HEX (q+3, p[1]); | |
179 | list_out (offset, q); | |
180 | } else if (typ == OUT_REL4ADR) { | |
181 | unsigned long d = *(long *)data; | |
182 | char q[11]; | |
183 | unsigned char p[4], *r = p; | |
184 | q[0] = '('; q[9] = ')'; q[10] = '\0'; | |
185 | WRITELONG (r, d); | |
186 | HEX (q+1, p[0]); | |
187 | HEX (q+3, p[1]); | |
188 | HEX (q+5, p[2]); | |
189 | HEX (q+7, p[3]); | |
190 | list_out (offset, q); | |
191 | } else if (typ == OUT_RESERVE) { | |
192 | char q[20]; | |
193 | sprintf(q, "<res %08lX>", size); | |
194 | list_out (offset, q); | |
195 | } | |
196 | } | |
197 | ||
198 | static void list_line (int type, char *line) { | |
199 | if (!listp) | |
200 | return; | |
201 | if (mistack && mistack->inhibiting) { | |
202 | if (type == LIST_MACRO) | |
203 | return; | |
204 | else { /* pop the m i stack */ | |
205 | MacroInhibit *temp = mistack; | |
206 | mistack = temp->next; | |
207 | nasm_free (temp); | |
208 | } | |
209 | } | |
210 | list_emit(); | |
211 | listlinep = TRUE; | |
212 | strncpy (listline, line, LIST_MAX_LEN-1); | |
213 | listline[LIST_MAX_LEN-1] = '\0'; | |
214 | listlevel_e = listlevel; | |
215 | } | |
216 | ||
217 | static void list_uplevel (int type) { | |
218 | if (!listp) | |
219 | return; | |
220 | if (type == LIST_INCBIN || type == LIST_TIMES) { | |
221 | suppress |= (type == LIST_INCBIN ? 1 : 2); | |
222 | list_out (listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>"); | |
223 | return; | |
224 | } | |
225 | listlevel++; | |
226 | if (mistack && mistack->inhibiting && type == LIST_INCLUDE) { | |
227 | MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit)); | |
228 | temp->next = mistack; | |
229 | temp->level = listlevel; | |
230 | temp->inhibiting = FALSE; | |
231 | mistack = temp; | |
232 | } else if (type == LIST_MACRO_NOLIST) { | |
233 | MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit)); | |
234 | temp->next = mistack; | |
235 | temp->level = listlevel; | |
236 | temp->inhibiting = TRUE; | |
237 | mistack = temp; | |
238 | } | |
239 | } | |
240 | ||
241 | static void list_downlevel (int type) { | |
242 | if (!listp) | |
243 | return; | |
244 | if (type == LIST_INCBIN || type == LIST_TIMES) { | |
245 | suppress &= ~(type == LIST_INCBIN ? 1 : 2); | |
246 | return; | |
247 | } | |
248 | listlevel--; | |
249 | while (mistack && mistack->level > listlevel) { | |
250 | MacroInhibit *temp = mistack; | |
251 | mistack = temp->next; | |
252 | nasm_free (temp); | |
253 | } | |
254 | } | |
255 | ||
256 | ListGen nasmlist = { | |
257 | list_init, | |
258 | list_cleanup, | |
259 | list_output, | |
260 | list_line, | |
261 | list_uplevel, | |
262 | list_downlevel | |
263 | }; |