| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- /* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
- * See the file AUTHORS included with the NASM distribution for
- * the specific copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following
- * conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ----------------------------------------------------------------------- */
- /*
- * listing.c listing file generator for the Netwide Assembler
- */
- #include "compiler.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <string.h>
- #include <ctype.h>
- #include "nasm.h"
- #include "nasmlib.h"
- #include "error.h"
- #include "listing.h"
- #define LIST_MAX_LEN 256 /* something sensible */
- #define LIST_INDENT 40
- #define LIST_HEXBIT 18
- typedef struct MacroInhibit MacroInhibit;
- static struct MacroInhibit {
- MacroInhibit *next;
- int level;
- int inhibiting;
- } *mistack;
- static char xdigit[] = "0123456789ABCDEF";
- #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
- static char listline[LIST_MAX_LEN];
- static bool listlinep;
- struct list_error {
- struct list_error *next;
- char str[1];
- };
- struct list_error *listerr_head, **listerr_tail;
- static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
- static int32_t listoffset;
- static int32_t listlineno;
- static int32_t listp;
- static int suppress; /* for INCBIN & TIMES special cases */
- static int listlevel, listlevel_e;
- static FILE *listfp;
- static void list_emit(void)
- {
- int i;
- struct list_error *le, *tmp;
- if (listlinep || *listdata) {
- fprintf(listfp, "%6"PRId32" ", listlineno);
- if (listdata[0])
- fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
- listdata);
- else
- fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
- if (listlevel_e)
- fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
- listlevel_e);
- else if (listlinep)
- fprintf(listfp, " ");
- if (listlinep)
- fprintf(listfp, " %s", listline);
- putc('\n', listfp);
- listlinep = false;
- listdata[0] = '\0';
- }
- list_for_each_safe(le, tmp, listerr_head) {
- fprintf(listfp, "%6"PRId32" ", listlineno);
- for (i = 0; i < LIST_HEXBIT; i++)
- putc('*', listfp);
- if (listlevel_e)
- fprintf(listfp, " %s<%d>", (listlevel < 10 ? " " : ""),
- listlevel_e);
- else
- fprintf(listfp, " ");
- fprintf(listfp, " %s\n", le->str);
- nasm_free(le);
- }
- listerr_head = NULL;
- listerr_tail = &listerr_head;
- }
- static void list_init(const char *fname)
- {
- if (!fname || fname[0] == '\0') {
- listfp = NULL;
- return;
- }
- listfp = nasm_open_write(fname, NF_TEXT);
- if (!listfp) {
- nasm_error(ERR_NONFATAL, "unable to open listing file `%s'",
- fname);
- return;
- }
- *listline = '\0';
- listlineno = 0;
- listerr_head = NULL;
- listerr_tail = &listerr_head;
- listp = true;
- listlevel = 0;
- suppress = 0;
- mistack = nasm_malloc(sizeof(MacroInhibit));
- mistack->next = NULL;
- mistack->level = 0;
- mistack->inhibiting = true;
- }
- static void list_cleanup(void)
- {
- if (!listp)
- return;
- while (mistack) {
- MacroInhibit *temp = mistack;
- mistack = temp->next;
- nasm_free(temp);
- }
- list_emit();
- fclose(listfp);
- }
- static void list_out(int64_t offset, char *str)
- {
- if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
- strcat(listdata, "-");
- list_emit();
- }
- if (!listdata[0])
- listoffset = offset;
- strcat(listdata, str);
- }
- static void list_address(int64_t offset, const char *brackets,
- int64_t addr, int size)
- {
- char q[20];
- char *r = q;
- nasm_assert(size <= 8);
- *r++ = brackets[0];
- while (size--) {
- HEX(r, addr);
- addr >>= 8;
- r += 2;
- }
- *r++ = brackets[1];
- *r = '\0';
- list_out(offset, q);
- }
- static void list_output(const struct out_data *data)
- {
- char q[24];
- uint64_t size = data->size;
- uint64_t offset = data->offset;
- const uint8_t *p = data->data;
- if (!listp || suppress || user_nolist)
- return;
- switch (data->type) {
- case OUT_ZERODATA:
- if (size > 16) {
- snprintf(q, sizeof(q), "<zero %08"PRIX64">", size);
- list_out(offset, q);
- break;
- } else {
- p = zero_buffer;
- }
- /* fall through */
- case OUT_RAWDATA:
- {
- if (size == 0 && !listdata[0])
- listoffset = data->offset;
- while (size--) {
- HEX(q, *p);
- q[2] = '\0';
- list_out(offset++, q);
- p++;
- }
- break;
- }
- case OUT_ADDRESS:
- list_address(offset, "[]", data->toffset, size);
- break;
- case OUT_SEGMENT:
- q[0] = '[';
- memset(q+1, 's', size << 1);
- q[(size << 1)+1] = ']';
- q[(size << 1)+2] = '\0';
- list_out(offset, q);
- offset += size;
- break;
- case OUT_RELADDR:
- list_address(offset, "()", data->toffset, size);
- break;
- case OUT_RESERVE:
- {
- snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
- list_out(offset, q);
- break;
- }
- default:
- panic();
- }
- }
- static void list_line(int type, char *line)
- {
- if (!listp)
- return;
- if (user_nolist)
- return;
- if (mistack && mistack->inhibiting) {
- if (type == LIST_MACRO)
- return;
- else { /* pop the m i stack */
- MacroInhibit *temp = mistack;
- mistack = temp->next;
- nasm_free(temp);
- }
- }
- list_emit();
- listlineno = src_get_linnum();
- listlinep = true;
- strncpy(listline, line, LIST_MAX_LEN - 1);
- listline[LIST_MAX_LEN - 1] = '\0';
- listlevel_e = listlevel;
- }
- static void list_uplevel(int type)
- {
- if (!listp)
- return;
- if (type == LIST_INCBIN || type == LIST_TIMES) {
- suppress |= (type == LIST_INCBIN ? 1 : 2);
- list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
- return;
- }
- listlevel++;
- if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
- MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
- temp->next = mistack;
- temp->level = listlevel;
- temp->inhibiting = false;
- mistack = temp;
- } else if (type == LIST_MACRO_NOLIST) {
- MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
- temp->next = mistack;
- temp->level = listlevel;
- temp->inhibiting = true;
- mistack = temp;
- }
- }
- static void list_downlevel(int type)
- {
- if (!listp)
- return;
- if (type == LIST_INCBIN || type == LIST_TIMES) {
- suppress &= ~(type == LIST_INCBIN ? 1 : 2);
- return;
- }
- listlevel--;
- while (mistack && mistack->level > listlevel) {
- MacroInhibit *temp = mistack;
- mistack = temp->next;
- nasm_free(temp);
- }
- }
- static void list_error(int severity, const char *fmt, ...)
- {
- struct list_error *le;
- va_list ap;
- int len;
- if (!listfp)
- return;
- va_start(ap, fmt);
- len = vsnprintf(NULL, 0, fmt, ap);
- va_end(ap);
- /* sizeof(*le) already accounts for the final NULL */
- le = nasm_malloc(sizeof(*le) + len);
- va_start(ap, fmt);
- vsnprintf(le->str, len+1, fmt, ap);
- va_end(ap);
- le->next = NULL;
- *listerr_tail = le;
- listerr_tail = &le->next;
- if ((severity & ERR_MASK) >= ERR_FATAL)
- list_emit();
- }
- static void list_set_offset(uint64_t offset)
- {
- listoffset = offset;
- }
- static const struct lfmt nasm_list = {
- list_init,
- list_cleanup,
- list_output,
- list_line,
- list_uplevel,
- list_downlevel,
- list_error,
- list_set_offset
- };
- const struct lfmt *lfmt = &nasm_list;
|