diff options
Diffstat (limited to 'listing.c')
-rw-r--r-- | listing.c | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/listing.c b/listing.c new file mode 100644 index 0000000..5a09440 --- /dev/null +++ b/listing.c @@ -0,0 +1,387 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 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 <inttypes.h> + +#include "nasm.h" +#include "nasmlib.h" +#include "listing.h" + +#define LIST_MAX_LEN 216 /* 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; + +static char listerror[LIST_MAX_LEN]; + +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; + + if (!listlinep && !listdata[0]) + return; + + 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'; + + if (listerror[0]) { + 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", listerror); + listerror[0] = '\0'; + } +} + +static void list_init(char *fname, efunc error) +{ + listfp = fopen(fname, "w"); + if (!listfp) { + error(ERR_NONFATAL, "unable to open listing file `%s'", + fname); + return; + } + + *listline = '\0'; + listlineno = 0; + *listerror = '\0'; + 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(int32_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_output(int32_t offset, const void *data, + enum out_type type, uint64_t size) +{ + if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */ + return; + + switch (type) { + case OUT_RAWDATA: + { + uint8_t const *p = data; + char q[3]; + if (size == 0 && !listdata[0]) + listoffset = offset; + while (size--) { + HEX(q, *p); + q[2] = '\0'; + list_out(offset++, q); + p++; + } + break; + } + case OUT_ADDRESS: + { + uint64_t d = *(int64_t *)data; + char q[20]; + uint8_t p[8], *r = p; + if (size == 4) { + q[0] = '['; + q[9] = ']'; + q[10] = '\0'; + WRITELONG(r, d); + HEX(q + 1, p[0]); + HEX(q + 3, p[1]); + HEX(q + 5, p[2]); + HEX(q + 7, p[3]); + list_out(offset, q); + } else if (size == 8) { + q[0] = '['; + q[17] = ']'; + q[18] = '\0'; + WRITEDLONG(r, d); + HEX(q + 1, p[0]); + HEX(q + 3, p[1]); + HEX(q + 5, p[2]); + HEX(q + 7, p[3]); + HEX(q + 9, p[4]); + HEX(q + 11, p[5]); + HEX(q + 13, p[6]); + HEX(q + 15, p[7]); + list_out(offset, q); + } else { + q[0] = '['; + q[5] = ']'; + q[6] = '\0'; + WRITESHORT(r, d); + HEX(q + 1, p[0]); + HEX(q + 3, p[1]); + list_out(offset, q); + } + break; + } + case OUT_REL2ADR: + { + uint32_t d = *(int32_t *)data; + char q[11]; + uint8_t p[4], *r = p; + q[0] = '('; + q[5] = ')'; + q[6] = '\0'; + WRITESHORT(r, d); + HEX(q + 1, p[0]); + HEX(q + 3, p[1]); + list_out(offset, q); + break; + } + case OUT_REL4ADR: + { + uint32_t d = *(int32_t *)data; + char q[11]; + uint8_t p[4], *r = p; + q[0] = '('; + q[9] = ')'; + q[10] = '\0'; + WRITELONG(r, d); + HEX(q + 1, p[0]); + HEX(q + 3, p[1]); + HEX(q + 5, p[2]); + HEX(q + 7, p[3]); + list_out(offset, q); + break; + } + case OUT_REL8ADR: + { + uint64_t d = *(int64_t *)data; + char q[19]; + uint8_t p[8], *r = p; + q[0] = '('; + q[17] = ')'; + q[18] = '\0'; + WRITEDLONG(r, d); + HEX(q + 1, p[0]); + HEX(q + 3, p[1]); + HEX(q + 5, p[2]); + HEX(q + 7, p[3]); + HEX(q + 9, p[4]); + HEX(q + 11, p[5]); + HEX(q + 13, p[6]); + HEX(q + 15, p[7]); + list_out(offset, q); + break; + } + case OUT_RESERVE: + { + char q[20]; + snprintf(q, sizeof(q), "<res %08"PRIX64">", size); + list_out(offset, q); + break; + } + } +} + +static void list_line(int type, char *line) +{ + if (!listp) + return; + if (user_nolist) { /* fbk - 9/2/00 */ + listlineno++; + 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(); + 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 *pfx, const char *msg) +{ + if (!listfp) + return; + + snprintf(listerror, sizeof listerror, "%s%s", pfx, msg); + + if ((severity & ERR_MASK) >= ERR_FATAL) + list_emit(); +} + + +ListGen nasmlist = { + list_init, + list_cleanup, + list_output, + list_line, + list_uplevel, + list_downlevel, + list_error +}; |