1
0
mirror of https://github.com/fachat/xa65.git synced 2025-04-19 11:38:30 +00:00

Add HTML output for listing

This commit is contained in:
fachat 2012-07-30 16:22:13 +02:00
parent 93d832b04a
commit 4517bcb87e
14 changed files with 355 additions and 19 deletions

View File

@ -45,6 +45,7 @@
#include "xar.h"
#include "xat.h"
#include "xacharset.h"
#include "xalisting.h"
#include "version.h"
@ -116,6 +117,8 @@ int main(int argc,char *argv[])
signed char *s=NULL;
char *tmpp;
char *listformat = NULL;
int mifiles = 5;
int nifiles = 0;
int verbose = 0;
@ -307,6 +310,13 @@ int main(int argc,char *argv[])
printfile=argv[i]+2;
}
break;
case 'F':
if (argv[i][2]==0) {
listformat = argv[++i];
} else {
listformat = argv[i]+2;
}
break;
case 'o':
if(argv[i][2]==0) {
ofile=argv[++i];
@ -499,6 +509,8 @@ int main(int argc,char *argv[])
{
if(verbose) logout("xAss65: Pass 2:\n");
list_start(listformat);
seg_pass2();
if(!relmode) {
@ -508,6 +520,8 @@ int main(int argc,char *argv[])
segment = SEG_TEXT;
}
er=pass2();
list_end();
}
if(fplab) printllist(fplab);
@ -887,6 +901,8 @@ static void usage(int default816, FILE *fp)
" -e filename sets errorlog filename, default is none\n"
" -l filename sets labellist filename, default is none\n"
" -P filename sets filename for listing, default is none, '-' is stdout\n"
" -F format sets format for listing, default is plain, 'html' is current only other\n"
" supported format\n"
" -r adds crossreference list to labellist (if `-l' given)\n"
" -M allow ``:'' to appear in comments for MASM compatibility\n"
" -Xcompatset set compatibility flags for other assemblers, known values are:\n"

View File

@ -453,19 +453,16 @@ char *l_get_name(int n, label_t *is_cll) {
return ltp->n;
}
int l_get(int n, int *v, int *afl)
{
if(crossref) l_addocc(n,v,afl);
ltp = afile->la.lt+n;
if (ltp->is_cll == UNNAMED_DEF) {
// works on the static(!) ltp "label table pointer"
// also returns the actual index in the table of the current ltp
static int resolve_unnamed() {
// need to count up/down in the linkd label list for the block
char *namep = ltp->n;
int nextp = -1;
//printf("::: unnamed_def: %s, n=%d\n", namep, n);
while ((*namep == '+') || (*namep == '-')) {
char c = *namep;
int nextp = -1;
nextp = -1;
if (c == '+') {
nextp = ltp->blknext;
} else
@ -474,7 +471,7 @@ int l_get(int n, int *v, int *afl)
}
//printf("::: nextp=%d\n", nextp);
if (nextp == -1) {
return E_NODEF;
return -1; // E_NODEF
}
ltp = afile->la.lt+nextp;
//printf("::: leads to: %s, nextp=%d\n", ltp->n, nextp);
@ -482,7 +479,50 @@ int l_get(int n, int *v, int *afl)
namep++;
}
}
}
return nextp;
}
/* for the listing, esp. html links; returns a pointer to a static buffer, available till next call */
char *l_get_unique_name(int n) {
static char buf[MAXLINE];
ltp=afile->la.lt+n;
if (ltp->is_cll == CHEAP || ltp->is_cll == STD) {
sprintf(buf, "%d%c%s", ltp->blk,
(ltp->is_cll == CHEAP) ? 'C' : '_',
ltp->n);
} else
if (ltp->is_cll == UNNAMED) {
// definition of unnamed label - name is NULL
// so use the actual index
sprintf(buf, "%dU%d", ltp->blk, n);
} else
if (ltp->is_cll == UNNAMED_DEF) {
// we actually need to find the correct label from the "+" and "-"
// in the name
int tmp = resolve_unnamed();
if (tmp >= 0) {
sprintf(buf, "%dU%d", ltp->blk, tmp);
} else {
sprintf(buf, "__%d", tmp);
}
} else {
buf[0] = 0; // no value
}
return buf;
}
int l_get(int n, int *v, int *afl)
{
if(crossref) l_addocc(n,v,afl);
ltp = afile->la.lt+n;
if (ltp->is_cll == UNNAMED_DEF) {
int tmp = resolve_unnamed();
if (tmp == -1) return E_NODEF;
// now ltp is set to the actual label
}
(*v)=ltp->val;
lz=ltp->n;
*afl = ltp->afl;

View File

@ -48,6 +48,7 @@ int l_def(char *s, int* l, int *x, int *f);
int l_search(char *s, int *l, int *x, int *v, int *afl);
void l_set(int n, int v, int afl);
char* l_get_name(int n, label_t *is_cll);
char* l_get_unique_name(int n);
int l_get(int n, int *v, int *afl);
int l_vget(int n, int *v, char **s);
int ll_search(char *s, int *n, label_t labeltype);

View File

@ -3,7 +3,7 @@
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
* maintained by Cameron Kaiser
*
* Core tokenizing module/pass 1 and pass 2
* Assembler listing
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -59,6 +59,131 @@ static int list_byte(char *buf, int outbyte);
static int list_byte_f(char *buf, int outbyte, signed char format);
static int list_nibble_f(char *buf, int outnib, signed char format);
/*********************************************************************************************/
// formatter
typedef struct {
void (*start_listing)(char *name);
void (*start_line)();
int (*set_anchor)(char *buf, char *name); // returns number of bytes added to buf
int (*start_label)(char *buf, char *name); // returns number of bytes added to buf
int (*end_label)(char *buf);
void (*end_line)();
void (*end_listing)();
char* (*escape)(char *toescape); // returns pointer to static buffer, valid until next call
char* (*escape_char)(char toescape); // returns pointer to static buffer, valid until next call
} formatter_t;
static char *def_escape(char *toescape) {
return toescape;
}
static char *def_escape_char(char toescape) {
static char buf[2];
buf[0] = toescape;
buf[1] = 0;
return buf;
}
static formatter_t def_format = {
NULL, NULL, NULL, NULL,
NULL, NULL, NULL,
def_escape, def_escape_char
};
static void html_start_listing(char *name) {
// really short version for now
fprintf(listfp, "<html><head><title>%s</title></head><body><pre>\n",
(name == NULL) ? "(null)" : name);
}
static int html_set_anchor(char *buf, char *name) {
sprintf(buf, "<a name=\"%s\"> </a>", name);
return strlen(buf);
}
static int html_start_label(char *buf, char *name) {
sprintf(buf, "<a href=\"#%s\">", name);
return strlen(buf);
}
static int html_end_label(char *buf) {
sprintf(buf, "</a>");
return strlen(buf);
}
static void html_end_listing() {
fprintf(listfp, "</pre></body></html>\n");
}
static char *html_escape(char *toescape) {
static char buf[MAXLINE];
char *p = toescape;
char *q = buf;
while (*p != 0) {
if (*p == '<') {
strcpy(q, "&lt;");
q+=4;
p++;
} else
if (*p == '&') {
strcpy(q, "&amp;");
q+=5;
p++;
} else {
*q = *p;
q++;
p++;
}
}
*q = 0; // string terminator
return buf;
}
static char *html_escape_char(char toescape) {
static char buf[2];
buf[0] = toescape;
buf[1] = 0;
return html_escape(buf);
}
static formatter_t html_format = {
html_start_listing,
NULL,
html_set_anchor,
html_start_label,
html_end_label,
NULL,
html_end_listing,
html_escape, html_escape_char
};
static formatter_t *formatp = &def_format;
/*********************************************************************************************/
void list_start(const char *formatname) {
formatp = &def_format;
if (formatname != NULL && strcmp("html", formatname) == 0) {
formatp = &html_format;
}
if (listfp != NULL) {
if (formatp->start_listing != NULL) formatp->start_listing(list_filenamep);
}
}
void list_end() {
if (listfp != NULL) {
if (formatp->end_listing != NULL) formatp->end_listing();
}
}
// set number of bytes per line displayed as hex
void list_setbytes(int number_of_bytes_per_line) {
list_numbytes = number_of_bytes_per_line;
@ -137,6 +262,7 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
/* no output file (not even stdout) */
if (listfp == NULL) return;
/*printf("do_listing: listing=%p (%d), bincode=%p (%d)\n", listing, listing_len, bincode, bincode_len);*/
if (bincode_len < 0) bincode_len = -bincode_len;
@ -149,6 +275,9 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
}
list_last_lineno = list_lineno;
// could be extended to include the preamble...
if (formatp->start_line != NULL) formatp->start_line();
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc);
// check if we have labels, so we can adjust the max printable number of
@ -174,6 +303,8 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
// make a break
buf[0] = 0;
fprintf(listfp, "%s\n", outline);
if (formatp->end_line != NULL) formatp->end_line();
if (formatp->start_line != NULL) formatp->start_line();
buf = outline;
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc + i + 1);
}
@ -195,6 +326,8 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
// make a break (Note: with original PC, as now the assembler text follows
buf[0] = 0;
fprintf(listfp, "%s\n", outline);
if (formatp->end_line != NULL) formatp->end_line();
if (formatp->start_line != NULL) formatp->start_line();
buf = outline;
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc);
i = 0;
@ -220,6 +353,8 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
buf[0] = 0;
fprintf(listfp, "%s\n", outline);
if (formatp->end_line != NULL) formatp->end_line();
}
int list_tokens(char *buf, signed char *input, int len) {
@ -242,6 +377,12 @@ int list_tokens(char *buf, signed char *input, int len) {
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
/*printf("define: len=%d, inp=%d, tmp=%d\n", len, inp, tmp);*/
name=l_get_name(tmp, &is_cll);
// duplicate anchor names?
if (formatp->set_anchor != NULL) {
outp += formatp->set_anchor(buf+outp, l_get_unique_name(tmp));
}
if (is_cll == CHEAP) {
outp += list_char(buf+outp, '@');
} else
@ -295,7 +436,7 @@ int list_tokens(char *buf, signed char *input, int len) {
switch(input[inp]) {
case T_CAST:
outp += list_char(buf+outp, input[inp+1]);
outp += list_string(buf+outp, formatp->escape_char(input[inp+1]));
break;
case T_VALUE:
/*outp += list_char(buf+outp, 'V');*/
@ -311,6 +452,11 @@ int list_tokens(char *buf, signed char *input, int len) {
/* 16 bit label number */
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
name=l_get_name(tmp, &is_cll);
// duplicate label name
if (formatp->start_label != NULL) {
outp += formatp->start_label(buf+outp, l_get_unique_name(tmp));
}
if (is_cll == CHEAP) {
outp += list_char(buf+outp, '@');
} else
@ -320,6 +466,9 @@ int list_tokens(char *buf, signed char *input, int len) {
if (is_cll != UNNAMED) {
outp += list_string(buf+outp, name);
}
if (formatp->end_label != NULL) outp += formatp->end_label(buf+outp);
inp += 3;
operator = 1; /* check if arithmetic operator follows */
break;
@ -327,6 +476,12 @@ int list_tokens(char *buf, signed char *input, int len) {
/* label arithmetic operation; inp[3] is operation like '=' or '+' */
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
name=l_get_name(tmp, &is_cll);
if (input[inp+3] == '=') {
// label definition
if (formatp->set_anchor != NULL) {
outp += formatp->set_anchor(buf+outp, l_get_unique_name(tmp));
}
}
if (is_cll) outp += list_char(buf+outp, '@');
outp += list_string(buf+outp, name);
outp += list_char(buf+outp, input[inp+3]);
@ -357,8 +512,13 @@ int list_tokens(char *buf, signed char *input, int len) {
/* what is this? It's actually resolved during token conversion */
tmp = ((input[inp+5]&255)<<8) | (input[inp+4]&255);
name=l_get_name(tmp, &is_cll);
if (formatp->start_label != NULL) {
outp += formatp->start_label(buf+outp, l_get_unique_name(tmp));
}
if (is_cll) outp += list_char(buf+outp, '@');
outp += list_string(buf+outp, name);
if (formatp->end_label != NULL) outp += formatp->end_label(buf+outp);
/*
outp += list_byte(buf+outp, input[inp+1]);
outp += list_char(buf+outp, '#');
@ -383,7 +543,7 @@ int list_tokens(char *buf, signed char *input, int len) {
default:
c = input[inp];
if (c > 31) {
outp += list_char(buf+outp, input[inp]);
outp += list_string(buf+outp, formatp->escape_char(input[inp]));
} else {
outp += list_char(buf+outp, '\'');
outp += list_byte(buf+outp, input[inp]);
@ -395,7 +555,7 @@ int list_tokens(char *buf, signed char *input, int len) {
if (operator && inp < len) {
signed char op = input[inp];
if (op > 0 && op <= 17) {
outp += list_string(buf+outp, arith_ops[op]);
outp += list_string(buf+outp, formatp->escape(arith_ops[op]));
inp += 1;
}
operator = 0;

View File

@ -19,6 +19,14 @@
#ifndef __XA65_XALISTING_H__
#define __XA65_XALISTING_H__
void list_start(char *formatname); //either NULL or "html"
void list_end();
void list_setfile(FILE *fp);
void list_line(int l); /* set line number for the coming listing output */
void list_filename(char *fname);/* set file name for the coming listing output */
// list a single line/token set
void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len);
#endif /* __XA65_XALISTING_H__ */

View File

@ -40,6 +40,7 @@
#include "xao.h"
#include "xap.h"
#include "xacharset.h"
#include "xalisting.h"
int dsb_len = 0;

View File

@ -21,14 +21,10 @@
extern int dsb_len;
void list_setfile(FILE *fp);
int t_p1(signed char *s, signed char *t, int *ll, int *al);
int t_p2_l(signed char *t, int *ll, int *al);
int b_term(char *s, int *v, int *l, int pc);
void list_line(int l); /* set line number for the coming listing output */
void list_filename(char *fname);/* set file name for the coming listing output */
extern char *kt[]; // table of key words, needed for listing
extern char *arith_ops[]; // table of arithmetic operators, needed for listing
extern int number_of_valid_tokens; // as it says, in the "kt" table

View File

@ -4,7 +4,10 @@
XA=../../xa
tests: linebreak include1 clean
CA65=ca65
LD65=ld65
tests: linebreak include1 listblocks listca65 clean
include1: include1.a65
@ -15,6 +18,16 @@ linebreak: linebreak.a65
${XA} -P- $< > a.out
cmp linebreak.out a.out
listblocks: listblocks.a65
${XA} -P- -Fhtml listblocks.a65 > a.out
cmp listblocks.html a.out
listca65: listca65.a65
${XA} -XCA65 -P- -Fhtml listca65.a65 > a.out
#${CA65} $<; ${LD65} -t none -o unnamed2.ca65 unnamed2.o; rm unnamed2.o
cmp listca65.html a.out
cmp listca65.ca65 a.o65
clean:
rm -f a.err a.o65 a.out

View File

@ -0,0 +1,23 @@
// tests the html listing feature with blocks that
// contain the same label names, but in different scopes
*=$1000
label1 lda #$00
.(
label2 sta $02
bne label2
.)
.(
label2 lda $02 ; again!
bne label2
.)
label2 iny
beq label2
jmp label1

View File

@ -0,0 +1,24 @@
<html><head><title>(null)</title></head><body><pre>
listblocks.a65
5 A:1000 *= $1000
7 A:1000 a9 00 <a name="0_label1"> </a>label1 lda #$00
9 A:1002 .(
10 A:1002 85 02 <a name="1_label2"> </a>label2 sta $02
11 A:1004 d0 fc bne <a href="#1_label2">label2</a>
12 A:1006 .)
14 A:1006 .(
15 A:1006 a5 02 <a name="2_label2"> </a>label2 lda $02 ; again!
16 A:1008 d0 fc bne <a href="#2_label2">label2</a>
17 A:100a .)
19 A:100a c8 <a name="0_label2"> </a>label2 iny
20 A:100b f0 fd beq <a href="#0_label2">label2</a>
22 A:100d 4c 00 10 jmp <a href="#0_label1">label1</a>
</pre></body></html>

View File

@ -0,0 +1,24 @@
; tests the html listing feature with blocks that
; contain the same label names, but in different scopes
.org $1000
: lda #$00
.scope
: sta $02
: bne :-
.endscope
.scope
@label2: lda $02 ; again!
bne @label2
.endscope
label2: iny
beq label2
beq :---
jmp :--

Binary file not shown.

View File

@ -0,0 +1,30 @@
<html><head><title>(null)</title></head><body><pre>
listca65.a65
2 A:1000 ; tests the html listing feature with blocks that
3 A:1000 ; contain the same label names, but in different scopes
5 A:1000 *= $1000
7 A:1000 a9 00 <a name="0U0"> </a>: lda #$00
9 A:1002 .(
10 A:1002 85 02 <a name="1U1"> </a>: sta $02
11 A:1004 d0 fe <a name="1U2"> </a>: bne <a href="#1U2">:-</a>
12 A:1006 .)
14 A:1006 .(
15 A:1006 <a name="3Clabel2"> </a>@label2
15 A:1006 a5 02 lda $02 ; again!
16 A:1008 d0 fc bne <a href="#3Clabel2">@label2</a>
17 A:100a .)
19 A:100a <a name="0_label2"> </a>label2
19 A:100a c8 iny
20 A:100b f0 fd beq <a href="#0_label2">label2</a>
22 A:100d f0 f1 beq <a href="#0U0">:---</a>
23 A:100f 4c 02 10 jmp <a href="#1U1">:--</a>
</pre></body></html>

BIN
xa/tests/listing/listca65.o Normal file

Binary file not shown.