preproc: fix the detection of the >= operator
[nasm.git] / asm / listing.c
blob3101a2583aa18cd2562542e06d2e46d5551482de
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2019 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * listing.c listing file generator for the Netwide Assembler
38 #include "compiler.h"
40 #include "nctype.h"
42 #include "nasm.h"
43 #include "nasmlib.h"
44 #include "error.h"
45 #include "strlist.h"
46 #include "listing.h"
48 #define LIST_MAX_LEN 1024 /* something sensible */
49 #define LIST_INDENT 40
50 #define LIST_HEXBIT 18
52 typedef struct MacroInhibit MacroInhibit;
54 static struct MacroInhibit {
55 MacroInhibit *next;
56 int level;
57 int inhibiting;
58 } *mistack;
60 static const char xdigit[] = "0123456789ABCDEF";
62 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
64 uint64_t list_options, active_list_options;
66 static char listline[LIST_MAX_LEN];
67 static bool listlinep;
69 static struct strlist *list_errors;
71 static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
72 static int32_t listoffset;
74 static int32_t listlineno;
76 static int suppress; /* for INCBIN & TIMES special cases */
78 static int listlevel, listlevel_e;
80 static FILE *listfp;
82 static void list_emit(void)
84 int i;
85 const struct strlist_entry *e;
87 if (listlinep || *listdata) {
88 fprintf(listfp, "%6"PRId32" ", listlineno);
90 if (listdata[0])
91 fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
92 listdata);
93 else
94 fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
96 if (listlevel_e)
97 fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
98 listlevel_e);
99 else if (listlinep)
100 fprintf(listfp, " ");
102 if (listlinep)
103 fprintf(listfp, " %s", listline);
105 putc('\n', listfp);
106 listlinep = false;
107 listdata[0] = '\0';
110 if (list_errors) {
111 static const char fillchars[] = " --***XX";
112 char fillchar;
114 strlist_for_each(e, list_errors) {
115 fprintf(listfp, "%6"PRId32" ", listlineno);
116 fillchar = fillchars[e->pvt.u & ERR_MASK];
117 for (i = 0; i < LIST_HEXBIT; i++)
118 putc(fillchar, listfp);
120 if (listlevel_e)
121 fprintf(listfp, " %s<%d>", (listlevel < 10 ? " " : ""),
122 listlevel_e);
123 else
124 fprintf(listfp, " ");
126 fprintf(listfp, " %s\n", e->str);
129 strlist_free(&list_errors);
133 static void list_cleanup(void)
135 if (!listfp)
136 return;
138 while (mistack) {
139 MacroInhibit *temp = mistack;
140 mistack = temp->next;
141 nasm_free(temp);
144 list_emit();
145 fclose(listfp);
146 listfp = NULL;
149 static void list_init(const char *fname)
151 if (listfp)
152 list_cleanup();
154 if (!fname || fname[0] == '\0') {
155 listfp = NULL;
156 return;
159 listfp = nasm_open_write(fname, NF_TEXT);
160 if (!listfp) {
161 nasm_nonfatal("unable to open listing file `%s'", fname);
162 return;
165 *listline = '\0';
166 listlineno = 0;
167 list_errors = NULL;
168 listlevel = 0;
169 suppress = 0;
170 nasm_new(mistack);
171 mistack->next = NULL;
172 mistack->level = 0;
173 mistack->inhibiting = true;
176 static void list_out(int64_t offset, char *str)
178 if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
179 strcat(listdata, "-");
180 list_emit();
182 if (!listdata[0])
183 listoffset = offset;
184 strcat(listdata, str);
187 static void list_address(int64_t offset, const char *brackets,
188 int64_t addr, int size)
190 char q[20];
191 char *r = q;
193 nasm_assert(size <= 8);
195 *r++ = brackets[0];
196 while (size--) {
197 HEX(r, addr);
198 addr >>= 8;
199 r += 2;
201 *r++ = brackets[1];
202 *r = '\0';
203 list_out(offset, q);
206 static void list_size(int64_t offset, const char *tag, uint64_t size)
208 char buf[64];
209 const char *fmt;
211 if (list_option('d'))
212 fmt = "<%s %"PRIu64">";
213 else
214 fmt = "<%s %"PRIX64"h>";
216 snprintf(buf, sizeof buf, fmt, tag, size);
217 list_out(offset, buf);
220 static void list_output(const struct out_data *data)
222 char q[24];
223 uint64_t size = data->size;
224 uint64_t offset = data->offset;
225 const uint8_t *p = data->data;
228 if (!listfp || suppress || user_nolist)
229 return;
231 switch (data->type) {
232 case OUT_ZERODATA:
233 if (size > 16) {
234 list_size(offset, "zero", size);
235 break;
236 } else {
237 p = zero_buffer;
239 /* fall through */
240 case OUT_RAWDATA:
242 if (size == 0) {
243 if (!listdata[0])
244 listoffset = data->offset;
245 } else if (p) {
246 while (size--) {
247 HEX(q, *p);
248 q[2] = '\0';
249 list_out(offset++, q);
250 p++;
252 } else {
253 /* Used for listing on non-code generation passes with -Lp */
254 list_size(offset, "len", size);
256 break;
258 case OUT_ADDRESS:
259 list_address(offset, "[]", data->toffset, size);
260 break;
261 case OUT_SEGMENT:
262 q[0] = '[';
263 memset(q+1, 's', size << 1);
264 q[(size << 1)+1] = ']';
265 q[(size << 1)+2] = '\0';
266 list_out(offset, q);
267 offset += size;
268 break;
269 case OUT_RELADDR:
270 list_address(offset, "()", data->toffset, size);
271 break;
272 case OUT_RESERVE:
274 if (size)
275 list_size(offset, "res", size);
276 break;
278 default:
279 panic();
283 static void list_line(int type, int32_t lineno, const char *line)
285 if (!listfp)
286 return;
288 if (user_nolist)
289 return;
291 if (mistack && mistack->inhibiting) {
292 if (type == LIST_MACRO)
293 return;
294 else { /* pop the m i stack */
295 MacroInhibit *temp = mistack;
296 mistack = temp->next;
297 nasm_free(temp);
300 list_emit();
301 if (lineno >= 0)
302 listlineno = lineno;
303 listlinep = true;
304 strlcpy(listline, line, LIST_MAX_LEN-3);
305 memcpy(listline + LIST_MAX_LEN-4, "...", 4);
306 listlevel_e = listlevel;
309 static void mistack_push(bool inhibiting)
311 MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
312 temp->next = mistack;
313 temp->level = listlevel;
314 temp->inhibiting = inhibiting;
315 mistack = temp;
318 static void list_uplevel(int type, int64_t size)
320 if (!listfp)
321 return;
323 switch (type) {
324 case LIST_INCBIN:
325 suppress |= 1;
326 list_size(listoffset, "bin", size);
327 break;
329 case LIST_TIMES:
330 suppress |= 2;
331 list_size(listoffset, "rep", size);
332 break;
334 case LIST_INCLUDE:
335 listlevel++;
336 if (mistack && mistack->inhibiting)
337 mistack_push(false);
338 break;
340 case LIST_MACRO_NOLIST:
341 listlevel++;
342 mistack_push(true);
343 break;
345 default:
346 listlevel++;
347 break;
351 static void list_downlevel(int type)
353 if (!listfp)
354 return;
356 switch (type) {
357 case LIST_INCBIN:
358 suppress &= ~1;
359 break;
361 case LIST_TIMES:
362 suppress &= ~2;
363 break;
365 default:
366 listlevel--;
367 while (mistack && mistack->level > listlevel) {
368 MacroInhibit *temp = mistack;
369 mistack = temp->next;
370 nasm_free(temp);
372 break;
376 static void list_error(errflags severity, const char *fmt, ...)
378 va_list ap;
380 if (!listfp)
381 return;
383 if (!list_errors)
384 list_errors = strlist_alloc(false);
386 va_start(ap, fmt);
387 strlist_vprintf(list_errors, fmt, ap);
388 va_end(ap);
389 strlist_tail(list_errors)->pvt.u = severity;
391 if ((severity & ERR_MASK) >= ERR_FATAL)
392 list_emit();
395 static void list_set_offset(uint64_t offset)
397 listoffset = offset;
400 static void list_update_options(const char *str)
402 bool state = true;
403 unsigned char c;
404 uint64_t mask;
406 while ((c = *str++)) {
407 switch (c) {
408 case '+':
409 state = true;
410 break;
411 case '-':
412 state = false;
413 break;
414 default:
415 mask = list_option_mask(c);
416 if (state)
417 list_options |= mask;
418 else
419 list_options &= ~mask;
420 break;
425 enum directive_result list_pragma(const struct pragma *pragma)
427 switch (pragma->opcode) {
428 case D_OPTIONS:
429 list_update_options(pragma->tail);
430 return DIRR_OK;
432 default:
433 return DIRR_UNKNOWN;
437 static const struct lfmt nasm_list = {
438 list_init,
439 list_cleanup,
440 list_output,
441 list_line,
442 list_uplevel,
443 list_downlevel,
444 list_error,
445 list_set_offset
448 const struct lfmt *lfmt = &nasm_list;