From 451e446016ccff0c72b6412d9ed7b462ef4d675b Mon Sep 17 00:00:00 2001
From: fachat <fachat@web.de>
Date: Sun, 29 Jul 2012 20:40:58 +0200
Subject: [PATCH] fix string display in listing, fix listing line breaks with
 .listbytes

---
 xa/src/xat.c                   | 106 +++++++++++++++------
 xa/tests/listing/Makefile      |  16 ++++
 xa/tests/listing/linebreak.a65 | 160 ++++++++++++++++++++++++++++++++
 xa/tests/listing/linebreak.out | 162 +++++++++++++++++++++++++++++++++
 4 files changed, 417 insertions(+), 27 deletions(-)
 create mode 100644 xa/tests/listing/Makefile
 create mode 100644 xa/tests/listing/linebreak.a65
 create mode 100644 xa/tests/listing/linebreak.out

diff --git a/xa/src/xat.c b/xa/src/xat.c
index a7a9299..dddf7f2 100644
--- a/xa/src/xat.c
+++ b/xa/src/xat.c
@@ -2583,6 +2583,32 @@ void list_setfile(FILE *fp) {
 	listfp = fp;
 }
 
+char *list_preamble(char *buf, int lineno, int seg, int pc) {
+	/* line number in file */
+	snprintf(buf, 10, "% 5d", lineno);
+	int i = strlen(buf);
+	buf += i;
+	buf += list_char(buf, ' ');
+
+	char c = '?';
+	/* preamble <segment>':'<address>' ' */
+	switch(seg) {
+	case SEG_ABS:	c='A'; break;
+	case SEG_TEXT:	c='T'; break;
+	case SEG_BSS:	c='B'; break;
+	case SEG_DATA:	c='D'; break;
+	case SEG_UNDEF:	c='U'; break;
+	case SEG_ZERO:	c='Z'; break;
+	}
+	buf = buf + list_char(buf, c);
+	buf = buf + list_char(buf, ':');
+	buf = buf + list_word(buf, pc);
+	buf = buf + list_nchar(buf, ' ', 2);
+
+	return buf;
+}
+
+
 /**
  * listing/listing_len give the buffer address and length respectively that contains
  * 	the token as they are produced by the tokenizer. 
@@ -2601,8 +2627,6 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
 	int lst_seg = listing[0];
 	int lst_pc = (listing[2]<<8) | (listing[1] & 255);
 
-	signed char c = '?';
-
 	/* no output file (not even stdout) */
 	if (listfp == NULL) return;
 
@@ -2618,43 +2642,59 @@ void do_listing(signed char *listing, int listing_len, signed char *bincode, int
 	}
 	list_last_lineno = list_lineno;
 
-	/* line number in file */
-	snprintf(buf, 10, "% 5d", list_lineno);
-	i = strlen(buf);
-	buf += i;
-	buf += list_char(buf, ' ');
+	buf = list_preamble(buf, list_lineno, lst_seg, lst_pc);
 
-	/* preamble <segment>':'<address>' ' */
-	switch(lst_seg) {
-	case SEG_ABS:	c='A'; break;
-	case SEG_TEXT:	c='T'; break;
-	case SEG_BSS:	c='B'; break;
-	case SEG_DATA:	c='D'; break;
-	case SEG_UNDEF:	c='U'; break;
-	case SEG_ZERO:	c='Z'; break;
+	// check if we have labels, so we can adjust the max printable number of 
+	// bytes in the last line
+	int num_last_line = 11;
+	int tmp = listing[3] & 255;
+	if (tmp == (T_DEFINE & 255)) {
+		// we have label definition
+		num_last_line = 8;
 	}
-	buf = buf + list_char(buf, c);
-	buf = buf + list_char(buf, ':');
-	buf = buf + list_word(buf, lst_pc);
-	buf = buf + list_nchar(buf, ' ', 2);
+	int overflow = 0;
 
 	/* binary output (up to 8 byte. If more than 8 byte, print 7 plus "..." */
 	n_hexb = bincode_len;
 	if (list_numbytes != 0 && n_hexb >= list_numbytes) {
 		n_hexb = list_numbytes-1;
+		overflow = 1;
 	}
 	for (i = 0; i < n_hexb; i++) {
 		buf = buf + list_byte(buf, bincode[i]);
 		buf = buf + list_sp(buf);
-	}
-	if ((n_hexb == 7) && (bincode_len > 7)) {
-		buf = buf + list_nchar(buf, '.', 3);
-	} else {
-		/* can move loop into nchar ... */
-		for (; i < 8; i++) {
-			buf = buf + list_nchar(buf, ' ', 3);
+		if ( (i%16) == 15) {
+			// make a break
+			buf[0] = 0;
+			fprintf(listfp, "%s\n", outline);
+			buf = outline;
+			buf = list_preamble(buf, list_lineno, lst_seg, lst_pc + i + 1);
 		}
 	}
+	if (overflow) {
+		// are we at the last byte?
+		if (n_hexb + 1 == bincode_len) {
+			// just print the last byte
+			buf = buf + list_byte(buf, bincode[i]);
+			buf = buf + list_sp(buf);
+		} else {
+			// display "..."
+			buf = buf + list_nchar(buf, '.', 3);
+		}
+		n_hexb++;
+	}
+	i = n_hexb % 16;
+	if (i > num_last_line) {
+		// make a break (Note: with original PC, as now the assembler text follows
+		buf[0] = 0;
+		fprintf(listfp, "%s\n", outline);
+		buf = outline;
+		buf = list_preamble(buf, list_lineno, lst_seg, lst_pc);
+		i = 0;
+	} 
+	i = num_last_line - i;
+	buf = buf + list_nchar(buf, ' ', i * 3);
+
 	buf = buf + list_sp(buf);
 
 	buf += list_tokens(buf, listing + 3, listing_len - 3);
@@ -2715,7 +2755,7 @@ int list_tokens(char *buf, signed char *input, int len) {
 		}
 	} else {
 		if (tmp >= 0 && tmp < Anzkey) {
-			outp += list_string(buf+outp, "          ");
+			outp += list_string(buf+outp, " ");
 		}
 	}
 
@@ -2820,6 +2860,18 @@ int list_tokens(char *buf, signed char *input, int len) {
 			inp += 6;
 			operator = 1;	/* check if arithmetic operator follows */
 			break;
+		case '"':
+			// string display
+			inp++;
+			outp += list_char(buf+outp, '"');
+			int len = input[inp] & 0xff;
+			for (int i = 0; i < len; i++) {
+				inp++;
+				outp += list_char(buf+outp, input[inp]);
+			}
+			inp++;
+			outp += list_char(buf+outp, '"');
+			break;
 		default:
 			c = input[inp];
 			if (c > 31) {
diff --git a/xa/tests/listing/Makefile b/xa/tests/listing/Makefile
new file mode 100644
index 0000000..f151618
--- /dev/null
+++ b/xa/tests/listing/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for tests
+#
+
+XA=../../xa
+
+tests: linebreak clean
+
+
+linebreak: linebreak.a65
+	${XA} -P- $< > a.out
+	cmp linebreak.out a.out
+
+clean:
+	rm -f a.err a.o65 a.out
+
diff --git a/xa/tests/listing/linebreak.a65 b/xa/tests/listing/linebreak.a65
new file mode 100644
index 0000000..1b4f8a8
--- /dev/null
+++ b/xa/tests/listing/linebreak.a65
@@ -0,0 +1,160 @@
+
+	*=$1000
+
+	// default listbytes is 8
+
+	lda #$0
+
+	// first without labels
+
+	.(
+	// less than 8 bytes
+	.byt 0,1,2,3,4,5	; 6
+	// seven bytes
+	.byt 0,1,2,3,4,5,6	; 7
+	// eight bytes
+	.byt 0,1,2,3,4,5,6,7	; 8
+	// nine bytes
+	.byt 0,1,2,3,4,5,6,7,8	; 9
+	// ten bytes
+	.byt 0,1,2,3,4,5,6,7,8,9	; 10
+	// eleven bytes
+	.byt 0,1,2,3,4,5,6,7,8,9,10	; 11
+	// fifteen bytes
+	.asc "012345678901234"	; 15, asc test as well
+	// sixteen bytes
+	.asc "0123456789012345"	; 16
+	// seventeen bytes
+	.asc "01234567890123456"; 17
+	// thirtythree
+	.asc "012345678901234567890123456789012"; 32
+
+	// now with labels
+
+	// less than 8 bytes
+l6	.byt 0,1,2,3,4,5	; 6
+	// seven bytes
+l7	.byt 0,1,2,3,4,5,6	; 7
+	// eight bytes
+l8	.byt 0,1,2,3,4,5,6,7	; 8
+	// nine bytes
+l9	.byt 0,1,2,3,4,5,6,7,8	; 9
+	// ten bytes
+l10	.byt 0,1,2,3,4,5,6,7,8,9	; 10
+	// eleven bytes
+l11	.byt 0,1,2,3,4,5,6,7,8,9,10	; 11
+	// fifteen bytes
+l15	.asc "012345678901234"	; 15, asc test as well
+	// sixteen bytes
+l16	.asc "0123456789012345"	; 16
+	// seventeen bytes
+l17	.asc "01234567890123456"; 17
+	// thirtythree
+l32	.asc "012345678901234567890123456789012"; 32
+
+	.)
+
+	// now set number of bytes per listing line to 10
+
+	.listbytes 10
+
+	.(
+	// less than 8 bytes
+	.byt 0,1,2,3,4,5	; 6
+	// seven bytes
+	.byt 0,1,2,3,4,5,6	; 7
+	// eight bytes
+	.byt 0,1,2,3,4,5,6,7	; 8
+	// nine bytes
+	.byt 0,1,2,3,4,5,6,7,8	; 9
+	// ten bytes
+	.byt 0,1,2,3,4,5,6,7,8,9	; 10
+	// eleven bytes
+	.byt 0,1,2,3,4,5,6,7,8,9,10	; 11
+	// fifteen bytes
+	.asc "012345678901234"	; 15, asc test as well
+	// sixteen bytes
+	.asc "0123456789012345"	; 16
+	// seventeen bytes
+	.asc "01234567890123456"; 17
+	// thirtythree
+	.asc "012345678901234567890123456789012"; 32
+
+
+	// now with labels
+
+	// less than 8 bytes
+l6	.byt 0,1,2,3,4,5	; 6
+	// seven bytes
+l7	.byt 0,1,2,3,4,5,6	; 7
+	// eight bytes
+l8	.byt 0,1,2,3,4,5,6,7	; 8
+	// nine bytes
+l9	.byt 01,2,3,4,5,6,7,8	; 9
+	// ten bytes
+l10	.byt 01,2,3,4,5,6,7,8,9	; 10
+	// eleven bytes
+l11	.byt 01,2,3,4,5,6,7,8,9,10	; 11
+	// fifteen bytes
+l15	.asc "012345678901234"	; 15, asc test as well
+	// sixteen bytes
+l16	.asc "0123456789012345"	; 16
+	// seventeen bytes
+l17	.asc "01234567890123456"; 17
+	// thirtythree
+l32	.asc "012345678901234567890123456789012"; 32
+
+	.)
+
+	// set number of listing bytes to unlimited
+	.listbytes unlimited
+
+	.(
+	// less than 8 bytes
+	.byt 0,1,2,3,4,5	; 6
+	// seven bytes
+	.byt 0,1,2,3,4,5,6	; 7
+	// eight bytes
+	.byt 0,1,2,3,4,5,6,7	; 8
+	// nine bytes
+	.byt 0,1,2,3,4,5,6,7,8	; 9
+	// ten bytes
+	.byt 0,1,2,3,4,5,6,7,8,9	; 10
+	// eleven bytes
+	.byt 0,1,2,3,4,5,6,7,8,9,10	; 11
+	// fifteen bytes
+	.asc "012345678901234"	; 15, asc test as well
+	// sixteen bytes
+	.asc "0123456789012345"	; 16
+	// seventeen bytes
+	.asc "01234567890123456"; 17
+	// thirtythree
+	.asc "012345678901234567890123456789012"; 32
+
+
+	// now with labels
+
+	// less than 8 bytes
+l6	.byt 0,1,2,3,4,5	; 6
+	// seven bytes
+l7	.byt 0,1,2,3,4,5,6	; 7
+	// eight bytes
+l8	.byt 0,1,2,3,4,5,6,7	; 8
+	// nine byte
+l9	.byt 0,1,2,3,4,5,6,7,8	; 9
+	// ten bytes
+l10	.byt 0,1,2,3,4,5,6,7,8,9	; 10
+	// eleven bytes
+l11	.byt 0,1,2,3,4,5,6,7,8,9,10	; 11
+	// fifteen bytes
+l15	.asc "012345678901234"	; 15, test as well
+	// sixteen bytes
+l16	.asc "0123456789012345"	; 16
+	// seventeen bytes
+l17	.asc "01234567890123456"; 17
+	// thirtythree
+l32	.asc "012345678901234567890123456789012"; 32
+
+	.)
+
+		
diff --git a/xa/tests/listing/linebreak.out b/xa/tests/listing/linebreak.out
new file mode 100644
index 0000000..723f4a4
--- /dev/null
+++ b/xa/tests/listing/linebreak.out
@@ -0,0 +1,162 @@
+
+linebreak.a65
+
+
+    2 A:1000                                     *= $1000
+
+    6 A:1000  a9 00                              lda #$00
+
+   10 A:1002                                     .( 
+
+   12 A:1002  00 01 02 03 04 05                  .byt 0,1,2,3,4,5; 6
+
+   14 A:1008  00 01 02 03 04 05 06               .byt 0,1,2,3,4,5,6; 7
+
+   16 A:100f  00 01 02 03 04 05 06 07            .byt 0,1,2,3,4,5,6,7; 8
+
+   18 A:1017  00 01 02 03 04 05 06 ...           .byt 0,1,2,3,4,5,6,7,8; 9
+
+   20 A:1020  00 01 02 03 04 05 06 ...           .byt 0,1,2,3,4,5,6,7,8,9; 10
+
+   22 A:102a  00 01 02 03 04 05 06 ...           .byt 0,1,2,3,4,5,6,7,8,9,10; 11
+
+   24 A:1035  30 31 32 33 34 35 36 ...           .asc "012345678901234"  ; 15, asc test as well
+
+   26 A:1044  30 31 32 33 34 35 36 ...           .asc "0123456789012345" ; 16
+
+   28 A:1054  30 31 32 33 34 35 36 ...           .asc "01234567890123456"; 17
+
+   30 A:1065  30 31 32 33 34 35 36 ...           .asc "012345678901234567890123456789012"; 32
+
+   35 A:1086  00 01 02 03 04 05        l6        .byt 0,1,2,3,4,5; 6
+
+   37 A:108c  00 01 02 03 04 05 06     l7        .byt 0,1,2,3,4,5,6; 7
+
+   39 A:1093  00 01 02 03 04 05 06 07  l8        .byt 0,1,2,3,4,5,6,7; 8
+
+   41 A:109b  00 01 02 03 04 05 06 ... l9        .byt 0,1,2,3,4,5,6,7,8; 9
+
+   43 A:10a4  00 01 02 03 04 05 06 ... l10       .byt 0,1,2,3,4,5,6,7,8,9; 10
+
+   45 A:10ae  00 01 02 03 04 05 06 ... l11       .byt 0,1,2,3,4,5,6,7,8,9,10; 11
+
+   47 A:10b9  30 31 32 33 34 35 36 ... l15       .asc "012345678901234"; 15, asc test as well
+
+   49 A:10c8  30 31 32 33 34 35 36 ... l16       .asc "0123456789012345"; 16
+
+   51 A:10d8  30 31 32 33 34 35 36 ... l17       .asc "01234567890123456"; 17
+
+   53 A:10e9  30 31 32 33 34 35 36 ... l32       .asc "012345678901234567890123456789012"; 32
+
+   55 A:110a                                     .) 
+
+   59 A:110a                                     .listbytes 10
+
+   61 A:110a                                     .( 
+
+   63 A:110a  00 01 02 03 04 05                  .byt 0,1,2,3,4,5; 6
+
+   65 A:1110  00 01 02 03 04 05 06               .byt 0,1,2,3,4,5,6; 7
+
+   67 A:1117  00 01 02 03 04 05 06 07            .byt 0,1,2,3,4,5,6,7; 8
+
+   69 A:111f  00 01 02 03 04 05 06 07 08         .byt 0,1,2,3,4,5,6,7,8; 9
+
+   71 A:1128  00 01 02 03 04 05 06 07 08 09      .byt 0,1,2,3,4,5,6,7,8,9; 10
+
+   73 A:1132  00 01 02 03 04 05 06 07 08 ...     .byt 0,1,2,3,4,5,6,7,8,9,10; 11
+
+   75 A:113d  30 31 32 33 34 35 36 37 38 ...     .asc "012345678901234"  ; 15, asc test as well
+
+   77 A:114c  30 31 32 33 34 35 36 37 38 ...     .asc "0123456789012345" ; 16
+
+   79 A:115c  30 31 32 33 34 35 36 37 38 ...     .asc "01234567890123456"; 17
+
+   81 A:116d  30 31 32 33 34 35 36 37 38 ...     .asc "012345678901234567890123456789012"; 32
+
+   87 A:118e  00 01 02 03 04 05        l6        .byt 0,1,2,3,4,5; 6
+
+   89 A:1194  00 01 02 03 04 05 06     l7        .byt 0,1,2,3,4,5,6; 7
+
+   91 A:119b  00 01 02 03 04 05 06 07  l8        .byt 0,1,2,3,4,5,6,7; 8
+
+   93 A:11a3  01 02 03 04 05 06 07 08  l9        .byt 1,2,3,4,5,6,7,8; 9
+
+   95 A:11ab  01 02 03 04 05 06 07 08 09 
+   95 A:11ab                           l10       .byt 1,2,3,4,5,6,7,8,9; 10
+
+   97 A:11b4  01 02 03 04 05 06 07 08 09 0a 
+   97 A:11b4                           l11       .byt 1,2,3,4,5,6,7,8,9,10; 11
+
+   99 A:11be  30 31 32 33 34 35 36 37 38 ...
+   99 A:11be                           l15       .asc "012345678901234"; 15, asc test as well
+
+  101 A:11cd  30 31 32 33 34 35 36 37 38 ...
+  101 A:11cd                           l16       .asc "0123456789012345"; 16
+
+  103 A:11dd  30 31 32 33 34 35 36 37 38 ...
+  103 A:11dd                           l17       .asc "01234567890123456"; 17
+
+  105 A:11ee  30 31 32 33 34 35 36 37 38 ...
+  105 A:11ee                           l32       .asc "012345678901234567890123456789012"; 32
+
+  107 A:120f                                     .) 
+
+  110 A:120f                                     .listbytes 0
+
+  112 A:120f                                     .( 
+
+  114 A:120f  00 01 02 03 04 05                  .byt 0,1,2,3,4,5; 6
+
+  116 A:1215  00 01 02 03 04 05 06               .byt 0,1,2,3,4,5,6; 7
+
+  118 A:121c  00 01 02 03 04 05 06 07            .byt 0,1,2,3,4,5,6,7; 8
+
+  120 A:1224  00 01 02 03 04 05 06 07 08         .byt 0,1,2,3,4,5,6,7,8; 9
+
+  122 A:122d  00 01 02 03 04 05 06 07 08 09      .byt 0,1,2,3,4,5,6,7,8,9; 10
+
+  124 A:1237  00 01 02 03 04 05 06 07 08 09 0a   .byt 0,1,2,3,4,5,6,7,8,9,10; 11
+
+  126 A:1242  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 
+  126 A:1242                                     .asc "012345678901234"  ; 15, asc test as well
+
+  128 A:1251  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 
+  128 A:1261                                     .asc "0123456789012345" ; 16
+
+  130 A:1261  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 
+  130 A:1271  36                                 .asc "01234567890123456"; 17
+
+  132 A:1272  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 
+  132 A:1282  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 
+  132 A:1292  32                                 .asc "012345678901234567890123456789012"; 32
+
+  138 A:1293  00 01 02 03 04 05        l6        .byt 0,1,2,3,4,5; 6
+
+  140 A:1299  00 01 02 03 04 05 06     l7        .byt 0,1,2,3,4,5,6; 7
+
+  142 A:12a0  00 01 02 03 04 05 06 07  l8        .byt 0,1,2,3,4,5,6,7; 8
+
+  144 A:12a8  00 01 02 03 04 05 06 07 08 
+  144 A:12a8                           l9        .byt 0,1,2,3,4,5,6,7,8; 9
+
+  146 A:12b1  00 01 02 03 04 05 06 07 08 09 
+  146 A:12b1                           l10       .byt 0,1,2,3,4,5,6,7,8,9; 10
+
+  148 A:12bb  00 01 02 03 04 05 06 07 08 09 0a 
+  148 A:12bb                           l11       .byt 0,1,2,3,4,5,6,7,8,9,10; 11
+
+  150 A:12c6  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 
+  150 A:12c6                           l15       .asc "012345678901234"; 15, test as well
+
+  152 A:12d5  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 
+  152 A:12e5                           l16       .asc "0123456789012345"; 16
+
+  154 A:12e5  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 
+  154 A:12f5  36                       l17       .asc "01234567890123456"; 17
+
+  156 A:12f6  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 
+  156 A:1306  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 
+  156 A:1316  32                       l32       .asc "012345678901234567890123456789012"; 32
+
+  158 A:1317                                     .)