2002-05-01 04:52:26 +08:00
|
|
|
/* listing.c listing file generator for the Netwide Assembler
|
|
|
|
*
|
|
|
|
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
|
|
|
* Julian Hall. All rights reserved. The software is
|
|
|
|
* redistributable under the licence given in the file "Licence"
|
|
|
|
* distributed in the NASM archive.
|
|
|
|
*
|
|
|
|
* initial version 2/vii/97 by Simon Tatham
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.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 int listlinep;
|
|
|
|
|
|
|
|
static char listdata[2*LIST_INDENT]; /* we need less than that actually */
|
|
|
|
static long listoffset;
|
|
|
|
|
|
|
|
static long listlineno;
|
|
|
|
|
|
|
|
static long listp;
|
|
|
|
|
|
|
|
static int suppress; /* for INCBIN & TIMES special cases */
|
|
|
|
|
|
|
|
static int listlevel, listlevel_e;
|
|
|
|
|
|
|
|
static FILE *listfp;
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_emit (void)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
if (!listlinep && !listdata[0])
|
|
|
|
return;
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
fprintf(listfp, "%6ld ", ++listlineno);
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
if (listdata[0])
|
|
|
|
fprintf(listfp, "%08lX %-*s", listoffset, LIST_HEXBIT+1, listdata);
|
|
|
|
else
|
|
|
|
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)
|
|
|
|
fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""), listlevel_e);
|
|
|
|
else if (listlinep)
|
|
|
|
fprintf(listfp, " ");
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
if (listlinep)
|
|
|
|
fprintf(listfp, " %s", listline);
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
fputc('\n', listfp);
|
|
|
|
listlinep = FALSE;
|
|
|
|
listdata[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_init (char *fname, efunc error)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
listfp = fopen (fname, "w");
|
|
|
|
if (!listfp) {
|
|
|
|
error (ERR_NONFATAL, "unable to open listing file `%s'", fname);
|
|
|
|
return;
|
|
|
|
}
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
*listline = '\0';
|
|
|
|
listlineno = 0;
|
|
|
|
listp = TRUE;
|
|
|
|
listlevel = 0;
|
|
|
|
suppress = 0;
|
|
|
|
mistack = nasm_malloc(sizeof(MacroInhibit));
|
|
|
|
mistack->next = NULL;
|
|
|
|
mistack->level = 0;
|
|
|
|
mistack->inhibiting = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_cleanup (void)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
if (!listp)
|
|
|
|
return;
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
while (mistack) {
|
|
|
|
MacroInhibit *temp = mistack;
|
|
|
|
mistack = temp->next;
|
|
|
|
nasm_free (temp);
|
|
|
|
}
|
2002-05-01 04:53:55 +08:00
|
|
|
|
2002-05-01 04:52:26 +08:00
|
|
|
list_emit();
|
|
|
|
fclose (listfp);
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_out (long offset, char *str)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
|
|
|
|
strcat(listdata, "-");
|
|
|
|
list_emit();
|
|
|
|
}
|
|
|
|
if (!listdata[0])
|
|
|
|
listoffset = offset;
|
|
|
|
strcat(listdata, str);
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_output (long offset, void *data, unsigned long type)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
long typ, size;
|
|
|
|
|
|
|
|
if (!listp || suppress)
|
|
|
|
return;
|
|
|
|
|
|
|
|
typ = type & OUT_TYPMASK;
|
|
|
|
size = type & OUT_SIZMASK;
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
if (typ == OUT_RAWDATA)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
unsigned char *p = data;
|
|
|
|
char q[3];
|
2002-05-01 04:53:55 +08:00
|
|
|
while (size--)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
HEX (q, *p);
|
|
|
|
q[2] = '\0';
|
|
|
|
list_out (offset++, q);
|
|
|
|
p++;
|
|
|
|
}
|
2002-05-01 04:53:55 +08:00
|
|
|
}
|
|
|
|
else if (typ == OUT_ADDRESS)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
unsigned long d = *(long *)data;
|
|
|
|
char q[11];
|
|
|
|
unsigned char p[4], *r = p;
|
2002-05-01 04:53:55 +08:00
|
|
|
if (size == 4)
|
|
|
|
{
|
2002-05-01 04:52:26 +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);
|
2002-05-01 04:53:55 +08:00
|
|
|
}
|
|
|
|
else {
|
2002-05-01 04:52:26 +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);
|
|
|
|
}
|
2002-05-01 04:53:55 +08:00
|
|
|
}
|
|
|
|
else if (typ == OUT_REL2ADR)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
unsigned long d = *(long *)data;
|
|
|
|
char q[11];
|
|
|
|
unsigned char 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);
|
2002-05-01 04:53:55 +08:00
|
|
|
}
|
|
|
|
else if (typ == OUT_REL4ADR)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
unsigned long d = *(long *)data;
|
|
|
|
char q[11];
|
|
|
|
unsigned char 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);
|
2002-05-01 04:53:55 +08:00
|
|
|
}
|
|
|
|
else if (typ == OUT_RESERVE)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
char q[20];
|
|
|
|
sprintf(q, "<res %08lX>", size);
|
|
|
|
list_out (offset, q);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_line (int type, char *line)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
if (!listp)
|
|
|
|
return;
|
2002-05-01 04:53:55 +08:00
|
|
|
|
|
|
|
if (mistack && mistack->inhibiting)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_uplevel (int type)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
if (!listp)
|
|
|
|
return;
|
2002-05-01 04:53:55 +08:00
|
|
|
if (type == LIST_INCBIN || type == LIST_TIMES)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
suppress |= (type == LIST_INCBIN ? 1 : 2);
|
|
|
|
list_out (listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
|
|
|
|
return;
|
|
|
|
}
|
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
|
|
|
|
|
|
|
if (mistack && mistack->inhibiting && type == LIST_INCLUDE)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
|
|
|
|
temp->next = mistack;
|
|
|
|
temp->level = listlevel;
|
|
|
|
temp->inhibiting = FALSE;
|
|
|
|
mistack = temp;
|
2002-05-01 04:53:55 +08:00
|
|
|
}
|
|
|
|
else if (type == LIST_MACRO_NOLIST)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
|
|
|
|
temp->next = mistack;
|
|
|
|
temp->level = listlevel;
|
|
|
|
temp->inhibiting = TRUE;
|
|
|
|
mistack = temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-01 04:53:55 +08:00
|
|
|
static void list_downlevel (int type)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
if (!listp)
|
|
|
|
return;
|
2002-05-01 04:53:55 +08:00
|
|
|
|
|
|
|
if (type == LIST_INCBIN || type == LIST_TIMES)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
suppress &= ~(type == LIST_INCBIN ? 1 : 2);
|
|
|
|
return;
|
|
|
|
}
|
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
|
|
|
while (mistack && mistack->level > listlevel)
|
|
|
|
{
|
2002-05-01 04:52:26 +08:00
|
|
|
MacroInhibit *temp = mistack;
|
|
|
|
mistack = temp->next;
|
|
|
|
nasm_free (temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ListGen nasmlist = {
|
|
|
|
list_init,
|
|
|
|
list_cleanup,
|
|
|
|
list_output,
|
|
|
|
list_line,
|
|
|
|
list_uplevel,
|
|
|
|
list_downlevel
|
|
|
|
};
|