nasm/listing.c

388 lines
9.4 KiB
C
Raw Normal View History

/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2009 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
2002-05-01 04:52:26 +08:00
*
* 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
2002-05-01 04:52:26 +08:00
*/
#include "compiler.h"
2002-05-01 04:52:26 +08:00
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
2002-05-01 04:52:26 +08:00
#include "nasm.h"
#include "nasmlib.h"
#include "listing.h"
2005-01-16 06:15:51 +08:00
#define LIST_MAX_LEN 216 /* something sensible */
2002-05-01 04:52:26 +08:00
#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";
2002-05-01 04:52:26 +08:00
#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];
2002-05-01 04:52:26 +08:00
static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
static int32_t listoffset;
2002-05-01 04:52:26 +08:00
static int32_t listlineno;
2002-05-01 04:52:26 +08:00
static int32_t listp;
2002-05-01 04:52:26 +08:00
2005-01-16 06:15:51 +08:00
static int suppress; /* for INCBIN & TIMES special cases */
2002-05-01 04:52:26 +08:00
static int listlevel, listlevel_e;
static FILE *listfp;
2005-01-16 06:15:51 +08:00
static void list_emit(void)
2002-05-01 04:53:55 +08:00
{
int i;
2002-05-01 04:52:26 +08:00
if (!listlinep && !listdata[0])
2005-01-16 06:15:51 +08:00
return;
2002-05-01 04:53:55 +08:00
2007-04-14 08:10:59 +08:00
fprintf(listfp, "%6"PRId32" ", ++listlineno);
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
if (listdata[0])
2007-04-14 08:10:59 +08:00
fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
2005-01-16 06:15:51 +08:00
listdata);
2002-05-01 04:52:26 +08:00
else
2005-01-16 06:15:51 +08:00
fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
if (listlevel_e)
2005-01-16 06:15:51 +08:00
fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
listlevel_e);
2002-05-01 04:52:26 +08:00
else if (listlinep)
2005-01-16 06:15:51 +08:00
fprintf(listfp, " ");
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
if (listlinep)
2005-01-16 06:15:51 +08:00
fprintf(listfp, " %s", listline);
2002-05-01 04:53:55 +08:00
putc('\n', listfp);
listlinep = false;
2002-05-01 04:52:26 +08:00
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';
}
2002-05-01 04:52:26 +08:00
}
static void list_init(char *fname, efunc error)
2002-05-01 04:53:55 +08:00
{
2005-01-16 06:15:51 +08:00
listfp = fopen(fname, "w");
2002-05-01 04:52:26 +08:00
if (!listfp) {
error(ERR_NONFATAL, "unable to open listing file `%s'",
fname);
2005-01-16 06:15:51 +08:00
return;
2002-05-01 04:52:26 +08:00
}
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
*listline = '\0';
listlineno = 0;
*listerror = '\0';
listp = true;
2002-05-01 04:52:26 +08:00
listlevel = 0;
suppress = 0;
mistack = nasm_malloc(sizeof(MacroInhibit));
mistack->next = NULL;
mistack->level = 0;
mistack->inhibiting = true;
2002-05-01 04:52:26 +08:00
}
2005-01-16 06:15:51 +08:00
static void list_cleanup(void)
2002-05-01 04:53:55 +08:00
{
2002-05-01 04:52:26 +08:00
if (!listp)
2005-01-16 06:15:51 +08:00
return;
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
while (mistack) {
2005-01-16 06:15:51 +08:00
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free(temp);
2002-05-01 04:52:26 +08:00
}
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
list_emit();
2005-01-16 06:15:51 +08:00
fclose(listfp);
2002-05-01 04:52:26 +08:00
}
static void list_out(int32_t offset, char *str)
2002-05-01 04:53:55 +08:00
{
2002-05-01 04:52:26 +08:00
if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
2005-01-16 06:15:51 +08:00
strcat(listdata, "-");
list_emit();
2002-05-01 04:52:26 +08:00
}
if (!listdata[0])
2005-01-16 06:15:51 +08:00
listoffset = offset;
2002-05-01 04:52:26 +08:00
strcat(listdata, str);
}
static void list_output(int32_t offset, const void *data,
enum out_type type, uint64_t size)
2002-05-01 04:53:55 +08:00
{
2005-01-16 06:15:51 +08:00
if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
return;
2002-05-01 04:52:26 +08:00
switch (type) {
case OUT_RAWDATA:
{
uint8_t const *p = data;
char q[3];
if (size == 0 && !listdata[0])
listoffset = offset;
2005-01-16 06:15:51 +08:00
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;
2005-01-16 06:15:51 +08:00
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);
2005-01-16 06:15:51 +08:00
} 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;
2005-01-16 06:15:51 +08:00
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;
2005-01-16 06:15:51 +08:00
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);
2005-01-16 06:15:51 +08:00
list_out(offset, q);
break;
}
2002-05-01 04:52:26 +08:00
}
}
static void list_line(int type, char *line)
2002-05-01 04:53:55 +08:00
{
2002-05-01 04:52:26 +08:00
if (!listp)
2005-01-16 06:15:51 +08:00
return;
if (user_nolist) { /* fbk - 9/2/00 */
2002-05-01 05:00:33 +08:00
listlineno++;
return;
}
2002-05-01 04:53:55 +08:00
2005-01-16 06:15:51 +08:00
if (mistack && mistack->inhibiting) {
if (type == LIST_MACRO)
return;
else { /* pop the m i stack */
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free(temp);
}
2002-05-01 04:52:26 +08:00
}
list_emit();
listlinep = true;
2005-01-16 06:15:51 +08:00
strncpy(listline, line, LIST_MAX_LEN - 1);
listline[LIST_MAX_LEN - 1] = '\0';
2002-05-01 04:52:26 +08:00
listlevel_e = listlevel;
}
2005-01-16 06:15:51 +08:00
static void list_uplevel(int type)
2002-05-01 04:53:55 +08:00
{
2002-05-01 04:52:26 +08:00
if (!listp)
2005-01-16 06:15:51 +08:00
return;
if (type == LIST_INCBIN || type == LIST_TIMES) {
suppress |= (type == LIST_INCBIN ? 1 : 2);
list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
return;
2002-05-01 04:52:26 +08:00
}
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
listlevel++;
2002-05-01 04:53:55 +08:00
2005-01-16 06:15:51 +08:00
if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
temp->next = mistack;
temp->level = listlevel;
temp->inhibiting = false;
2005-01-16 06:15:51 +08:00
mistack = temp;
} else if (type == LIST_MACRO_NOLIST) {
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
temp->next = mistack;
temp->level = listlevel;
temp->inhibiting = true;
2005-01-16 06:15:51 +08:00
mistack = temp;
2002-05-01 04:52:26 +08:00
}
}
2005-01-16 06:15:51 +08:00
static void list_downlevel(int type)
2002-05-01 04:53:55 +08:00
{
2002-05-01 04:52:26 +08:00
if (!listp)
2005-01-16 06:15:51 +08:00
return;
2002-05-01 04:53:55 +08:00
2005-01-16 06:15:51 +08:00
if (type == LIST_INCBIN || type == LIST_TIMES) {
suppress &= ~(type == LIST_INCBIN ? 1 : 2);
return;
2002-05-01 04:52:26 +08:00
}
2002-05-01 04:53:55 +08:00
2002-05-01 04:52:26 +08:00
listlevel--;
2005-01-16 06:15:51 +08:00
while (mistack && mistack->level > listlevel) {
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free(temp);
2002-05-01 04:52:26 +08:00
}
}
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();
}
2002-05-01 04:52:26 +08:00
ListGen nasmlist = {
list_init,
list_cleanup,
list_output,
list_line,
list_uplevel,
list_downlevel,
list_error
2002-05-01 04:52:26 +08:00
};