mirror of
https://github.com/fachat/xa65.git
synced 2024-09-28 09:54:27 +00:00
Merge branch 'testsuite' into testmerge
Resolved Conflicts: xa/ChangeLog xa/src/xa.c xa/tests/adrm/Makefile xa/tests/binclude/Makefile xa/tests/charset/Makefile xa/tests/comcom/Makefile xa/tests/fordef/Makefile xa/tests/incerr/Makefile
This commit is contained in:
commit
bd65f3de18
5
README
5
README
@ -13,3 +13,8 @@ These are the directories:
|
|||||||
xa - contains the main source. The master branch is the stable version (currently 2.3.5)
|
xa - contains the main source. The master branch is the stable version (currently 2.3.5)
|
||||||
|
|
||||||
|
|
||||||
|
These are the current branches:
|
||||||
|
|
||||||
|
master - stable branch, currently 2.3.5
|
||||||
|
listing - experimental branch that adds ca65 compatibility features and assembler listing
|
||||||
|
|
||||||
|
21
xa/ChangeLog
21
xa/ChangeLog
@ -304,3 +304,24 @@ xa-2.3.6
|
|||||||
* Fixed message offsets.
|
* Fixed message offsets.
|
||||||
|
|
||||||
-- Cameron Kaiser <ckaiser@floodgap.com> 11 July 2014
|
-- Cameron Kaiser <ckaiser@floodgap.com> 11 July 2014
|
||||||
|
|
||||||
|
xa-2.x.x
|
||||||
|
|
||||||
|
* Add -E commandline option to not stop after 20 errors, but show all
|
||||||
|
of them
|
||||||
|
* Introduce -X compatibility set commandline option, to distinguish
|
||||||
|
between MASM and CA65 compatibility options
|
||||||
|
* Implement CA65 "cheap local labels", ":=" label definitions,
|
||||||
|
and various pseudo opcodes (.include, .import, .importzp,
|
||||||
|
.zeropage, .proc (anonymous only), .endproc, .code, .org, .reloc)
|
||||||
|
* some bugfixes around error/warning logs
|
||||||
|
* some more comments
|
||||||
|
* Stuff is mostly untested...
|
||||||
|
|
||||||
|
-- André Fachat <afachat@gmx.de> 25 June, 2011
|
||||||
|
|
||||||
|
xa-2.x.x
|
||||||
|
|
||||||
|
* add test suite code
|
||||||
|
|
||||||
|
-- André Fachat <afachat@gmx.de> 20 August, 2014
|
||||||
|
10
xa/TODO
10
xa/TODO
@ -8,3 +8,13 @@ o inc a -> ina, dec a -> dea (right now uses bare inc and dec)
|
|||||||
o VICE label file support
|
o VICE label file support
|
||||||
|
|
||||||
o Smarter -X that can cope with non-block-aligned segment sizes
|
o Smarter -X that can cope with non-block-aligned segment sizes
|
||||||
|
|
||||||
|
o The listing feature is not bug-free yet:
|
||||||
|
- ca65 and other assembler compatibility pseudo-opcodes will be
|
||||||
|
listed as xa specific ones, not the original in the source
|
||||||
|
E.g. a CA65 ".scope" will appear as ".(" in the listing
|
||||||
|
- The assembler has no constant handling, so constants are
|
||||||
|
resolved at parse time. Thus they appear as their value
|
||||||
|
in the listing. Only situation now is ".listbytes unlimited",
|
||||||
|
which will show as ".listbytes 0" in the listing
|
||||||
|
|
||||||
|
@ -40,8 +40,9 @@ respectively. Not valid for bss or zero.
|
|||||||
.B \-X
|
.B \-X
|
||||||
Extract text and data segment together
|
Extract text and data segment together
|
||||||
from the file instead of writing back the whole
|
from the file instead of writing back the whole
|
||||||
file. Relocating data segment to the end of the text segment
|
file. Relocating data segment to the end of the text segment and
|
||||||
(ignoring the \-xd option) before extracting.
|
bss segment to the end of the data segment
|
||||||
|
(\-xd and \-xb options override the derived address) before extracting.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-help
|
.B \-\-help
|
||||||
Show summary of options.
|
Show summary of options.
|
||||||
|
71
xa/man/xa.1
71
xa/man/xa.1
@ -19,6 +19,9 @@ further in this manual page.
|
|||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
|
.B \-E
|
||||||
|
Do not stop after 20 errors, but show all errors.
|
||||||
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
Verbose output.
|
Verbose output.
|
||||||
.TP
|
.TP
|
||||||
@ -54,6 +57,15 @@ use the special filename
|
|||||||
.BR \-
|
.BR \-
|
||||||
to output to standard output.
|
to output to standard output.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-P filename
|
||||||
|
Set listing filename, default is none. use the special filename
|
||||||
|
.BR \-
|
||||||
|
to print the listing to standard output.
|
||||||
|
.TP
|
||||||
|
.B \-F html
|
||||||
|
Set listing format, default is plain. The only other currently supported format is
|
||||||
|
.BR html
|
||||||
|
.TP
|
||||||
.B \-e filename
|
.B \-e filename
|
||||||
Set errorlog filename, default is none.
|
Set errorlog filename, default is none.
|
||||||
.TP
|
.TP
|
||||||
@ -67,12 +79,27 @@ to reconstruct source.
|
|||||||
Add cross-reference list to labellist (requires
|
Add cross-reference list to labellist (requires
|
||||||
.BR \-l ).
|
.BR \-l ).
|
||||||
.TP
|
.TP
|
||||||
|
.B \-Xcompatset
|
||||||
|
Enables compatibility settings to become more (not fully!) compatible with other 6502 assemblers.
|
||||||
|
Currently supported are compatibility set "MASM" and "CA65".
|
||||||
|
"MASM" allows colons to appear in comments. This does not affect colon interpretation elsewhere.
|
||||||
|
"CA65" allows the ":=" label definition (instead of "="), It adds the "unnamed labels" and also the
|
||||||
|
"cheap local labels" using
|
||||||
|
the "@" character. This, however, disables the "@" 24-bit enforcement.
|
||||||
|
"C" enables the usage of "0xHEX" and "0OCTAL" C-style number encodings. Note that you can combine
|
||||||
|
compatibility sets e.g. with "-XCA65 -XC".
|
||||||
|
.TP
|
||||||
.B \-M
|
.B \-M
|
||||||
Allow colons to appear in comments; for MASM compatibility. This does
|
Allow colons to appear in comments; for MASM compatibility. This does
|
||||||
not affect colon interpretation elsewhere.
|
not affect colon interpretation elsewhere. This option is deprecated. Use
|
||||||
|
.BR -X
|
||||||
|
instead.
|
||||||
.TP
|
.TP
|
||||||
.B \-R
|
.B \-R
|
||||||
Start assembler in relocating mode.
|
Start assembler in relocating mode, i.e. use segments.
|
||||||
|
.TP
|
||||||
|
.B \-U
|
||||||
|
Do not allow undefined labels in relocating mode.
|
||||||
.TP
|
.TP
|
||||||
.B \-Llabel
|
.B \-Llabel
|
||||||
Defines
|
Defines
|
||||||
@ -339,7 +366,7 @@ for those opcodes that support it (i.e., keep as 16 bit word)
|
|||||||
.B @
|
.B @
|
||||||
render as 24-bit quantity for 65816 (must specify
|
render as 24-bit quantity for 65816 (must specify
|
||||||
.B \-w
|
.B \-w
|
||||||
command-line option).
|
command-line option, must not specify the CA65 compatibility).
|
||||||
.B This is required to specify any
|
.B This is required to specify any
|
||||||
.B 24-bit quantity!
|
.B 24-bit quantity!
|
||||||
.TP
|
.TP
|
||||||
@ -441,7 +468,7 @@ and
|
|||||||
are synonymous, so you can mix things such as
|
are synonymous, so you can mix things such as
|
||||||
.B .byt $43, 22, """a character string"""
|
.B .byt $43, 22, """a character string"""
|
||||||
and get the expected result. The string is subject to the current character
|
and get the expected result. The string is subject to the current character
|
||||||
set, but the remaining bytes are inserted wtihout modification.
|
set, but the remaining bytes are inserted without modification.
|
||||||
.TP
|
.TP
|
||||||
.B .aasc """text1""","text2",...
|
.B .aasc """text1""","text2",...
|
||||||
Specifies a character string that is
|
Specifies a character string that is
|
||||||
@ -492,9 +519,20 @@ or precede it with
|
|||||||
.B &
|
.B &
|
||||||
to declare it within the previous level only (or globally if you are only
|
to declare it within the previous level only (or globally if you are only
|
||||||
one level deep). Sixteen levels of scoping are permitted.
|
one level deep). Sixteen levels of scoping are permitted.
|
||||||
|
.B \&.)
|
||||||
|
is equivalent to
|
||||||
|
.B .block
|
||||||
|
or
|
||||||
|
.B .proc
|
||||||
|
. The latter is similar to the ca65 pseudo-opcode, but only anonymous blocks
|
||||||
|
are supported.
|
||||||
.TP
|
.TP
|
||||||
.B \&.)
|
.B \&.)
|
||||||
Closes a block.
|
Closes a block. This is equivalent to
|
||||||
|
.B .bend
|
||||||
|
or
|
||||||
|
.B .endproc
|
||||||
|
.
|
||||||
.TP
|
.TP
|
||||||
.B \.as \.al \.xs \.xl
|
.B \.as \.al \.xs \.xl
|
||||||
Only relevant in 65816 mode (with the
|
Only relevant in 65816 mode (with the
|
||||||
@ -521,6 +559,11 @@ and
|
|||||||
generate errors if
|
generate errors if
|
||||||
.B \-w
|
.B \-w
|
||||||
is not specified.
|
is not specified.
|
||||||
|
.TP
|
||||||
|
.B .include "filename"
|
||||||
|
Includes another file in place of the pseudo opcode. Same as the preprocessor
|
||||||
|
.B #include
|
||||||
|
|
||||||
.LP
|
.LP
|
||||||
The following pseudo-ops apply primarily to relocatable .o65 objects.
|
The following pseudo-ops apply primarily to relocatable .o65 objects.
|
||||||
A full discussion of the relocatable format is beyond the
|
A full discussion of the relocatable format is beyond the
|
||||||
@ -538,6 +581,11 @@ space for allocation and .zero being uninitialized zero page space for
|
|||||||
allocation. In .bss and .zero, only labels are evaluated. These pseudo-ops
|
allocation. In .bss and .zero, only labels are evaluated. These pseudo-ops
|
||||||
are valid in relative and absolute modes.
|
are valid in relative and absolute modes.
|
||||||
.TP
|
.TP
|
||||||
|
.B .code
|
||||||
|
For CA65 compatibility this is currently mapped to ".text".
|
||||||
|
.B .zeropage
|
||||||
|
For CA65 compatibility this is currently mapped to ".zero".
|
||||||
|
.TP
|
||||||
.B .align value
|
.B .align value
|
||||||
Aligns the current segment to a byte boundary (2, 4 or 256) as specified by
|
Aligns the current segment to a byte boundary (2, 4 or 256) as specified by
|
||||||
.B
|
.B
|
||||||
@ -555,6 +603,17 @@ is used to specify the file option being referenced. A table of these options
|
|||||||
is in the relocatable o65 file format description. The remainder of the options
|
is in the relocatable o65 file format description. The remainder of the options
|
||||||
are interpreted as values to insert. Any number of values may be specified,
|
are interpreted as values to insert. Any number of values may be specified,
|
||||||
and may also be strings.
|
and may also be strings.
|
||||||
|
.TP
|
||||||
|
.B .import label1, label2, label3, ...
|
||||||
|
Defines the given labels as global labels which are imported and resolved during
|
||||||
|
the link stage. Similar to the
|
||||||
|
.B -L
|
||||||
|
command line parameter
|
||||||
|
.TP
|
||||||
|
.B .importzp label1, label2, label3, ...
|
||||||
|
Similar to
|
||||||
|
.B .import
|
||||||
|
only it imports zeropage labels (i.e. byte values)
|
||||||
|
|
||||||
.SH PREPROCESSOR
|
.SH PREPROCESSOR
|
||||||
|
|
||||||
@ -830,7 +889,7 @@ This manual page was written by David Weinehall <tao@acc.umu.se>,
|
|||||||
Andre Fachat <fachat@web.de>
|
Andre Fachat <fachat@web.de>
|
||||||
and Cameron Kaiser <ckaiser@floodgap.com>.
|
and Cameron Kaiser <ckaiser@floodgap.com>.
|
||||||
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
Original xa package (C)1989-1997 Andre Fachat. Additional changes
|
||||||
(C)1989-2009 Andre Fachat, Jolse Maginnis, David Weinehall,
|
(C)1989-2011 Andre Fachat, Jolse Maginnis, David Weinehall,
|
||||||
Cameron Kaiser. The official maintainer is Cameron Kaiser.
|
Cameron Kaiser. The official maintainer is Cameron Kaiser.
|
||||||
|
|
||||||
.SH WEBSITE
|
.SH WEBSITE
|
||||||
|
@ -74,6 +74,7 @@ void usage(FILE *fp)
|
|||||||
" -X extracts the file such that text and data\n"
|
" -X extracts the file such that text and data\n"
|
||||||
" segments are chained, i.e. possibly relocating\n"
|
" segments are chained, i.e. possibly relocating\n"
|
||||||
" the data segment to the end of the text segment\n"
|
" the data segment to the end of the text segment\n"
|
||||||
|
" -v verbose output\n"
|
||||||
" --version output version information and exit\n"
|
" --version output version information and exit\n"
|
||||||
" --help display this help and exit\n");
|
" --help display this help and exit\n");
|
||||||
}
|
}
|
||||||
@ -86,6 +87,7 @@ int main(int argc, char *argv[]) {
|
|||||||
int tbase = 0, dbase = 0, bbase = 0, zbase = 0;
|
int tbase = 0, dbase = 0, bbase = 0, zbase = 0;
|
||||||
char *outfile = "a.o65";
|
char *outfile = "a.o65";
|
||||||
int extract = 0;
|
int extract = 0;
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
usage(stderr);
|
usage(stderr);
|
||||||
@ -106,6 +108,9 @@ int main(int argc, char *argv[]) {
|
|||||||
if(argv[i][0]=='-') {
|
if(argv[i][0]=='-') {
|
||||||
/* process options */
|
/* process options */
|
||||||
switch(argv[i][1]) {
|
switch(argv[i][1]) {
|
||||||
|
case 'v':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if(argv[i][2]) outfile=argv[i]+2;
|
if(argv[i][2]) outfile=argv[i]+2;
|
||||||
else outfile=argv[++i];
|
else outfile=argv[++i];
|
||||||
@ -188,25 +193,53 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
file.tbase = file.buf[ 9]*256+file.buf[ 8];
|
file.tbase = file.buf[ 9]*256+file.buf[ 8];
|
||||||
file.tlen = file.buf[11]*256+file.buf[10];
|
file.tlen = file.buf[11]*256+file.buf[10];
|
||||||
file.tdiff = tflag? tbase - file.tbase : 0;
|
file.tdiff = tflag ? tbase - file.tbase : 0;
|
||||||
|
|
||||||
file.dbase = file.buf[13]*256+file.buf[12];
|
file.dbase = file.buf[13]*256+file.buf[12];
|
||||||
file.dlen = file.buf[15]*256+file.buf[14];
|
file.dlen = file.buf[15]*256+file.buf[14];
|
||||||
|
file.ddiff = dflag ? dbase - file.dbase : 0;
|
||||||
if (extract == 3) {
|
if (extract == 3) {
|
||||||
if (dflag) {
|
if (dflag) {
|
||||||
fprintf(stderr,"reloc65: %s: Warning: data segment address ignored for -X option\n", argv[i]);
|
fprintf(stderr,"reloc65: %s: Warning: data segment address overrides -X option\n", argv[i]);
|
||||||
|
} else {
|
||||||
|
dbase = file.tbase + file.tdiff + file.tlen;
|
||||||
|
file.ddiff = dbase - file.dbase;
|
||||||
}
|
}
|
||||||
dbase = file.tbase + file.tdiff + file.tlen;
|
|
||||||
file.ddiff = dbase - file.dbase;
|
|
||||||
} else {
|
|
||||||
file.ddiff = dflag? dbase - file.dbase : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file.bbase = file.buf[17]*256+file.buf[16];
|
file.bbase = file.buf[17]*256+file.buf[16];
|
||||||
file.blen = file.buf[19]*256+file.buf[18];
|
file.blen = file.buf[19]*256+file.buf[18];
|
||||||
file.bdiff = bflag? bbase - file.bbase : 0;
|
file.bdiff = bflag ? bbase - file.bbase : 0;
|
||||||
file.zbase = file.buf[21]*256+file.buf[20];
|
if (extract == 3) {
|
||||||
file.zlen = file.buf[23]*256+file.buf[21];
|
if (bflag) {
|
||||||
file.zdiff = zflag? zbase - file.zbase : 0;
|
fprintf(stderr,"reloc65: %s: Warning: bss segment address overrides -X option\n", argv[i]);
|
||||||
|
} else {
|
||||||
|
bbase = file.dbase + file.ddiff + file.dlen;
|
||||||
|
file.bdiff = bbase - file.bbase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.zbase = file.buf[21]*256+file.buf[20];
|
||||||
|
file.zlen = file.buf[23]*256+file.buf[22];
|
||||||
|
file.zdiff = zflag ? zbase - file.zbase : 0;
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
printf("Relocating segments to:\n");
|
||||||
|
printf("text segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n",
|
||||||
|
file.tbase + file.tdiff, file.tbase + file.tdiff + file.tlen,
|
||||||
|
file.tlen, file.tlen, file.tdiff, file.tdiff & 0xffff);
|
||||||
|
printf("data segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n",
|
||||||
|
file.dbase + file.ddiff, file.dbase + file.ddiff + file.dlen,
|
||||||
|
file.dlen, file.dlen, file.ddiff, file.ddiff & 0xffff);
|
||||||
|
printf("bss segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n",
|
||||||
|
file.bbase + file.bdiff, file.bbase + file.bdiff + file.blen,
|
||||||
|
file.blen, file.blen, file.bdiff, file.bdiff & 0xffff);
|
||||||
|
printf("zero segment @ $%04x - $%04x, %5d ($%04x) bytes, diff is %5d ($%04x)\n",
|
||||||
|
file.zbase + file.zdiff, file.zbase + file.zdiff + file.zlen,
|
||||||
|
file.zlen, file.zlen, file.zdiff, file.zdiff & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pointer of position in file */
|
||||||
file.segt = file.buf + hlen;
|
file.segt = file.buf + hlen;
|
||||||
file.segd = file.segt + file.tlen;
|
file.segd = file.segt + file.tlen;
|
||||||
file.utab = file.segd + file.dlen;
|
file.utab = file.segd + file.dlen;
|
||||||
|
2
xa/src/.gitignore
vendored
Normal file
2
xa/src/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
|
@ -1,7 +1,8 @@
|
|||||||
OBJ = xa.o xaa.o xal.o xap.o xat.o xar.o xar2.o xao.o xau.o xam.o xacharset.o
|
OBJ = xa.o xaa.o xal.o xap.o xat.o xar.o xar2.o xao.o xau.o xam.o xacharset.o xalisting.o
|
||||||
|
|
||||||
#CFLAGS=-W -Wall -pedantic -ansi #-g
|
#CFLAGS=-W -Wall -pedantic -ansi -g
|
||||||
#CFLAGS=-W -Wall -ansi -O2
|
#CFLAGS=-W -Wall -ansi -O2
|
||||||
|
CFLAGS=-g -std=c99
|
||||||
#LD = ${CC}
|
#LD = ${CC}
|
||||||
#LDFLAGS = "-lc"
|
#LDFLAGS = "-lc"
|
||||||
|
|
||||||
|
255
xa/src/xa.c
255
xa/src/xa.c
@ -45,6 +45,7 @@
|
|||||||
#include "xar.h"
|
#include "xar.h"
|
||||||
#include "xat.h"
|
#include "xat.h"
|
||||||
#include "xacharset.h"
|
#include "xacharset.h"
|
||||||
|
#include "xalisting.h"
|
||||||
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
@ -55,26 +56,33 @@
|
|||||||
#define ANZWARN 13
|
#define ANZWARN 13
|
||||||
|
|
||||||
#define programname "xa"
|
#define programname "xa"
|
||||||
#define progversion "v2.3.6"
|
#define progversion "v2.3.6+af"
|
||||||
#define authors "Written by Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser"
|
#define authors "Written by Andre Fachat, Jolse Maginnis, David Weinehall and Cameron Kaiser"
|
||||||
#define copyright "Copyright (C) 1989-2014 Andre Fachat, Jolse Maginnis, David Weinehall\nand Cameron Kaiser."
|
#define copyright "Copyright (C) 1989-2014 Andre Fachat, Jolse Maginnis, David Weinehall\nand Cameron Kaiser."
|
||||||
|
|
||||||
/* exported globals */
|
/* exported globals */
|
||||||
int ncmos, cmosfl, w65816, n65816;
|
int ncmos, cmosfl, w65816, n65816;
|
||||||
int masm = 0;
|
/* compatibility flags */
|
||||||
|
int masm = 0; /* MASM */
|
||||||
|
int ca65 = 0; /* CA65 */
|
||||||
|
int ctypes = 0; /* C compatibility, like "0xab" types */
|
||||||
|
|
||||||
int nolink = 0;
|
int nolink = 0;
|
||||||
int romable = 0;
|
int romable = 0;
|
||||||
int romaddr = 0;
|
int romaddr = 0;
|
||||||
int noglob = 0;
|
int noglob = 0;
|
||||||
int showblk = 0;
|
int showblk = 0;
|
||||||
int crossref = 0;
|
int crossref = 0;
|
||||||
|
int noundef = 0; // overrides -R acceptance of undefined labels
|
||||||
char altppchar;
|
char altppchar;
|
||||||
|
|
||||||
/* local variables */
|
/* local variables */
|
||||||
|
|
||||||
static char out[MAXLINE];
|
static char out[MAXLINE];
|
||||||
static time_t tim1, tim2;
|
static time_t tim1, tim2;
|
||||||
static FILE *fpout, *fperr, *fplab;
|
static FILE *fpout, *fperr, *fplab, *fplist;
|
||||||
static int ner = 0;
|
static int ner = 0;
|
||||||
|
static int ner_max = 20;
|
||||||
|
|
||||||
static int align = 1;
|
static int align = 1;
|
||||||
|
|
||||||
@ -85,12 +93,14 @@ static int x_init(void);
|
|||||||
static int pass1(void);
|
static int pass1(void);
|
||||||
static int pass2(void);
|
static int pass2(void);
|
||||||
static int puttmp(int);
|
static int puttmp(int);
|
||||||
|
static int puttmpw(int);
|
||||||
static int puttmps(signed char *, int);
|
static int puttmps(signed char *, int);
|
||||||
static void chrput(int);
|
static void chrput(int);
|
||||||
static int xa_getline(char *);
|
static int xa_getline(char *);
|
||||||
static void lineout(void);
|
static void lineout(void);
|
||||||
static long ga_p1(void);
|
static long ga_p1(void);
|
||||||
static long gm_p1(void);
|
static long gm_p1(void);
|
||||||
|
static int set_compat(char *compat_name);
|
||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
int memode,xmode;
|
int memode,xmode;
|
||||||
@ -110,6 +120,8 @@ int main(int argc,char *argv[])
|
|||||||
signed char *s=NULL;
|
signed char *s=NULL;
|
||||||
char *tmpp;
|
char *tmpp;
|
||||||
|
|
||||||
|
char *listformat = NULL;
|
||||||
|
|
||||||
int mifiles = 5;
|
int mifiles = 5;
|
||||||
int nifiles = 0;
|
int nifiles = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
@ -117,9 +129,10 @@ int main(int argc,char *argv[])
|
|||||||
int no_link = 0;
|
int no_link = 0;
|
||||||
|
|
||||||
char **ifiles;
|
char **ifiles;
|
||||||
char *ofile;
|
char *printfile; /* print listing to this file */
|
||||||
char *efile;
|
char *ofile; /* output file */
|
||||||
char *lfile;
|
char *efile; /* error listing goes there */
|
||||||
|
char *lfile; /* labels go here */
|
||||||
char *ifile;
|
char *ifile;
|
||||||
|
|
||||||
char old_e[MAXLINE];
|
char old_e[MAXLINE];
|
||||||
@ -173,6 +186,7 @@ int main(int argc,char *argv[])
|
|||||||
ofile="a.o65";
|
ofile="a.o65";
|
||||||
efile=NULL;
|
efile=NULL;
|
||||||
lfile=NULL;
|
lfile=NULL;
|
||||||
|
printfile=NULL;
|
||||||
|
|
||||||
if(pp_init()) {
|
if(pp_init()) {
|
||||||
logout("fatal: pp: no memory!");
|
logout("fatal: pp: no memory!");
|
||||||
@ -191,6 +205,9 @@ int main(int argc,char *argv[])
|
|||||||
while(i<argc) {
|
while(i<argc) {
|
||||||
if(argv[i][0]=='-') {
|
if(argv[i][0]=='-') {
|
||||||
switch(argv[i][1]) {
|
switch(argv[i][1]) {
|
||||||
|
case 'E':
|
||||||
|
ner_max = 0;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
/* intentionally not allowing an argument to follow with a
|
/* intentionally not allowing an argument to follow with a
|
||||||
space to avoid - being seen as the alternate
|
space to avoid - being seen as the alternate
|
||||||
@ -210,6 +227,19 @@ int main(int argc,char *argv[])
|
|||||||
case 'M':
|
case 'M':
|
||||||
masm = 1; /* MASM compatibility mode */
|
masm = 1; /* MASM compatibility mode */
|
||||||
break;
|
break;
|
||||||
|
case 'X': /* compatibility across assemblers... */
|
||||||
|
{
|
||||||
|
char *name = NULL;
|
||||||
|
if (argv[i][2] == 0) {
|
||||||
|
name = argv[++i];
|
||||||
|
} else {
|
||||||
|
name = argv[i]+2;
|
||||||
|
}
|
||||||
|
if (set_compat(name) < 0) {
|
||||||
|
fprintf(stderr, "Compatibility set '%s' unknown - ignoring! (check case?)\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'O': /* output charset */
|
case 'O': /* output charset */
|
||||||
{
|
{
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
@ -241,6 +271,9 @@ int main(int argc,char *argv[])
|
|||||||
case 'R':
|
case 'R':
|
||||||
relmode = 1;
|
relmode = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'U':
|
||||||
|
noundef = 1;
|
||||||
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
s = (signed char*)strstr(argv[i]+2,"=");
|
s = (signed char*)strstr(argv[i]+2,"=");
|
||||||
if(s) *s = ' ';
|
if(s) *s = ' ';
|
||||||
@ -276,6 +309,20 @@ int main(int argc,char *argv[])
|
|||||||
reg_include(argv[i]+2);
|
reg_include(argv[i]+2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
if(argv[i][2]==0) {
|
||||||
|
printfile=argv[++i];
|
||||||
|
} else {
|
||||||
|
printfile=argv[i]+2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (argv[i][2]==0) {
|
||||||
|
listformat = argv[++i];
|
||||||
|
} else {
|
||||||
|
listformat = argv[i]+2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if(argv[i][2]==0) {
|
if(argv[i][2]==0) {
|
||||||
ofile=argv[++i];
|
ofile=argv[++i];
|
||||||
@ -356,6 +403,12 @@ int main(int argc,char *argv[])
|
|||||||
if(setfext(old_l,".lab")==0) lfile = old_l;
|
if(setfext(old_l,".lab")==0) lfile = old_l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (printfile!=NULL && !strcmp(printfile, "-")) {
|
||||||
|
printfile=NULL;
|
||||||
|
fplist = stdout;
|
||||||
|
} else {
|
||||||
|
fplist= printfile ? xfopen(printfile,"w") : NULL;
|
||||||
|
}
|
||||||
fplab= lfile ? xfopen(lfile,"w") : NULL;
|
fplab= lfile ? xfopen(lfile,"w") : NULL;
|
||||||
fperr= efile ? xfopen(efile,"w") : NULL;
|
fperr= efile ? xfopen(efile,"w") : NULL;
|
||||||
if(!strcmp(ofile,"-")) {
|
if(!strcmp(ofile,"-")) {
|
||||||
@ -371,6 +424,7 @@ int main(int argc,char *argv[])
|
|||||||
|
|
||||||
if(verbose) fprintf(stderr, "%s\n",copyright);
|
if(verbose) fprintf(stderr, "%s\n",copyright);
|
||||||
|
|
||||||
|
|
||||||
if(1 /*!m_init()*/)
|
if(1 /*!m_init()*/)
|
||||||
{
|
{
|
||||||
if(1 /*!b_init()*/)
|
if(1 /*!b_init()*/)
|
||||||
@ -384,6 +438,8 @@ int main(int argc,char *argv[])
|
|||||||
if(fperr) fprintf(fperr,"%s\n",copyright);
|
if(fperr) fprintf(fperr,"%s\n",copyright);
|
||||||
if(verbose) logout(ctime(&tim1));
|
if(verbose) logout(ctime(&tim1));
|
||||||
|
|
||||||
|
list_setfile(fplist);
|
||||||
|
|
||||||
/* Pass 1 */
|
/* Pass 1 */
|
||||||
|
|
||||||
pc[SEG_ABS]= 0; /* abs addressing */
|
pc[SEG_ABS]= 0; /* abs addressing */
|
||||||
@ -406,7 +462,7 @@ int main(int argc,char *argv[])
|
|||||||
if(verbose) logout(out);
|
if(verbose) logout(out);
|
||||||
|
|
||||||
er=pp_open(ifile);
|
er=pp_open(ifile);
|
||||||
puttmp(0);
|
puttmpw(0);
|
||||||
puttmp(T_FILE);
|
puttmp(T_FILE);
|
||||||
puttmp(0);
|
puttmp(0);
|
||||||
puttmp(0);
|
puttmp(0);
|
||||||
@ -459,6 +515,8 @@ int main(int argc,char *argv[])
|
|||||||
{
|
{
|
||||||
if(verbose) logout("xAss65: Pass 2:\n");
|
if(verbose) logout("xAss65: Pass 2:\n");
|
||||||
|
|
||||||
|
list_start(listformat);
|
||||||
|
|
||||||
seg_pass2();
|
seg_pass2();
|
||||||
|
|
||||||
if(!relmode) {
|
if(!relmode) {
|
||||||
@ -468,6 +526,8 @@ int main(int argc,char *argv[])
|
|||||||
segment = SEG_TEXT;
|
segment = SEG_TEXT;
|
||||||
}
|
}
|
||||||
er=pass2();
|
er=pass2();
|
||||||
|
|
||||||
|
list_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fplab) printllist(fplab);
|
if(fplab) printllist(fplab);
|
||||||
@ -476,9 +536,10 @@ int main(int argc,char *argv[])
|
|||||||
|
|
||||||
if((!er) && relmode) seg_end(fpout); /* write reloc/label info */
|
if((!er) && relmode) seg_end(fpout); /* write reloc/label info */
|
||||||
|
|
||||||
|
if(fplist && fplist!=stdout) fclose(fplist);
|
||||||
if(fperr) fclose(fperr);
|
if(fperr) fclose(fperr);
|
||||||
if(fplab) fclose(fplab);
|
if(fplab) fclose(fplab);
|
||||||
if(fpout) fclose(fpout);
|
if(fpout && fpout!=stdout) fclose(fpout);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logout("fatal: x: no memory!\n");
|
logout("fatal: x: no memory!\n");
|
||||||
@ -500,7 +561,12 @@ int main(int argc,char *argv[])
|
|||||||
|
|
||||||
if(ner || er)
|
if(ner || er)
|
||||||
{
|
{
|
||||||
|
if (ner_max > 0) {
|
||||||
fprintf(stderr, "Break after %d error%c\n",ner,ner?'s':0);
|
fprintf(stderr, "Break after %d error%c\n",ner,ner?'s':0);
|
||||||
|
} else {
|
||||||
|
/* ner_max==0, i.e. show all errors */
|
||||||
|
fprintf(stderr, "End after %d error%c\n",ner,ner?'s':0);
|
||||||
|
}
|
||||||
/*unlink();*/
|
/*unlink();*/
|
||||||
if(ofile) {
|
if(ofile) {
|
||||||
unlink(ofile);
|
unlink(ofile);
|
||||||
@ -615,39 +681,41 @@ static int pass2(void)
|
|||||||
filep=&datei;
|
filep=&datei;
|
||||||
afile->mn.tmpe=0L;
|
afile->mn.tmpe=0L;
|
||||||
|
|
||||||
while(ner<20 && afile->mn.tmpe<afile->mn.tmpz)
|
while((ner_max==0 || ner<ner_max) && afile->mn.tmpe<afile->mn.tmpz)
|
||||||
{
|
{
|
||||||
l=afile->mn.tmp[afile->mn.tmpe++];
|
// get the length of the entry (now two byte - need to handle the sign)
|
||||||
|
l = 255 & afile->mn.tmp[afile->mn.tmpe++];
|
||||||
|
l |= afile->mn.tmp[afile->mn.tmpe++] << 8;
|
||||||
ll=l;
|
ll=l;
|
||||||
|
|
||||||
|
//printf("%p: l=%d first=%02x\n", afile->mn.tmp+afile->mn.tmpe-1, l, 0xff & afile->mn.tmp[afile->mn.tmpe]);
|
||||||
|
|
||||||
if(!l)
|
if(!l)
|
||||||
{
|
{
|
||||||
if(afile->mn.tmp[afile->mn.tmpe]==T_LINE)
|
if(afile->mn.tmp[afile->mn.tmpe]==T_LINE)
|
||||||
{
|
{
|
||||||
datei.fline=(afile->mn.tmp[afile->mn.tmpe+1]&255)+(afile->mn.tmp[afile->mn.tmpe+2]<<8);
|
datei.fline=(afile->mn.tmp[afile->mn.tmpe+1]&255)+(afile->mn.tmp[afile->mn.tmpe+2]<<8);
|
||||||
afile->mn.tmpe+=3;
|
afile->mn.tmpe+=3;
|
||||||
|
list_line(datei.fline); /* set line number of next listing output */
|
||||||
} else
|
} else
|
||||||
if(afile->mn.tmp[afile->mn.tmpe]==T_FILE)
|
if(afile->mn.tmp[afile->mn.tmpe]==T_FILE)
|
||||||
{
|
{
|
||||||
|
// copy the current line number from the current file descriptor
|
||||||
datei.fline=(afile->mn.tmp[afile->mn.tmpe+1]&255)+(afile->mn.tmp[afile->mn.tmpe+2]<<8);
|
datei.fline=(afile->mn.tmp[afile->mn.tmpe+1]&255)+(afile->mn.tmp[afile->mn.tmpe+2]<<8);
|
||||||
|
// copy the pointer to the file name in the current file descriptor
|
||||||
|
// Note: the filename in the current file descriptor is separately malloc'd and
|
||||||
|
// thus save to store the pointer
|
||||||
memcpy(&datei.fname, afile->mn.tmp+afile->mn.tmpe+3, sizeof(datei.fname));
|
memcpy(&datei.fname, afile->mn.tmp+afile->mn.tmpe+3, sizeof(datei.fname));
|
||||||
afile->mn.tmpe+=3+sizeof(datei.fname);
|
afile->mn.tmpe+=3+sizeof(datei.fname);
|
||||||
/*
|
|
||||||
datei.fname = malloc(strlen((char*) afile->mn.tmp+afile->mn.tmpe+3)+1);
|
list_filename(datei.fname); /* set file name of next listing output */
|
||||||
if(!datei.fname) {
|
|
||||||
fprintf(stderr,"Oops, no more memory\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
strcpy(datei.fname,(char*) afile->mn.tmp+afile->mn.tmpe+3);
|
|
||||||
afile->mn.tmpe+=3+strlen(datei.fname);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
/* do not attempt address mode optimization on pass 2 */
|
/* do not attempt address mode optimization on pass 2 */
|
||||||
er=t_p2(afile->mn.tmp+afile->mn.tmpe,&ll,1,&al);
|
|
||||||
|
|
||||||
|
/* t_p2_l() includes the listing call to do_listing() */
|
||||||
|
er=t_p2_l(afile->mn.tmp+afile->mn.tmpe,&ll,&al);
|
||||||
if(er==E_NOLINE)
|
if(er==E_NOLINE)
|
||||||
{
|
{
|
||||||
} else
|
} else
|
||||||
@ -752,16 +820,14 @@ fprintf(stderr, "offset = %i length = %i fstart = %i flen = %i charo = %c\n",
|
|||||||
|
|
||||||
static int pass1(void)
|
static int pass1(void)
|
||||||
{
|
{
|
||||||
signed char o[MAXLINE];
|
signed char o[2*MAXLINE]; /* doubled for token listing */
|
||||||
int l,er,temp_er,al;
|
int l,er,al;
|
||||||
|
|
||||||
memode=0;
|
memode=0;
|
||||||
xmode=0;
|
xmode=0;
|
||||||
tlen=0;
|
tlen=0;
|
||||||
ner=0;
|
ner=0;
|
||||||
|
|
||||||
temp_er = 0;
|
|
||||||
|
|
||||||
/*FIXIT*/
|
/*FIXIT*/
|
||||||
while(!(er=xa_getline(s)))
|
while(!(er=xa_getline(s)))
|
||||||
{
|
{
|
||||||
@ -774,7 +840,7 @@ static int pass1(void)
|
|||||||
case SEG_ZERO: zlen += al; break;
|
case SEG_ZERO: zlen += al; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*printf(": er= %d, l=%d, tmpz=%d\n",er,l,tmpz); */
|
//printf(": er= %d, l=%d\n",er,l);
|
||||||
|
|
||||||
if(l)
|
if(l)
|
||||||
{
|
{
|
||||||
@ -782,14 +848,14 @@ static int pass1(void)
|
|||||||
{
|
{
|
||||||
if(er==E_OKDEF)
|
if(er==E_OKDEF)
|
||||||
{
|
{
|
||||||
if(!(er=puttmp(l)))
|
if(!(er=puttmpw(l)))
|
||||||
er=puttmps(o,l);
|
er=puttmps(o,l);
|
||||||
} else
|
} else
|
||||||
if(er==E_NOLINE)
|
if(er==E_NOLINE)
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if(!(er=puttmp(-l)))
|
if(!(er=puttmpw(-l)))
|
||||||
er=puttmps(o,l);
|
er=puttmps(o,l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -827,6 +893,7 @@ static void usage(int default816, FILE *fp)
|
|||||||
programname);
|
programname);
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
" -v verbose output\n"
|
" -v verbose output\n"
|
||||||
|
" -E do not break after 20 errors, but show all\n"
|
||||||
" -x old filename behaviour (overrides `-o', `-e', `-l')\n"
|
" -x old filename behaviour (overrides `-o', `-e', `-l')\n"
|
||||||
" This is deprecated and may disappear in future versions!\n"
|
" This is deprecated and may disappear in future versions!\n"
|
||||||
" -C no CMOS-opcodes\n"
|
" -C no CMOS-opcodes\n"
|
||||||
@ -842,11 +909,18 @@ static void usage(int default816, FILE *fp)
|
|||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
" -e filename sets errorlog filename, default is none\n"
|
" -e filename sets errorlog filename, default is none\n"
|
||||||
" -l filename sets labellist 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"
|
" -r adds crossreference list to labellist (if `-l' given)\n"
|
||||||
" -M allow ``:'' to appear in comments for MASM compatibility\n"
|
" -M allow ``:'' to appear in comments for MASM compatibility\n"
|
||||||
" -R start assembler in relocating mode\n");
|
" -Xcompatset set compatibility flags for other assemblers, known values are:\n"
|
||||||
|
" MASM, CA65\n"
|
||||||
|
" -R start assembler in relocating mode\n"
|
||||||
|
" -U do not allow undefined labels in relocating mode\n");
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
" -Llabel defines `label' as absolute, undefined label even when linking\n"
|
" -Llabel defines `label' as absolute, undefined label even when linking\n"
|
||||||
|
" -p<c> replace preprocessor char '#' with custom, e.g. '-p!' replaces it with '!'\n"
|
||||||
" -b? addr set segment base address to integer value addr\n"
|
" -b? addr set segment base address to integer value addr\n"
|
||||||
" `?' stands for t(ext), d(ata), b(ss) and z(ero) segment\n"
|
" `?' stands for t(ext), d(ata), b(ss) and z(ero) segment\n"
|
||||||
" (address can be given more than once, last one is used)\n");
|
" (address can be given more than once, last one is used)\n");
|
||||||
@ -900,7 +974,7 @@ static char *ertxt[] = {
|
|||||||
"NewFile",
|
"NewFile",
|
||||||
"CMOS instruction used with -C",
|
"CMOS instruction used with -C",
|
||||||
"pp:Wrong parameter count",
|
"pp:Wrong parameter count",
|
||||||
"Illegal pointer arithmetic",
|
"Illegal pointer arithmetic (-26)",
|
||||||
"Illegal segment",
|
"Illegal segment",
|
||||||
"File header option too long",
|
"File header option too long",
|
||||||
"File option not at file start (when ROM-able)",
|
"File option not at file start (when ROM-able)",
|
||||||
@ -939,11 +1013,10 @@ static char *ertxt[] = {
|
|||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
|
||||||
/* warnings */
|
/* warnings */
|
||||||
"Cutting word relocation in byte value",
|
"Cutting word relocation in byte value",
|
||||||
"Byte relocation in word value",
|
"Byte relocation in word value",
|
||||||
"Illegal pointer arithmetic",
|
"Illegal pointer arithmetic (-66)",
|
||||||
"Address access to low or high byte pointer",
|
"Address access to low or high byte pointer",
|
||||||
"High byte access to low byte pointer",
|
"High byte access to low byte pointer",
|
||||||
"Low byte access to high byte pointer",
|
"Low byte access to high byte pointer",
|
||||||
@ -977,7 +1050,9 @@ static int x_init(void)
|
|||||||
static int puttmp(int c)
|
static int puttmp(int c)
|
||||||
{
|
{
|
||||||
int er=E_NOMEM;
|
int er=E_NOMEM;
|
||||||
/*printf("puttmp: afile=%p, tmp=%p, tmpz=%d\n",afile, afile?afile->mn.tmp:0, afile?afile->mn.tmpz:0);*/
|
|
||||||
|
//printf("puttmp: %02x -> %p \n",0xff & c, afile->mn.tmp+afile->mn.tmpz);
|
||||||
|
|
||||||
if(afile->mn.tmpz<TMPMEM)
|
if(afile->mn.tmpz<TMPMEM)
|
||||||
{
|
{
|
||||||
afile->mn.tmp[afile->mn.tmpz++]=c;
|
afile->mn.tmp[afile->mn.tmpz++]=c;
|
||||||
@ -986,17 +1061,37 @@ static int puttmp(int c)
|
|||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int puttmpw(int c)
|
||||||
|
{
|
||||||
|
int er=E_NOMEM;
|
||||||
|
|
||||||
|
//printf("puttmp: %02x -> %p \n",0xff & c, afile->mn.tmp+afile->mn.tmpz);
|
||||||
|
|
||||||
|
if(afile->mn.tmpz<TMPMEM-1)
|
||||||
|
{
|
||||||
|
afile->mn.tmp[afile->mn.tmpz++]= c & 0xff;
|
||||||
|
afile->mn.tmp[afile->mn.tmpz++]= (c >> 8) & 0xff;
|
||||||
|
er=E_OK;
|
||||||
|
}
|
||||||
|
return(er);
|
||||||
|
}
|
||||||
|
|
||||||
static int puttmps(signed char *s, int l)
|
static int puttmps(signed char *s, int l)
|
||||||
{
|
{
|
||||||
int i=0,er=E_NOMEM;
|
int i=0,er=E_NOMEM;
|
||||||
|
|
||||||
|
// printf("puttmps %d bytes from %p to %p:", l, s, afile->mn.tmp+afile->mn.tmpz);
|
||||||
|
|
||||||
if(afile->mn.tmpz+l<TMPMEM)
|
if(afile->mn.tmpz+l<TMPMEM)
|
||||||
{
|
{
|
||||||
while(i<l)
|
while(i<l) {
|
||||||
afile->mn.tmp[afile->mn.tmpz++]=s[i++];
|
//printf(" %02x", 0xff & s[i]);
|
||||||
|
afile->mn.tmp[afile->mn.tmpz++]=s[i++];
|
||||||
|
}
|
||||||
|
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
}
|
}
|
||||||
|
// printf("\n");
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,25 +1121,19 @@ static int xa_getline(char *s)
|
|||||||
|
|
||||||
if(ec==E_NEWLINE)
|
if(ec==E_NEWLINE)
|
||||||
{
|
{
|
||||||
puttmp(0);
|
puttmpw(0);
|
||||||
puttmp(T_LINE);
|
puttmp(T_LINE);
|
||||||
puttmp((filep->fline)&255);
|
puttmpw(filep->fline);
|
||||||
puttmp(((filep->fline)>>8)&255);
|
ec=E_OK;
|
||||||
ec=E_OK;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if(ec==E_NEWFILE)
|
if(ec==E_NEWFILE)
|
||||||
{
|
{
|
||||||
puttmp(0);
|
puttmpw(0);
|
||||||
puttmp(T_FILE);
|
puttmp(T_FILE);
|
||||||
puttmp((filep->fline)&255);
|
puttmpw(filep->fline);
|
||||||
puttmp(((filep->fline)>>8)&255);
|
|
||||||
puttmps((signed char*)&(filep->fname), sizeof(filep->fname));
|
puttmps((signed char*)&(filep->fname), sizeof(filep->fname));
|
||||||
/*
|
|
||||||
puttmps((signed char*)filep->fname,
|
|
||||||
1+(int)strlen(filep->fname));
|
|
||||||
*/
|
|
||||||
ec=E_OK;
|
ec=E_OK;
|
||||||
}
|
}
|
||||||
} while(!ec && l[i]=='\0');
|
} while(!ec && l[i]=='\0');
|
||||||
@ -1053,26 +1142,50 @@ static int xa_getline(char *s)
|
|||||||
gl=0;
|
gl=0;
|
||||||
if(!ec || ec==E_EOF)
|
if(!ec || ec==E_EOF)
|
||||||
{
|
{
|
||||||
|
int startofline = 1;
|
||||||
do {
|
do {
|
||||||
c=s[j]=l[i++];
|
c=s[j]=l[i++];
|
||||||
|
|
||||||
if (c=='\"')
|
if (c=='\"') {
|
||||||
hkfl^=1;
|
hkfl^=1;
|
||||||
if (c==';' && !hkfl)
|
}
|
||||||
|
if (c==';' && !hkfl) {
|
||||||
|
// start of comment
|
||||||
comcom = 1;
|
comcom = 1;
|
||||||
if (c=='\0')
|
}
|
||||||
break; /* hkfl = comcom = 0 */
|
if (c=='\0') {
|
||||||
if (c==':' && !hkfl && (!comcom || !masm)) {
|
// end of line
|
||||||
gl=1;
|
break; /* hkfl = comcom = 0 */
|
||||||
break;
|
}
|
||||||
}
|
if (c==':' && !hkfl) {
|
||||||
|
/* if the next char is a "=" - so that we have a ":=" - and we
|
||||||
|
we have ca65 compatibility, we ignore the colon */
|
||||||
|
// also check for ":+" and ":-"
|
||||||
|
|
||||||
|
if (((!startofline) && l[i]!='=' && l[i]!='+' && l[i]!='-') || !ca65 || comcom) {
|
||||||
|
/* but otherwise we check if it is in a comment and we have
|
||||||
|
MASM or CA65 compatibility, then we ignore the colon as well */
|
||||||
|
if(!comcom || !(masm || ca65)) {
|
||||||
|
/* we found a colon, so we keep the current line in memory
|
||||||
|
but return the part before the colon, and next time the part
|
||||||
|
after the colon, so we can parse C64 BASIC text assembler... */
|
||||||
|
gl=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isspace(c)) {
|
||||||
|
startofline = 0;
|
||||||
|
}
|
||||||
j++;
|
j++;
|
||||||
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
|
} while (c!='\0' && j<MAXLINE-1 && i<MAXLINE-1);
|
||||||
|
|
||||||
s[j]='\0';
|
s[j]='\0';
|
||||||
} else
|
} else
|
||||||
s[0]='\0';
|
s[0]='\0';
|
||||||
|
#if 0
|
||||||
|
printf("got line: %s\n", s);
|
||||||
|
#endif
|
||||||
return(ec);
|
return(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1092,8 +1205,8 @@ static void lineout(void)
|
|||||||
|
|
||||||
void errout(int er)
|
void errout(int er)
|
||||||
{
|
{
|
||||||
if (er<-ANZERR || er>-1) {
|
if (er<=-ANZERR || er>-1) {
|
||||||
if(er>=-(ANZERR+ANZWARN) && er < -ANZERR) {
|
if(er>=-(ANZERR+ANZWARN) && er <= -ANZERR) {
|
||||||
sprintf(out,"%s:line %d: %04x: Warning - %s\n",
|
sprintf(out,"%s:line %d: %04x: Warning - %s\n",
|
||||||
filep->fname, filep->fline, pc[segment], ertxt[(-er)-1]);
|
filep->fname, filep->fline, pc[segment], ertxt[(-er)-1]);
|
||||||
} else {
|
} else {
|
||||||
@ -1129,3 +1242,31 @@ void logout(char *s)
|
|||||||
fprintf(fperr,"%s",s);
|
fprintf(fperr,"%s",s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
int *flag;
|
||||||
|
} compat_set;
|
||||||
|
|
||||||
|
static compat_set compat_sets[] = {
|
||||||
|
{ "MASM", &masm },
|
||||||
|
{ "CA65", &ca65 },
|
||||||
|
{ "C", &ctypes },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
int set_compat(char *compat_name) {
|
||||||
|
int i = 0;
|
||||||
|
while (compat_sets[i].name != NULL) {
|
||||||
|
if (strcmp(compat_sets[i].name, compat_name) == 0) {
|
||||||
|
/* set appropriate compatibility flag */
|
||||||
|
(*compat_sets[i].flag) = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,11 +22,12 @@
|
|||||||
#include "xah.h" /* For SEG_MAX */
|
#include "xah.h" /* For SEG_MAX */
|
||||||
|
|
||||||
extern int ncmos, cmosfl, w65816, n65816;
|
extern int ncmos, cmosfl, w65816, n65816;
|
||||||
extern int masm, nolink;
|
extern int masm, ca65, nolink,noundef;
|
||||||
extern int noglob;
|
extern int noglob;
|
||||||
extern int showblk;
|
extern int showblk;
|
||||||
extern int relmode;
|
extern int relmode;
|
||||||
extern int crossref;
|
extern int crossref;
|
||||||
|
extern int ctypes;
|
||||||
extern char altppchar;
|
extern char altppchar;
|
||||||
|
|
||||||
extern int tlen, tbase;
|
extern int tlen, tbase;
|
||||||
|
32
xa/src/xaa.c
32
xa/src/xaa.c
@ -119,13 +119,15 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
if(s[pp]==T_LABEL)
|
if(s[pp]==T_LABEL)
|
||||||
{
|
{
|
||||||
er=l_get(cval(s+pp+1),v, &afl);
|
er=l_get(cval(s+pp+1),v, &afl);
|
||||||
/* printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
//printf("label: er=%d, seg=%d, afl=%d, nolink=%d, fundef=%d\n",
|
||||||
er, segment, afl, nolink, fundef); */
|
// er, segment, afl, nolink, fundef);
|
||||||
if(er==E_NODEF && segment != SEG_ABS && fundef ) {
|
if(er==E_NODEF && segment != SEG_ABS && fundef ) {
|
||||||
if( nolink || (afl==SEG_UNDEF)) {
|
if( (nolink && !noundef) || ((afl==SEG_UNDEF) || (afl==SEG_UNDEFZP))) {
|
||||||
er = E_OK;
|
er = E_OK;
|
||||||
*v = 0;
|
*v = 0;
|
||||||
afl = SEG_UNDEF;
|
if(afl!=SEG_UNDEFZP) {
|
||||||
|
afl = SEG_UNDEF;
|
||||||
|
}
|
||||||
*label = cval(s+pp+1);
|
*label = cval(s+pp+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,7 +137,7 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
if(s[pp]==T_VALUE)
|
if(s[pp]==T_VALUE)
|
||||||
{
|
{
|
||||||
*v=lval(s+pp+1);
|
*v=lval(s+pp+1);
|
||||||
pp+=4;
|
pp+=5;
|
||||||
/* printf("value: v=%04x\n",*v); */
|
/* printf("value: v=%04x\n",*v); */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -143,7 +145,7 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
{
|
{
|
||||||
afl = s[pp+1];
|
afl = s[pp+1];
|
||||||
*v=cval(s+pp+2);
|
*v=cval(s+pp+2);
|
||||||
pp+=4;
|
pp+=6;
|
||||||
/* printf("pointer: v=%04x, afl=%04x\n",*v,afl); */
|
/* printf("pointer: v=%04x, afl=%04x\n",*v,afl); */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -159,7 +161,7 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
|
|
||||||
*v *= mf;
|
*v *= mf;
|
||||||
|
|
||||||
while(!er && s[pp]!=')' && s[pp]!=']' && s[pp]!=',' && s[pp]!=T_END)
|
while(!er && s[pp]!=')' && s[pp]!=']' && s[pp]!=',' && s[pp]!=T_END && s[pp]!=T_COMMENT)
|
||||||
{
|
{
|
||||||
er=get_op(s,&o);
|
er=get_op(s,&o);
|
||||||
|
|
||||||
@ -169,7 +171,7 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
if(!(er=ag_term(s,pr[o],&w, nafl, label)))
|
if(!(er=ag_term(s,pr[o],&w, nafl, label)))
|
||||||
{
|
{
|
||||||
if(afl || *nafl) { /* check pointer arithmetic */
|
if(afl || *nafl) { /* check pointer arithmetic */
|
||||||
if((afl == *nafl) && (afl!=SEG_UNDEF) && o==2) {
|
if((afl == *nafl) && (afl!=SEG_UNDEFZP) && (afl!=SEG_UNDEF) && o==2) {
|
||||||
afl = 0; /* substract two pointers */
|
afl = 0; /* substract two pointers */
|
||||||
} else
|
} else
|
||||||
if(((afl && !*nafl) || (*nafl && !afl)) && o==1) {
|
if(((afl && !*nafl) || (*nafl && !afl)) && o==1) {
|
||||||
@ -180,6 +182,8 @@ static int ag_term(signed char *s, int p, int *v, int *nafl, int *label)
|
|||||||
} else {
|
} else {
|
||||||
if(segment!=SEG_ABS) {
|
if(segment!=SEG_ABS) {
|
||||||
if(!dsb_len) {
|
if(!dsb_len) {
|
||||||
|
/*printf("ILLPOINTER=dsb_len=%d,segment=%d\n",dsb_len, segment);*/
|
||||||
|
/* e.g. adding two pointers, adding two undefined values */
|
||||||
er=E_ILLPOINTER;
|
er=E_ILLPOINTER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,10 +206,18 @@ static int get_op(signed char *s, int *o)
|
|||||||
|
|
||||||
*o=s[pp];
|
*o=s[pp];
|
||||||
|
|
||||||
if(*o<1 || *o>17)
|
if(*o<1 || *o>17) {
|
||||||
|
/*
|
||||||
|
printf("*o=%d, pp=%d, s=%s\n", *o, pp, s);
|
||||||
|
for (int i=0; i< 10; i++) {
|
||||||
|
printf(" %02x", s[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
er=E_SYNTAX;
|
er=E_SYNTAX;
|
||||||
else
|
} else {
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,12 @@
|
|||||||
|
|
||||||
#define cval(s) 256 * ((s)[1] & 255) + ((s)[0]&255)
|
#define cval(s) 256 * ((s)[1] & 255) + ((s)[0]&255)
|
||||||
#define lval(s) 65536 * ((s)[2] & 255) + 256 * ((s)[1] & 255) + ((s)[0] & 255)
|
#define lval(s) 65536 * ((s)[2] & 255) + 256 * ((s)[1] & 255) + ((s)[0] & 255)
|
||||||
#define wval(i, v) do { \
|
#define wval(i, v, f) do { \
|
||||||
t[i++] = T_VALUE; \
|
t[i++] = T_VALUE; \
|
||||||
t[i++] = v & 255; \
|
t[i++] = v & 255; \
|
||||||
t[i++] = (v >> 8) & 255; \
|
t[i++] = (v >> 8) & 255; \
|
||||||
t[i++] = (v >> 16) & 255; \
|
t[i++] = (v >> 16) & 255; \
|
||||||
|
t[i++] = f & 255; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* __XA65_XAD_H__ */
|
#endif /* __XA65_XAD_H__ */
|
||||||
|
90
xa/src/xah.h
90
xa/src/xah.h
@ -20,15 +20,29 @@
|
|||||||
#ifndef __XA65_XAH_H__
|
#ifndef __XA65_XAH_H__
|
||||||
#define __XA65_XAH_H__
|
#define __XA65_XAH_H__
|
||||||
|
|
||||||
#define ANZLAB 5000 /* mal 14 -> Byte */
|
/*
|
||||||
|
* Note: the computations to get the number of bytes necessary to allocate are
|
||||||
|
* a historic remnant of the Atari ST (the original platform) not being able to efficiently allocate small chunks
|
||||||
|
* of memory so I had to allocate a large chunk myself and manage the tables myself.
|
||||||
|
* This has changed and some parts of xa65 are modified to just do a malloc() now.
|
||||||
|
* These fixed numbers should actually go away. AF 20110623
|
||||||
|
*/
|
||||||
|
#define ANZLAB 5000 /* multiplied by sizeof(Labtab) -> Byte */
|
||||||
#define LABMEM 40000L
|
#define LABMEM 40000L
|
||||||
#define MAXLAB 32
|
#define MAXLAB 32
|
||||||
#define MAXBLK 16
|
#define MAXBLK 16
|
||||||
#define MAXFILE 7
|
#define MAXFILE 7
|
||||||
#define MAXLINE 2048
|
#define MAXLINE 2048
|
||||||
#define MAXPP 40000L
|
#define MAXPP 40000L
|
||||||
#define ANZDEF 2340 /* mal 14 -> Byte, ANZDEF * 14 < 32768 */
|
#define ANZDEF 2340 /* multiplied by sizeof(List) -> Byte, ANZDEF * 20 < 32768 */
|
||||||
#define TMPMEM 200000L /* Zwischenspeicher von Pass1 nach Pass 2 */
|
#define TMPMEM 2000000L /* temporary memory buffer from Pass1 to Pass 2 (includes all source, thus enlarged) */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STD = 0,
|
||||||
|
CHEAP = 1,
|
||||||
|
UNNAMED = 2,
|
||||||
|
UNNAMED_DEF = 3
|
||||||
|
} label_t;
|
||||||
|
|
||||||
typedef struct LabOcc {
|
typedef struct LabOcc {
|
||||||
struct LabOcc *next;
|
struct LabOcc *next;
|
||||||
@ -36,17 +50,27 @@ typedef struct LabOcc {
|
|||||||
char *fname;
|
char *fname;
|
||||||
} LabOcc;
|
} LabOcc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct that defines a label, after it has been parsed
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int blk;
|
int blk;
|
||||||
int val;
|
int val;
|
||||||
int len;
|
int len;
|
||||||
int fl; /* 0 = label value not valid/known,
|
int fl; /* 0 = label value not valid/known,
|
||||||
* 1 = label value known
|
* 1 = label value known
|
||||||
|
* 2 = label value not known, external global label (imported on link)
|
||||||
*/
|
*/
|
||||||
int afl; /* 0 = no address (no relocation), 1 = address label */
|
int afl; /* 0 = no address (no relocation), 1 = address label */
|
||||||
int nextindex;
|
int nextindex;
|
||||||
|
label_t is_cll; /* 0 is normal label, 1 is cheap local label (used for listing) */
|
||||||
char *n;
|
char *n;
|
||||||
struct LabOcc *occlist;
|
struct LabOcc *occlist;
|
||||||
|
// within a block, make a linked list for the unnamed label counting
|
||||||
|
// use indexes, as the label table can be re-alloced (so pointers change)
|
||||||
|
// -1 is the "undef'd" end of list
|
||||||
|
int blknext;
|
||||||
|
int blkprev;
|
||||||
} Labtab;
|
} Labtab;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -71,20 +95,20 @@ typedef struct {
|
|||||||
|
|
||||||
#define BUFSIZE 4096 /* File-Puffegroesse (wg Festplatte) */
|
#define BUFSIZE 4096 /* File-Puffegroesse (wg Festplatte) */
|
||||||
|
|
||||||
#define E_OK 0 /* Fehlernummern */
|
#define E_OK 0 /* No error */
|
||||||
#define E_SYNTAX -1 /* Syntax Fehler */
|
#define E_SYNTAX -1 /* Syntax error */
|
||||||
#define E_LABDEF -2 /* Label definiert */
|
#define E_LABDEF -2 /* Label already defined (duplicate label definition) */
|
||||||
#define E_NODEF -3 /* Label nicht definiert */
|
#define E_NODEF -3 /* Label not defined */
|
||||||
#define E_LABFULL -4 /* Labeltabelle voll */
|
#define E_LABFULL -4 /* Label table full */
|
||||||
#define E_LABEXP -5 /* Label erwartet */
|
#define E_LABEXP -5 /* Label expected but not found */
|
||||||
#define E_NOMEM -6 /* kein Speicher mehr */
|
#define E_NOMEM -6 /* out of memory */
|
||||||
#define E_ILLCODE -7 /* Illegaler Opcode */
|
#define E_ILLCODE -7 /* Illegal Opcode */
|
||||||
#define E_ADRESS -8 /* Illegale Adressierung */
|
#define E_ADRESS -8 /* Illegal Addressing mode */
|
||||||
#define E_RANGE -9 /* Branch out of range */
|
#define E_RANGE -9 /* Branch out of range */
|
||||||
#define E_OVERFLOW -10 /* Ueberlauf */
|
#define E_OVERFLOW -10 /* overflow */
|
||||||
#define E_DIV -11 /* Division durch Null */
|
#define E_DIV -11 /* Division by zero */
|
||||||
#define E_PSOEXP -12 /* Pseudo-Opcode erwartet */
|
#define E_PSOEXP -12 /* Pseudo-Opcode expected but not found */
|
||||||
#define E_BLKOVR -13 /* Block-Stack Uebergelaufen */
|
#define E_BLKOVR -13 /* Block-Stack overflow */
|
||||||
#define E_FNF -14 /* File not found (pp) */
|
#define E_FNF -14 /* File not found (pp) */
|
||||||
#define E_EOF -15 /* End of File */
|
#define E_EOF -15 /* End of File */
|
||||||
#define E_BLOCK -16 /* Block inkonsistent */
|
#define E_BLOCK -16 /* Block inkonsistent */
|
||||||
@ -126,18 +150,25 @@ typedef struct {
|
|||||||
#define W_OVER16M -74 /* included binary over 16M in 65816 mode */
|
#define W_OVER16M -74 /* included binary over 16M in 65816 mode */
|
||||||
/* warnings 75-77 are placeholders */
|
/* warnings 75-77 are placeholders */
|
||||||
|
|
||||||
#define T_VALUE -1
|
/* Meta-values for the token list. Note must not overlap with the
|
||||||
#define T_LABEL -2
|
* K* definitions in xat.c, which have outgrown the positive numbers
|
||||||
#define T_OP -3
|
* and are now growing up from -128 ... */
|
||||||
#define T_END -4
|
#define T_VALUE -1 /* following is a 24 bit value in the token list */
|
||||||
#define T_LINE -5
|
#define T_LABEL -2 /* referring to a label, following the token is the 16bit label number */
|
||||||
#define T_FILE -6
|
#define T_OP -3 /* label oriented operation; following is the label number (16bit), plus the operation char (e.g. '+') */
|
||||||
#define T_POINTER -7
|
#define T_END -4 /* end of line marker */
|
||||||
|
#define T_LINE -5 /* new line indicator; following is the 16 bit line number */
|
||||||
|
#define T_FILE -6 /* new file indicator; following is the 16 bit line number, then the file name (zero-term) */
|
||||||
|
#define T_POINTER -7 /* ??? */
|
||||||
|
#define T_COMMENT -8 /* unused */
|
||||||
|
#define T_DEFINE -9 /* define a label; inserted at conversion and discarded in pass1, only used in listing output */
|
||||||
|
#define T_LISTING -10 /* meta token, inserted after conversion before pass1, used after pass2 to create listing */
|
||||||
|
#define T_CAST -11 /* token inserted for a cast */
|
||||||
|
|
||||||
#define P_START 0 /* Prioritaeten fuer Arithmetik */
|
#define P_START 0 /* arithmetic operation priorities */
|
||||||
#define P_LOR 1 /* Von zwei Operationen wird immer */
|
#define P_LOR 1 /* of any two operations, the one with */
|
||||||
#define P_LAND 2 /* die mit der hoeheren Prioritaet */
|
#define P_LAND 2 /* the higher priority will be done first */
|
||||||
#define P_OR 3 /* zuerst ausgefuehrt */
|
#define P_OR 3
|
||||||
#define P_XOR 4
|
#define P_XOR 4
|
||||||
#define P_AND 5
|
#define P_AND 5
|
||||||
#define P_EQU 6
|
#define P_EQU 6
|
||||||
@ -168,6 +199,8 @@ typedef struct {
|
|||||||
#define SEG_ZERO 5
|
#define SEG_ZERO 5
|
||||||
#define SEG_MAX 6
|
#define SEG_MAX 6
|
||||||
|
|
||||||
|
#define SEG_UNDEFZP 7 /* is being mapped to UNDEF */
|
||||||
|
|
||||||
typedef struct Fopt {
|
typedef struct Fopt {
|
||||||
signed char *text; /* text after pass1 */
|
signed char *text; /* text after pass1 */
|
||||||
int len;
|
int len;
|
||||||
@ -188,8 +221,11 @@ typedef struct File {
|
|||||||
int base[SEG_MAX];
|
int base[SEG_MAX];
|
||||||
int len[SEG_MAX];
|
int len[SEG_MAX];
|
||||||
struct {
|
struct {
|
||||||
|
// temporary memory between pass1 and pass2
|
||||||
signed char *tmp;
|
signed char *tmp;
|
||||||
|
// write pointer
|
||||||
unsigned long tmpz;
|
unsigned long tmpz;
|
||||||
|
// read pointer
|
||||||
unsigned long tmpe;
|
unsigned long tmpe;
|
||||||
} mn;
|
} mn;
|
||||||
struct {
|
struct {
|
||||||
|
453
xa/src/xal.c
453
xa/src/xal.c
@ -48,7 +48,21 @@ static int b_fget(int*,int);
|
|||||||
static int b_ltest(int,int);
|
static int b_ltest(int,int);
|
||||||
static int b_get(int*);
|
static int b_get(int*);
|
||||||
static int b_test(int);
|
static int b_test(int);
|
||||||
static int ll_def(char *s, int *n, int b);
|
static int ll_def(char *s, int *n, int b, label_t ltype);
|
||||||
|
static int b_link(int);
|
||||||
|
|
||||||
|
static int b_new(void);
|
||||||
|
|
||||||
|
static void cll_init();
|
||||||
|
static int cll_get();
|
||||||
|
static void cll_clear();
|
||||||
|
static int cll_getcur();
|
||||||
|
|
||||||
|
/*
|
||||||
|
static void unn_init();
|
||||||
|
static int unn_get();
|
||||||
|
static void unn_clear();
|
||||||
|
*/
|
||||||
|
|
||||||
/* local variables */
|
/* local variables */
|
||||||
|
|
||||||
@ -69,6 +83,8 @@ static Labtab *ltp;
|
|||||||
|
|
||||||
int l_init(void)
|
int l_init(void)
|
||||||
{
|
{
|
||||||
|
cll_init();
|
||||||
|
//unn_init();
|
||||||
return 0;
|
return 0;
|
||||||
#if 0
|
#if 0
|
||||||
int er;
|
int er;
|
||||||
@ -139,69 +155,168 @@ FILE *fp;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************
|
||||||
|
* cheap local labels
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int cll_current = 0; /* the current cheap local labels block */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init the cheap local labels
|
||||||
|
*/
|
||||||
|
void cll_init() {
|
||||||
|
cll_current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the block number for a new cheap local label block
|
||||||
|
*/
|
||||||
|
int cll_get() {
|
||||||
|
if (cll_current == 0) {
|
||||||
|
cll_current = b_new();
|
||||||
|
}
|
||||||
|
return cll_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clear the local labels
|
||||||
|
*/
|
||||||
|
void cll_clear() {
|
||||||
|
cll_current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cll_getcur() {
|
||||||
|
return cll_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* define a global label (from the "-L" command line parameter)
|
||||||
|
*/
|
||||||
int lg_set(char *s ) {
|
int lg_set(char *s ) {
|
||||||
int n, er;
|
int n, er;
|
||||||
|
|
||||||
er = ll_search(s,&n);
|
er = ll_search(s,&n, STD);
|
||||||
|
|
||||||
if(er==E_OK) {
|
if(er==E_OK) {
|
||||||
fprintf(stderr,"Warning: global label doubly defined!\n");
|
fprintf(stderr,"Warning: global label doubly defined!\n");
|
||||||
} else {
|
} else {
|
||||||
if(!(er=ll_def(s,&n,0))) {
|
if(!(er=ll_def(s,&n,0, STD))) {
|
||||||
ltp=afile->la.lt+n;
|
return lg_import(n);
|
||||||
ltp->fl=2;
|
}
|
||||||
ltp->afl=SEG_UNDEF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return er;
|
return er;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* define a global label (from the .import pseudo opcode))
|
||||||
|
* "s" is a pointer to the first label character, end is at \0
|
||||||
|
* or at non-alphanumeric/_ char
|
||||||
|
*/
|
||||||
|
int lg_import(int n) {
|
||||||
|
int er=E_OK;
|
||||||
|
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
ltp->fl=2;
|
||||||
|
ltp->afl=SEG_UNDEF;
|
||||||
|
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* define a global zeropage label (from the .importzp pseudo opcode))
|
||||||
|
* "s" is a pointer to the first label character, end is at \0
|
||||||
|
* or at non-alphanumeric/_ char
|
||||||
|
*/
|
||||||
|
int lg_importzp(int n) {
|
||||||
|
int er=E_OK;
|
||||||
|
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
ltp->fl=2;
|
||||||
|
ltp->afl=SEG_UNDEFZP;
|
||||||
|
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************/
|
||||||
|
|
||||||
int l_def(char *s, int *l, int *x, int *f)
|
int l_def(char *s, int *l, int *x, int *f)
|
||||||
{
|
{
|
||||||
int n,er,b,i=0;
|
int n,er,b,i=0;
|
||||||
|
label_t cll_fl;
|
||||||
|
|
||||||
*f=0;
|
*f=0; /* flag (given as param) that the label is to be re-defined and the
|
||||||
b=0;
|
"label defined error" is to be skipped */
|
||||||
n=0;
|
b=0; /* block level on block stack, resp. block number */
|
||||||
|
n=0; /* flag, when set, b is absolute block number and not being translated */
|
||||||
|
cll_fl=STD; /* when 0, clear the cheap local label block */
|
||||||
|
|
||||||
|
if(s[0]==':') {
|
||||||
|
// ca65 unnamed label
|
||||||
|
i++;
|
||||||
|
//n++; /* block number b is absolute */
|
||||||
|
//b=unn_get(); /* current (possibly newly allocated) unnamed label block */
|
||||||
|
cll_fl = UNNAMED; // keep the cheap local label block
|
||||||
|
} else
|
||||||
if(s[0]=='-')
|
if(s[0]=='-')
|
||||||
{
|
{
|
||||||
*f+=1;
|
*f+=1; /* label is being redefined */
|
||||||
i++;
|
i++;
|
||||||
} else
|
} else
|
||||||
|
if(s[0]=='@')
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
n++; /* block number b is absolute */
|
||||||
|
b=cll_get(); /* current (possibly newly allocated) cheap label block */
|
||||||
|
cll_fl=CHEAP; /* do not clear the cll block again... */
|
||||||
|
} else
|
||||||
if(s[0]=='+')
|
if(s[0]=='+')
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
n++;
|
n++; /* block number b is absolute */
|
||||||
b=0;
|
b=0; /* global block number */
|
||||||
}
|
}
|
||||||
while(s[i]=='&')
|
while(s[i]=='&')
|
||||||
{
|
{
|
||||||
n=0;
|
if (n) b=0; /* reset block number */
|
||||||
|
n=0; /* block number is relative */
|
||||||
i++;
|
i++;
|
||||||
b++;
|
b++; /* one (more) level up the block stack */
|
||||||
}
|
}
|
||||||
if(!n)
|
if(!n) {
|
||||||
|
/* translate from block stack level to absolute block number */
|
||||||
b_fget(&b,b);
|
b_fget(&b,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cll_fl == STD) {
|
||||||
|
/* clear cheap local labels */
|
||||||
|
cll_clear();
|
||||||
|
}
|
||||||
|
|
||||||
if(!isalpha(s[i]) && s[i]!='_')
|
if((!isalpha(s[i])) && (s[i]!='_') && !(ca65 && ((cll_fl == UNNAMED) || isdigit(s[i])) ) ) {
|
||||||
|
//printf("SYNTAX cll_fl=%d, i=%d, s[i]=%02x (%c)\n", cll_fl, i, s[i], s[i]);
|
||||||
er=E_SYNTAX;
|
er=E_SYNTAX;
|
||||||
else
|
} else
|
||||||
{
|
{
|
||||||
er=ll_search(s+i,&n);
|
er = E_NODEF;
|
||||||
|
if (cll_fl != UNNAMED) {
|
||||||
|
er=ll_search(s+i,&n, cll_fl);
|
||||||
|
}
|
||||||
|
|
||||||
if(er==E_OK)
|
if(er==E_OK)
|
||||||
{
|
{
|
||||||
|
/* we actually found an existing label in the same scope */
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
|
|
||||||
if(*f)
|
if(*f)
|
||||||
{
|
{
|
||||||
|
/* redefinition of label */
|
||||||
*l=ltp->len+i;
|
*l=ltp->len+i;
|
||||||
} else
|
} else
|
||||||
if(ltp->fl==0)
|
if(ltp->fl==0)
|
||||||
{
|
{
|
||||||
|
/* label has not been defined yet, (e.g. pass1 forward ref), so we try to set it. */
|
||||||
*l=ltp->len+i;
|
*l=ltp->len+i;
|
||||||
if(b_ltest(ltp->blk,b))
|
if(b_ltest(ltp->blk,b))
|
||||||
er=E_LABDEF;
|
er=E_LABDEF;
|
||||||
@ -213,11 +328,13 @@ int l_def(char *s, int *l, int *x, int *f)
|
|||||||
} else
|
} else
|
||||||
if(er==E_NODEF)
|
if(er==E_NODEF)
|
||||||
{
|
{
|
||||||
if(!(er=ll_def(s+i,&n,b))) /* ll_def(...,*f) */
|
|
||||||
|
if(!(er=ll_def(s+i,&n,b, cll_fl) )) /* store the label in the table of labels */
|
||||||
{
|
{
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
*l=ltp->len+i;
|
*l=ltp->len+i;
|
||||||
ltp->fl=0;
|
ltp->fl=0;
|
||||||
|
ltp->is_cll=cll_fl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,15 +346,31 @@ int l_def(char *s, int *l, int *x, int *f)
|
|||||||
int l_search(char *s, int *l, int *x, int *v, int *afl)
|
int l_search(char *s, int *l, int *x, int *v, int *afl)
|
||||||
{
|
{
|
||||||
int n,er,b;
|
int n,er,b;
|
||||||
|
label_t cll_fl;
|
||||||
|
|
||||||
*afl=0;
|
*afl=0;
|
||||||
|
|
||||||
er=ll_search(s,&n);
|
/* check cheap local label */
|
||||||
/*printf("l_search: lab=%s(l=%d), afl=%d, er=%d, n=%d\n",s,*l, *afl,er,n);*/
|
cll_fl=STD;
|
||||||
|
if (s[0]=='@') {
|
||||||
|
cll_fl=CHEAP;
|
||||||
|
s++;
|
||||||
|
} else
|
||||||
|
if (s[0]==':') {
|
||||||
|
cll_fl = UNNAMED_DEF;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
er = E_NODEF;
|
||||||
|
if (cll_fl != UNNAMED_DEF) {
|
||||||
|
er=ll_search(s,&n, cll_fl);
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("l_search: lab=%s(afl=%d, er=%d, cll_fl=%d, cll_cur=%d)\n",s,*afl,er, cll_fl, cll_getcur());
|
||||||
if(er==E_OK)
|
if(er==E_OK)
|
||||||
{
|
{
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
*l=ltp->len;
|
*l=ltp->len + ((cll_fl == STD) ? 0 : 1);
|
||||||
if(ltp->fl == 1)
|
if(ltp->fl == 1)
|
||||||
{
|
{
|
||||||
l_get(n,v,afl);/* *v=lt[n].val;*/
|
l_get(n,v,afl);/* *v=lt[n].val;*/
|
||||||
@ -251,12 +384,22 @@ int l_search(char *s, int *l, int *x, int *v, int *afl)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b_get(&b);
|
if(cll_fl == CHEAP) {
|
||||||
er=ll_def(s,x,b); /* ll_def(...,*v); */
|
b=cll_get();
|
||||||
|
} else
|
||||||
|
if(cll_fl == UNNAMED_DEF) {
|
||||||
|
b_get(&b); // b=unn_get();
|
||||||
|
} else {
|
||||||
|
b_get(&b);
|
||||||
|
}
|
||||||
|
|
||||||
|
er=ll_def(s,x,b, cll_fl); /* ll_def(...,*v); */
|
||||||
|
|
||||||
ltp=afile->la.lt+(*x);
|
ltp=afile->la.lt+(*x);
|
||||||
|
ltp->is_cll = cll_fl;
|
||||||
|
|
||||||
*l=ltp->len;
|
*l=ltp->len + ((cll_fl == STD) ? 0 : 1);
|
||||||
|
//*l=ltp->len + cll_fl;
|
||||||
|
|
||||||
if(!er)
|
if(!er)
|
||||||
{
|
{
|
||||||
@ -303,11 +446,87 @@ void l_addocc(int n, int *v, int *afl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for the list functionality */
|
||||||
|
char *l_get_name(int n, label_t *is_cll) {
|
||||||
|
if (n > afile->la.ltm) {
|
||||||
|
fprintf(stderr, "Corrupted structures! n=%d, but max=%d\n", n, afile->la.ltm);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ltp=afile->la.lt+n;
|
||||||
|
*is_cll = ltp->is_cll;
|
||||||
|
return ltp->n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
nextp = -1;
|
||||||
|
if (c == '+') {
|
||||||
|
nextp = ltp->blknext;
|
||||||
|
} else
|
||||||
|
if (c == '-') {
|
||||||
|
nextp = ltp->blkprev;
|
||||||
|
}
|
||||||
|
//printf("::: nextp=%d\n", nextp);
|
||||||
|
if (nextp == -1) {
|
||||||
|
return -1; // E_NODEF
|
||||||
|
}
|
||||||
|
ltp = afile->la.lt+nextp;
|
||||||
|
//printf("::: leads to: %s, nextp=%d\n", ltp->n, nextp);
|
||||||
|
if (ltp->is_cll == UNNAMED) {
|
||||||
|
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)
|
int l_get(int n, int *v, int *afl)
|
||||||
{
|
{
|
||||||
if(crossref) l_addocc(n,v,afl);
|
if(crossref) l_addocc(n,v,afl);
|
||||||
|
|
||||||
ltp=afile->la.lt+n;
|
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;
|
(*v)=ltp->val;
|
||||||
lz=ltp->n;
|
lz=ltp->n;
|
||||||
*afl = ltp->afl;
|
*afl = ltp->afl;
|
||||||
@ -335,19 +554,23 @@ static void ll_exblk(int a, int b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ll_def(char *s, int *n, int b) /* definiert naechstes Label nr->n */
|
/* defines next label, returns new label number in out param n */
|
||||||
|
static int ll_def(char *s, int *n, int b, label_t ltype)
|
||||||
{
|
{
|
||||||
int j=0,er=E_NOMEM,hash;
|
int j=0,er=E_NOMEM,hash;
|
||||||
char *s2;
|
char *s2 = NULL;
|
||||||
|
|
||||||
/*printf("ll_def: s=%s\n",s); */
|
//printf("ll_def: s=%s, ltype=%d, no_name=%d\n",s, ltype, no_name);
|
||||||
|
|
||||||
|
// label table for the file ...
|
||||||
if(!afile->la.lt) {
|
if(!afile->la.lt) {
|
||||||
|
// ... does not exist yet, so malloc it
|
||||||
afile->la.lti = 0;
|
afile->la.lti = 0;
|
||||||
afile->la.ltm = 1000;
|
afile->la.ltm = 1000;
|
||||||
afile->la.lt = malloc(afile->la.ltm * sizeof(Labtab));
|
afile->la.lt = malloc(afile->la.ltm * sizeof(Labtab));
|
||||||
}
|
}
|
||||||
if(afile->la.lti>=afile->la.ltm) {
|
if(afile->la.lti>=afile->la.ltm) {
|
||||||
|
// ... or is at its capacity limit, so realloc it
|
||||||
afile->la.ltm *= 1.5;
|
afile->la.ltm *= 1.5;
|
||||||
afile->la.lt = realloc(afile->la.lt, afile->la.ltm * sizeof(Labtab));
|
afile->la.lt = realloc(afile->la.lt, afile->la.ltm * sizeof(Labtab));
|
||||||
}
|
}
|
||||||
@ -355,54 +578,66 @@ static int ll_def(char *s, int *n, int b) /* definiert naechstes Label
|
|||||||
fprintf(stderr, "Oops: no memory!\n");
|
fprintf(stderr, "Oops: no memory!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if((lti<ANZLAB) /*&&(lni<(long)(LABMEM-MAXLAB))*/)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
ltp=afile->la.lt+afile->la.lti;
|
|
||||||
/*
|
|
||||||
s2=ltp->n=ln+lni;
|
|
||||||
|
|
||||||
while((j<MAXLAB-1) && (s[j]!='\0') && (isalnum(s[j]) || s[j]=='_'))
|
// current pointer in label table
|
||||||
{
|
ltp = afile->la.lt + afile->la.lti;
|
||||||
s2[j]=s[j];
|
|
||||||
j++;
|
if (ltype != UNNAMED) {
|
||||||
}
|
// alloc space and copy over name
|
||||||
*/
|
if (ltype == UNNAMED_DEF) {
|
||||||
while((s[j]!='\0') && (isalnum(s[j]) || (s[j]=='_'))) j++;
|
// unnamed lables are like ":--" or ":+" with variable length
|
||||||
s2 = malloc(j+1);
|
while((s[j]!='\0') && (s[j]=='+' || s[j]=='-')) j++;
|
||||||
if(!s2) {
|
} else {
|
||||||
|
// standard (and cheap) labels are normal text
|
||||||
|
while((s[j]!='\0') && (isalnum(s[j]) || (s[j]=='_'))) j++;
|
||||||
|
}
|
||||||
|
s2 = malloc(j+1);
|
||||||
|
if(!s2) {
|
||||||
fprintf(stderr,"Oops: no memory!\n");
|
fprintf(stderr,"Oops: no memory!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
|
strncpy(s2,s,j);
|
||||||
|
s2[j]=0;
|
||||||
}
|
}
|
||||||
strncpy(s2,s,j);
|
|
||||||
s2[j]=0;
|
// init new entry in label table
|
||||||
/*
|
|
||||||
if(j<MAXLAB)
|
|
||||||
{
|
|
||||||
*/
|
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
ltp->len=j;
|
ltp->len=j; // length of label
|
||||||
ltp->n = s2;
|
ltp->n = s2; // name of label (char*)
|
||||||
ltp->blk=b;
|
ltp->blk=b; // block number
|
||||||
ltp->fl=0;
|
ltp->fl=0;
|
||||||
ltp->afl=0;
|
ltp->afl=0;
|
||||||
|
ltp->is_cll=ltype; // STD, CHEAP, or UNNAMED label
|
||||||
ltp->occlist=NULL;
|
ltp->occlist=NULL;
|
||||||
hash=hashcode(s,j);
|
hash=hashcode(s,j); // compute hashcode
|
||||||
ltp->nextindex=afile->la.hashindex[hash];
|
ltp->nextindex=afile->la.hashindex[hash]; // and link in before last entry with same hashcode
|
||||||
afile->la.hashindex[hash]=afile->la.lti;
|
afile->la.hashindex[hash]=afile->la.lti; // set as start of list for that hashcode
|
||||||
*n=afile->la.lti;
|
|
||||||
afile->la.lti++;
|
// TODO: does not work across files!
|
||||||
/* lni+=j+1;*/
|
ltp->blknext = -1; // no next block
|
||||||
/* }
|
ltp->blkprev = b_link( afile->la.lti ); // previous block, linked within block
|
||||||
}
|
|
||||||
*/
|
if (ltp->blkprev != -1) {
|
||||||
/*printf("ll_def return: %d\n",er);*/
|
ltp = afile->la.lt + ltp->blkprev;
|
||||||
|
ltp->blknext = afile->la.lti;
|
||||||
|
}
|
||||||
|
|
||||||
|
*n=afile->la.lti; // return the list index for that file in the out parameter n
|
||||||
|
afile->la.lti++; // increase last index in lable table
|
||||||
|
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
|
* search a label name in the label table. Return the label number
|
||||||
|
* in "n". Finds only labels that are in a block that is in the current
|
||||||
|
* set of blocks (in the block stack)
|
||||||
|
*
|
||||||
|
* If cll_fl is set, the label is also searched in the local cheap label scope
|
||||||
|
*
|
||||||
|
* Do not define the label (as is done in l_search()!)
|
||||||
|
*/
|
||||||
|
int ll_search(char *s, int *n, label_t cll_fl) /* search Label in Tabelle ,nr->n */
|
||||||
{
|
{
|
||||||
int i,j=0,k,er=E_NODEF,hash;
|
int i,j=0,k,er=E_NODEF,hash;
|
||||||
|
|
||||||
@ -411,7 +646,6 @@ int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
|
|||||||
hash=hashcode(s,j);
|
hash=hashcode(s,j);
|
||||||
i=afile->la.hashindex[hash];
|
i=afile->la.hashindex[hash];
|
||||||
|
|
||||||
/*printf("search?\n");*/
|
|
||||||
if(i>=afile->la.ltm) return E_NODEF;
|
if(i>=afile->la.ltm) return E_NODEF;
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -422,11 +656,24 @@ int ll_search(char *s, int *n) /* search Label in Tabelle ,nr->n */
|
|||||||
{
|
{
|
||||||
for (k=0;(k<j)&&(ltp->n[k]==s[k]);k++);
|
for (k=0;(k<j)&&(ltp->n[k]==s[k]);k++);
|
||||||
|
|
||||||
if((j==k)&&(!b_test(ltp->blk)))
|
if (cll_fl == CHEAP) {
|
||||||
{
|
if (ltp->blk == cll_getcur()) {
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
if (cll_fl == UNNAMED) {
|
||||||
|
// TODO
|
||||||
|
} else {
|
||||||
|
/* check if the found label is in any of the blocks in the
|
||||||
|
current block stack */
|
||||||
|
if((j==k)&&(!b_test(ltp->blk)))
|
||||||
|
{
|
||||||
|
/* ok, label found and it is reachable (its block nr is in the current block stack */
|
||||||
|
er=E_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!i)
|
if(!i)
|
||||||
@ -451,7 +698,7 @@ int ll_pdef(char *t)
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if(ll_search(t,&n)==E_OK)
|
if(ll_search(t,&n, STD)==E_OK)
|
||||||
{
|
{
|
||||||
ltp=afile->la.lt+n;
|
ltp=afile->la.lt+n;
|
||||||
if(ltp->fl)
|
if(ltp->fl)
|
||||||
@ -496,19 +743,39 @@ int l_write(FILE *fp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bt[MAXBLK];
|
/*******************************************************************************************
|
||||||
static int blk;
|
* block management code. Here the ".(" and ".)" blocks are maintained.
|
||||||
static int bi;
|
*
|
||||||
|
* Blocks are numbered uniquely, every time a new block is opened, the "blk" variable
|
||||||
|
* is increased and its number used as block number.
|
||||||
|
*
|
||||||
|
* The currently open blocks are maintained in a stack (bt[]). The lowest entry is the outermost
|
||||||
|
* block number, adding block numbers as blocks are opened. When a block is closed,
|
||||||
|
* the block stack is shortened again (bi has the length of the block stack)
|
||||||
|
*
|
||||||
|
* Methods exist to open new blocks, close a block, and do some checks, e.g. whether
|
||||||
|
* a specific block number is contained in the current block stack.
|
||||||
|
*/
|
||||||
|
static int bt[MAXBLK]; /* block stack */
|
||||||
|
static int labind; /* last allocated label, -1 none yet alloc'd - used for linking to find unnamed labels */
|
||||||
|
static int bi; /* length of the block stack (minus 1, i.e. bi[bi] has the innermost block) */
|
||||||
|
static int blk; /* current block number for allocation */
|
||||||
|
|
||||||
int b_init(void)
|
int b_init(void)
|
||||||
{
|
{
|
||||||
blk =0;
|
blk =0;
|
||||||
bi =0;
|
bi =0;
|
||||||
bt[bi]=blk;
|
bt[bi]=blk;
|
||||||
|
labind=-1;
|
||||||
|
|
||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int b_new(void)
|
||||||
|
{
|
||||||
|
return ++blk;
|
||||||
|
}
|
||||||
|
|
||||||
int b_depth(void)
|
int b_depth(void)
|
||||||
{
|
{
|
||||||
return bi;
|
return bi;
|
||||||
@ -519,19 +786,26 @@ int ga_blk(void)
|
|||||||
return(blk);
|
return(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* open a new block scope
|
||||||
|
*/
|
||||||
int b_open(void)
|
int b_open(void)
|
||||||
{
|
{
|
||||||
int er=E_BLKOVR;
|
int er=E_BLKOVR;
|
||||||
|
|
||||||
if(bi<MAXBLK-1)
|
if(bi<MAXBLK-1)
|
||||||
{
|
{
|
||||||
bt[++bi]=++blk;
|
bi++;
|
||||||
|
bt[bi]=b_new();
|
||||||
|
|
||||||
er=E_OK;
|
er=E_OK;
|
||||||
}
|
}
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* close a block scope
|
||||||
|
*/
|
||||||
int b_close(void)
|
int b_close(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -542,10 +816,14 @@ int b_close(void)
|
|||||||
} else {
|
} else {
|
||||||
return E_BLOCK;
|
return E_BLOCK;
|
||||||
}
|
}
|
||||||
|
cll_clear();
|
||||||
|
//unn_clear();
|
||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the block number of the current innermost block
|
||||||
|
*/
|
||||||
static int b_get(int *n)
|
static int b_get(int *n)
|
||||||
{
|
{
|
||||||
*n=bt[bi];
|
*n=bt[bi];
|
||||||
@ -553,6 +831,9 @@ static int b_get(int *n)
|
|||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the block number of the block "i" levels up in the current block stack
|
||||||
|
*/
|
||||||
static int b_fget(int *n, int i)
|
static int b_fget(int *n, int i)
|
||||||
{
|
{
|
||||||
if((bi-i)>=0)
|
if((bi-i)>=0)
|
||||||
@ -562,6 +843,10 @@ static int b_fget(int *n, int i)
|
|||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tests whether the given block number n is in the current stack of
|
||||||
|
* current block numbers bt[]
|
||||||
|
*/
|
||||||
static int b_test(int n)
|
static int b_test(int n)
|
||||||
{
|
{
|
||||||
int i=bi;
|
int i=bi;
|
||||||
@ -572,6 +857,9 @@ static int b_test(int n)
|
|||||||
return( i+1 ? E_OK : E_NOBLK );
|
return( i+1 ? E_OK : E_NOBLK );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tests whether the given block number "a" is in the
|
||||||
|
*/
|
||||||
static int b_ltest(int a, int b) /* testet ob bt^-1(b) in intervall [0,bt^-1(a)] */
|
static int b_ltest(int a, int b) /* testet ob bt^-1(b) in intervall [0,bt^-1(a)] */
|
||||||
{
|
{
|
||||||
int i=0,er=E_OK;
|
int i=0,er=E_OK;
|
||||||
@ -593,3 +881,10 @@ static int b_ltest(int a, int b) /* testet ob bt^-1(b) in intervall [0,bt^-1(
|
|||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int b_link(int newlab) {
|
||||||
|
int tmp = labind;
|
||||||
|
//printf("b_link: old was %d, set to %d\n", tmp, newlab);
|
||||||
|
labind = newlab;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
11
xa/src/xal.h
11
xa/src/xal.h
@ -21,8 +21,13 @@
|
|||||||
|
|
||||||
#include <stdio.h> /* for FILE */
|
#include <stdio.h> /* for FILE */
|
||||||
|
|
||||||
|
/* nasty stuff - "lz" is exported from xal.c so xa.c can print the name
|
||||||
|
* of the label that was last searched for in the error message that the
|
||||||
|
* label was not found...
|
||||||
|
*/
|
||||||
extern char *lz;
|
extern char *lz;
|
||||||
|
|
||||||
|
|
||||||
int l_init(void);
|
int l_init(void);
|
||||||
int ga_lab(void);
|
int ga_lab(void);
|
||||||
int gm_lab(void);
|
int gm_lab(void);
|
||||||
@ -30,6 +35,8 @@ long gm_labm(void);
|
|||||||
long ga_labm(void);
|
long ga_labm(void);
|
||||||
|
|
||||||
int lg_set(char *);
|
int lg_set(char *);
|
||||||
|
int lg_import(int);
|
||||||
|
int lg_importzp(int);
|
||||||
|
|
||||||
int b_init(void);
|
int b_init(void);
|
||||||
int b_depth(void);
|
int b_depth(void);
|
||||||
@ -40,9 +47,11 @@ int ga_blk(void);
|
|||||||
int l_def(char *s, int* l, int *x, int *f);
|
int l_def(char *s, int* l, int *x, int *f);
|
||||||
int l_search(char *s, int *l, int *x, int *v, int *afl);
|
int l_search(char *s, int *l, int *x, int *v, int *afl);
|
||||||
void l_set(int n, 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_get(int n, int *v, int *afl);
|
||||||
int l_vget(int n, int *v, char **s);
|
int l_vget(int n, int *v, char **s);
|
||||||
int ll_search(char *s, int *n);
|
int ll_search(char *s, int *n, label_t labeltype);
|
||||||
int ll_pdef(char *t);
|
int ll_pdef(char *t);
|
||||||
|
|
||||||
int b_open(void);
|
int b_open(void);
|
||||||
|
730
xa/src/xalisting.c
Normal file
730
xa/src/xalisting.c
Normal file
@ -0,0 +1,730 @@
|
|||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
* maintained by Cameron Kaiser
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* enable this to turn on (copious) optimization output */
|
||||||
|
/* #define DEBUG_AM */
|
||||||
|
#undef LISTING_DEBUG
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "xah.h"
|
||||||
|
#include "xal.h"
|
||||||
|
#include "xat.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
/* this is the listing code
|
||||||
|
*
|
||||||
|
* Unfortunately this code has to go here (for now), as this file is the only one
|
||||||
|
* where we have access to the tables that allow to convert the tokens back to
|
||||||
|
* a listing
|
||||||
|
*/
|
||||||
|
|
||||||
|
static FILE *listfp = NULL;
|
||||||
|
static int list_lineno = 1; /* current line number */
|
||||||
|
static int list_last_lineno = 0; /* current line number */
|
||||||
|
static char *list_filenamep = NULL; /* current file name pointer */
|
||||||
|
|
||||||
|
static int list_numbytes = 8;
|
||||||
|
|
||||||
|
static int list_string(char *buf, char *string);
|
||||||
|
static int list_tokens(char *buf, signed char *input, int len);
|
||||||
|
static int list_value(char *buf, int val, signed char format);
|
||||||
|
static int list_nchar(char *buf, signed char c, int n);
|
||||||
|
static int list_char(char *buf, signed char c);
|
||||||
|
static int list_sp(char *buf);
|
||||||
|
static int list_word(char *buf, int outword);
|
||||||
|
static int list_word_f(char *buf, int outword, signed char format);
|
||||||
|
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, "<");
|
||||||
|
q+=4;
|
||||||
|
p++;
|
||||||
|
} else
|
||||||
|
if (*p == '&') {
|
||||||
|
strcpy(q, "&");
|
||||||
|
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_flush() {
|
||||||
|
if (listfp != NULL) {
|
||||||
|
fflush(listfp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set line number for the coming listing output */
|
||||||
|
void list_line(int l) {
|
||||||
|
list_lineno = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set file name for the coming listing output */
|
||||||
|
void list_filename(char *fname) {
|
||||||
|
if (list_filenamep == NULL || (fname != NULL && strcmp(fname, list_filenamep) != 0)) {
|
||||||
|
list_filenamep = fname;
|
||||||
|
list_lineno = 1;
|
||||||
|
list_last_lineno = 0;
|
||||||
|
|
||||||
|
/* Hack */
|
||||||
|
if (listfp != NULL) {
|
||||||
|
fprintf(listfp, "\n%s\n\n", fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the output file descriptor where to write the listing
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
* bincode/bincode_len give the buffer address and length that contain the binary code
|
||||||
|
* that is produced from the token listing
|
||||||
|
*
|
||||||
|
* Note that both lengths may be zero
|
||||||
|
*/
|
||||||
|
void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len) {
|
||||||
|
|
||||||
|
int i, n_hexb;
|
||||||
|
|
||||||
|
char outline[MAXLINE];
|
||||||
|
char *buf = outline;
|
||||||
|
|
||||||
|
int lst_seg = listing[0];
|
||||||
|
int lst_pc = (listing[2]<<8) | (listing[1] & 255);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* do we need a separation line? */
|
||||||
|
if (list_lineno > list_last_lineno+1) {
|
||||||
|
/* yes */
|
||||||
|
/*fprintf(listfp, "line=%d, last=%d\n", list_lineno, list_last_lineno);*/
|
||||||
|
fprintf(listfp, "\n");
|
||||||
|
}
|
||||||
|
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
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
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 ( (i%16) == 15) {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef LISTING_DEBUG
|
||||||
|
/* for now only do a hex dump so we see what actually happens */
|
||||||
|
{
|
||||||
|
char valbuf[32];
|
||||||
|
i = buf - outline;
|
||||||
|
if (i<80) buf += list_nchar(buf, ' ', 80-i);
|
||||||
|
|
||||||
|
buf += list_string(buf, " >>");
|
||||||
|
sprintf(valbuf, "%p", listing+3);
|
||||||
|
buf += list_string(buf, valbuf);
|
||||||
|
buf += list_sp(buf);
|
||||||
|
for (i = 3; i < listing_len; i++) {
|
||||||
|
buf = buf + list_byte(buf, listing[i]);
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
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) {
|
||||||
|
int outp = 0;
|
||||||
|
int inp = 0;
|
||||||
|
int tmp;
|
||||||
|
char *name;
|
||||||
|
signed char c;
|
||||||
|
label_t is_cll;
|
||||||
|
int tabval;
|
||||||
|
signed char format;
|
||||||
|
|
||||||
|
if (inp >= len) return 0;
|
||||||
|
|
||||||
|
tmp = input[inp] & 255;
|
||||||
|
|
||||||
|
tabval = 0;
|
||||||
|
if (tmp == (T_DEFINE & 255)) {
|
||||||
|
while (inp < len && tmp == (T_DEFINE & 255)) {
|
||||||
|
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
|
||||||
|
if (is_cll == UNNAMED_DEF || is_cll == UNNAMED) {
|
||||||
|
outp += list_char(buf+outp, ':');
|
||||||
|
}
|
||||||
|
if (is_cll != UNNAMED) {
|
||||||
|
tmp = list_string(buf+outp, name);
|
||||||
|
tabval += tmp + 1 + is_cll;
|
||||||
|
outp += tmp;
|
||||||
|
}
|
||||||
|
outp += list_char(buf+outp, ' ');
|
||||||
|
inp += 3;
|
||||||
|
tmp = input[inp] & 255;
|
||||||
|
}
|
||||||
|
if (tabval < 10) {
|
||||||
|
outp += list_nchar(buf+outp, ' ', 10-tabval);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tmp >= 0 && tmp < number_of_valid_tokens) {
|
||||||
|
outp += list_string(buf+outp, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp >= 0 && tmp < number_of_valid_tokens) {
|
||||||
|
/* assembler keyword */
|
||||||
|
/*printf("tmp=%d, kt[tmp]=%p\n", tmp, kt[tmp]);*/
|
||||||
|
if (kt[tmp] != NULL) {
|
||||||
|
outp += list_string(buf+outp, kt[tmp]);
|
||||||
|
}
|
||||||
|
outp += list_sp(buf + outp);
|
||||||
|
inp += 1;
|
||||||
|
#if 0
|
||||||
|
if (tmp == Kinclude) {
|
||||||
|
/* just another exception from the rule... */
|
||||||
|
/* next char is terminator (", ') then the length and then the file name */
|
||||||
|
char term = input[inp];
|
||||||
|
int len = input[inp+1] & 255;
|
||||||
|
outp += list_char(buf+outp, term);
|
||||||
|
for (tmp = 2; tmp < len+2; tmp++) {
|
||||||
|
outp += list_char(buf+outp, input[inp+tmp]);
|
||||||
|
}
|
||||||
|
outp += list_char(buf+outp, term);
|
||||||
|
inp += len + 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
while (inp < len) {
|
||||||
|
int operator = 0;
|
||||||
|
|
||||||
|
switch(input[inp]) {
|
||||||
|
case T_CAST:
|
||||||
|
outp += list_string(buf+outp, formatp->escape_char(input[inp+1]));
|
||||||
|
inp+=2;
|
||||||
|
break;
|
||||||
|
case T_VALUE:
|
||||||
|
/*outp += list_char(buf+outp, 'V');*/
|
||||||
|
/* 24 bit value */
|
||||||
|
tmp = ((input[inp+3]&255)<<16) | ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
format = input[inp+4];
|
||||||
|
outp += list_value(buf+outp, tmp, format);
|
||||||
|
inp += 5;
|
||||||
|
operator = 1; /* check if arithmetic operator follows */
|
||||||
|
break;
|
||||||
|
case T_LABEL:
|
||||||
|
/*outp += list_char(buf+outp, 'L');*/
|
||||||
|
/* 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
|
||||||
|
if (is_cll == UNNAMED || is_cll == UNNAMED_DEF) {
|
||||||
|
outp += list_char(buf+outp, ':');
|
||||||
|
}
|
||||||
|
if (is_cll != UNNAMED) {
|
||||||
|
outp += list_string(buf+outp, name == NULL ? "<null>" : name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formatp->end_label != NULL) outp += formatp->end_label(buf+outp);
|
||||||
|
|
||||||
|
inp += 3;
|
||||||
|
operator = 1; /* check if arithmetic operator follows */
|
||||||
|
break;
|
||||||
|
case T_OP:
|
||||||
|
/* 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]);
|
||||||
|
inp += 4;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case T_END:
|
||||||
|
/* end of operation */
|
||||||
|
/*outp += list_string(buf+outp, ";");*/
|
||||||
|
inp += 1;
|
||||||
|
goto end;
|
||||||
|
break;
|
||||||
|
case T_COMMENT:
|
||||||
|
if (inp > 0 && inp < 20) {
|
||||||
|
outp += list_nchar(buf+outp, ' ', 20-inp);
|
||||||
|
}
|
||||||
|
tmp = ((input[inp+2]&255)<<8) | (input[inp+1]&255);
|
||||||
|
outp += list_char(buf+outp, ';');
|
||||||
|
outp += list_string(buf+outp, (char*)input+inp+3);
|
||||||
|
inp += tmp + 3;
|
||||||
|
break;
|
||||||
|
case T_LINE:
|
||||||
|
case T_FILE:
|
||||||
|
/* those two are meta-tokens, evaluated outside the t_p2 call,
|
||||||
|
* they result in calls to list_line(), list_filename() */
|
||||||
|
break;
|
||||||
|
case T_POINTER:
|
||||||
|
/* 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, '#');
|
||||||
|
tmp = ((input[inp+3]&255)<<8) | (input[inp+2]&255);
|
||||||
|
outp += list_value(buf+outp, tmp);
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
outp += list_string(buf+outp, formatp->escape_char(input[inp]));
|
||||||
|
} else {
|
||||||
|
outp += list_char(buf+outp, '\'');
|
||||||
|
outp += list_byte(buf+outp, input[inp]);
|
||||||
|
}
|
||||||
|
inp += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operator && inp < len) {
|
||||||
|
signed char op = input[inp];
|
||||||
|
if (op > 0 && op <= 17) {
|
||||||
|
outp += list_string(buf+outp, formatp->escape(arith_ops[op]));
|
||||||
|
inp += 1;
|
||||||
|
}
|
||||||
|
operator = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
return outp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_string(char *buf, char *string) {
|
||||||
|
if (buf == NULL || string == NULL) {
|
||||||
|
fprintf(stderr, "NULL pointer: buf=%p, string=%p\n", buf, string);
|
||||||
|
fflush(stderr);
|
||||||
|
//exit(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int p = 0;
|
||||||
|
while (string[p] != 0) {
|
||||||
|
buf[p] = string[p];
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_value(char *buf, int val, signed char format) {
|
||||||
|
int p = 0;
|
||||||
|
char valbuf[32];
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case '$':
|
||||||
|
p += list_char(buf + p, '$');
|
||||||
|
if (val & (255<<16)) {
|
||||||
|
p += list_byte(buf+p, val>>16);
|
||||||
|
p += list_word(buf+p, val);
|
||||||
|
} else
|
||||||
|
if (val & (255<<8)) {
|
||||||
|
p += list_word(buf+p, val);
|
||||||
|
} else {
|
||||||
|
p += list_byte(buf+p, val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
p += list_char(buf + p, '%');
|
||||||
|
if (val & (255<<16)) {
|
||||||
|
p += list_byte_f(buf+p, val>>16,'%');
|
||||||
|
p += list_word_f(buf+p, val,'%');
|
||||||
|
} else
|
||||||
|
if (val & (255<<8)) {
|
||||||
|
p += list_word_f(buf+p, val,'%');
|
||||||
|
} else {
|
||||||
|
p += list_byte_f(buf+p, val,'%');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
snprintf(valbuf, 32, "%o",val);
|
||||||
|
p+= list_char(buf+p, '&');
|
||||||
|
p+= list_string(buf+p, valbuf);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
snprintf(valbuf, 32, "%d",val);
|
||||||
|
p+= list_string(buf+p, valbuf);
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
case '"':
|
||||||
|
p+= list_char(buf+p, format);
|
||||||
|
p+= list_char(buf+p, val);
|
||||||
|
p+= list_char(buf+p, format);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* hex format as fallback */
|
||||||
|
p += list_char(buf + p, '$');
|
||||||
|
if (val & (255<<16)) {
|
||||||
|
p += list_byte(buf+p, val>>16);
|
||||||
|
p += list_word(buf+p, val);
|
||||||
|
} else
|
||||||
|
if (val & (255<<8)) {
|
||||||
|
p += list_word(buf+p, val);
|
||||||
|
} else {
|
||||||
|
p += list_byte(buf+p, val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_nchar(char *buf, signed char c, int n) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
buf[i]=c;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_char(char *buf, signed char c) {
|
||||||
|
buf[0] = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_sp(char *buf) {
|
||||||
|
buf[0] = ' ';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_word(char *buf, int outword) {
|
||||||
|
return list_word_f(buf, outword, '$');
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_word_f(char *buf, int outword, signed char format) {
|
||||||
|
int p = 0;
|
||||||
|
p+= list_byte_f(buf+p, outword >> 8, format);
|
||||||
|
p+= list_byte_f(buf+p, outword, format);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_byte(char *buf, int outbyte) {
|
||||||
|
return list_byte_f(buf, outbyte, '$');
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_byte_f(char *buf, int outbyte, signed char format) {
|
||||||
|
int p = 0;
|
||||||
|
p+= list_nibble_f(buf+p, (outbyte >> 4), format);
|
||||||
|
p+= list_nibble_f(buf+p, outbyte, format);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_nibble_f(char *buf, int outnib, signed char format) {
|
||||||
|
int p = 0;
|
||||||
|
outnib = outnib & 0xf;
|
||||||
|
switch(format) {
|
||||||
|
case '$':
|
||||||
|
if (outnib < 10) {
|
||||||
|
buf[p]='0'+outnib;
|
||||||
|
} else {
|
||||||
|
buf[p]='a'-10+outnib;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
buf[p++] = (outnib&8)?'1':'0';
|
||||||
|
buf[p++] = (outnib&4)?'1':'0';
|
||||||
|
buf[p++] = (outnib&2)?'1':'0';
|
||||||
|
buf[p++] = (outnib&1)?'1':'0';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* hex as default */
|
||||||
|
if (outnib < 10) {
|
||||||
|
buf[p]='0'+outnib;
|
||||||
|
} else {
|
||||||
|
buf[p]='a'-10+outnib;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
34
xa/src/xalisting.h
Normal file
34
xa/src/xalisting.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __XA65_XALISTING_H__
|
||||||
|
#define __XA65_XALISTING_H__
|
||||||
|
|
||||||
|
void list_start(char *formatname); //either NULL or "html"
|
||||||
|
void list_end();
|
||||||
|
|
||||||
|
void list_flush(); // debug helper
|
||||||
|
|
||||||
|
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__ */
|
@ -53,10 +53,13 @@ FILE *xfopen(const char *fn,const char *mode)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy to xname by replacing windows backslashes with the proper DIRCHAR
|
||||||
for(i=0;i<l+1;i++) {
|
for(i=0;i<l+1;i++) {
|
||||||
xname[i]=((fn[i]=='\\')?DIRCHAR:fn[i]);
|
xname[i]=((fn[i]=='\\')?DIRCHAR:fn[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("name=%s, xname=%s, mode=%s\n",fn,xname, mode);
|
||||||
|
|
||||||
if(mode[0]=='r')
|
if(mode[0]=='r')
|
||||||
{
|
{
|
||||||
if((file=fopen(fn,mode))==NULL
|
if((file=fopen(fn,mode))==NULL
|
||||||
@ -68,7 +71,6 @@ FILE *xfopen(const char *fn,const char *mode)
|
|||||||
strcpy(n2,n);
|
strcpy(n2,n);
|
||||||
strcat(n2,xname);
|
strcat(n2,xname);
|
||||||
strcat(n,fn);
|
strcat(n,fn);
|
||||||
/* printf("name=%s,n2=%s,mode=%s\n",n,n2,mode); */
|
|
||||||
file=fopen(n,mode);
|
file=fopen(n,mode);
|
||||||
if(!file) file=fopen(n2,mode);
|
if(!file) file=fopen(n2,mode);
|
||||||
}
|
}
|
||||||
@ -87,7 +89,6 @@ FILE *xfopen(const char *fn,const char *mode)
|
|||||||
strcpy(n2,n);
|
strcpy(n2,n);
|
||||||
strcat(n2,xname);
|
strcat(n2,xname);
|
||||||
strcat(n,fn);
|
strcat(n,fn);
|
||||||
/* printf("name=%s,n2=%s,mode=%s\n",n,n2,mode); */
|
|
||||||
file=fopen(n,mode);
|
file=fopen(n,mode);
|
||||||
if(!file) file=fopen(n2,mode);
|
if(!file) file=fopen(n2,mode);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ void o_write(FILE *fp) {
|
|||||||
l=afile->fo.olist[i].len;
|
l=afile->fo.olist[i].len;
|
||||||
t=afile->fo.olist[i].text;
|
t=afile->fo.olist[i].text;
|
||||||
/* do not optimize */
|
/* do not optimize */
|
||||||
t_p2(t, &l, 1, &afl);
|
t_p2_l(t, &l, &afl);
|
||||||
|
|
||||||
if(l>254) {
|
if(l>254) {
|
||||||
errout(E_OPTLEN);
|
errout(E_OPTLEN);
|
||||||
|
579
xa/src/xap.c
579
xa/src/xap.c
@ -40,7 +40,8 @@
|
|||||||
#include "xap.h"
|
#include "xap.h"
|
||||||
|
|
||||||
/* define this for recursive evaluation output */
|
/* define this for recursive evaluation output */
|
||||||
/* #define DEBUG_RECMAC */
|
#undef DEBUG_RECMAC
|
||||||
|
#undef DEBUG_REPLACE
|
||||||
|
|
||||||
char s[MAXLINE];
|
char s[MAXLINE];
|
||||||
Datei *filep;
|
Datei *filep;
|
||||||
@ -50,7 +51,8 @@ static int pp_replace(char*,char*,int,int);
|
|||||||
static int searchdef(char*);
|
static int searchdef(char*);
|
||||||
static int fgetline(char*,int len, int *rlen, FILE*);
|
static int fgetline(char*,int len, int *rlen, FILE*);
|
||||||
|
|
||||||
static int icl_open(char*),pp_ifdef(char*),pp_ifndef(char*);
|
/*static int icl_open(char*);*/
|
||||||
|
static int pp_ifdef(char*),pp_ifndef(char*);
|
||||||
static int pp_else(char*),pp_endif(char*);
|
static int pp_else(char*),pp_endif(char*);
|
||||||
static int pp_echo(char*),pp_if(char*),pp_print(char*),pp_prdef(char*);
|
static int pp_echo(char*),pp_if(char*),pp_print(char*),pp_prdef(char*);
|
||||||
static int pp_ifldef(char*),pp_iflused(char*);
|
static int pp_ifldef(char*),pp_iflused(char*);
|
||||||
@ -130,7 +132,7 @@ int pp_ifldef(char *t)
|
|||||||
int pp_iflused(char *t)
|
int pp_iflused(char *t)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
loopfl=(loopfl<<1)+( ll_search(t,&n) ? 1 : 0 );
|
loopfl=(loopfl<<1)+( ll_search(t,&n,STD) ? 1 : 0 );
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +355,10 @@ int pp_define(char *k)
|
|||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
liste[rl].p_anz++;
|
liste[rl].p_anz++;
|
||||||
for(j=0; t[i+j]!=')' && t[i+j]!=',' && t[i+j]!='\0';j++);
|
// skip whitespace before parameter name
|
||||||
|
while(isspace(t[i])) i++;
|
||||||
|
// find length
|
||||||
|
for(j=0; (!isspace(t[i+j])) && t[i+j]!=')' && t[i+j]!=',' && t[i+j]!='\0';j++);
|
||||||
if(j<memfre)
|
if(j<memfre)
|
||||||
{
|
{
|
||||||
strncpy(mem,t+i,j);
|
strncpy(mem,t+i,j);
|
||||||
@ -362,6 +367,8 @@ int pp_define(char *k)
|
|||||||
memfre-=j+1;
|
memfre-=j+1;
|
||||||
}
|
}
|
||||||
i+=j;
|
i+=j;
|
||||||
|
// skip trailing whitespace after parameter name
|
||||||
|
while(isspace(t[i])) i++;
|
||||||
}
|
}
|
||||||
if(t[i]==')')
|
if(t[i]==')')
|
||||||
i++;
|
i++;
|
||||||
@ -370,7 +377,7 @@ int pp_define(char *k)
|
|||||||
i++;
|
i++;
|
||||||
t+=i;
|
t+=i;
|
||||||
|
|
||||||
pp_replace(h,t,-1,0);
|
pp_replace(h,t,-1,rlist);
|
||||||
|
|
||||||
t=h;
|
t=h;
|
||||||
|
|
||||||
@ -433,78 +440,92 @@ int tcompare(char s[],char *v[], int n)
|
|||||||
return((i==n)? -1 : i);
|
return((i==n)? -1 : i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pp_replace(char *to, char *ti, int a,int b)
|
static int check_name(char *t, int n) {
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
{
|
||||||
|
char *x=liste[n].search;
|
||||||
|
while(t[i]==*x++ && t[i] && (isalnum(t[i]) || t[i]=='_'))
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_RECMAC
|
||||||
|
printf("check name with n=%d, name='%s' ->i=%d, len=%d\n", n, liste[n].search,i, liste[n].s_len);
|
||||||
|
#endif
|
||||||
|
return i == liste[n].s_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this is a break out of the original pp_replace code, as this code
|
||||||
|
* was basically duplicated for initial and recursive calls.
|
||||||
|
*/
|
||||||
|
static int pp_replace_part(char *to, char *t, int n, int sl, int recursive, int *l, int blist)
|
||||||
{
|
{
|
||||||
char *t=to,c,*x,*y,*mx,*rs;
|
int er = E_OK;
|
||||||
int i,l,n,sl,d,ld,er=E_OK,hkfl,klfl;
|
|
||||||
char fti[MAXLINE],fto[MAXLINE];
|
|
||||||
/*
|
|
||||||
int flag=!strncmp(ti,"TOUT",4);
|
|
||||||
if(flag) printf("flag=%d\n",flag);
|
|
||||||
*/
|
|
||||||
(void)strcpy(t,ti);
|
|
||||||
|
|
||||||
if(rlist)
|
// save mem, to restore it when we don't need the pseudo replacements anymore
|
||||||
{
|
// Note: in a real version, that should probably be a parameter, and not fiddling
|
||||||
while(t[0]!='\0')
|
// with global variables...
|
||||||
{
|
char *saved_mem = mem;
|
||||||
while(!isalpha(t[0]) && t[0]!='_')
|
|
||||||
if(t[0]=='\0')
|
|
||||||
break; /*return(E_OK);*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t++;
|
|
||||||
ti++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(l=0;isalnum(t[l])||t[l]=='_';l++);
|
#ifdef DEBUG_RECMAC
|
||||||
ld=l;
|
printf("replace part: n=%d, sl=%d, rec=%d, %s\n", n, sl, recursive, t);
|
||||||
/*
|
#endif
|
||||||
if(flag) printf("l=%d,a=%d,t=%s\n",l,a,t);
|
|
||||||
*/
|
|
||||||
if(a<0)
|
|
||||||
{
|
|
||||||
n=hashindex[hashcode(t,l)];
|
|
||||||
|
|
||||||
do
|
// yes, mark replacement string
|
||||||
{
|
char *rs=liste[n].replace;
|
||||||
sl=liste[n].s_len;
|
|
||||||
|
|
||||||
if(sl && (sl==l))
|
|
||||||
{
|
|
||||||
i=0;
|
|
||||||
x=liste[n].search;
|
|
||||||
while(t[i]==*x++ && t[i])
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if(i==sl)
|
|
||||||
{
|
|
||||||
rs=liste[n].replace;
|
|
||||||
|
|
||||||
|
// does it have parameters?
|
||||||
if(liste[n].p_anz)
|
if(liste[n].p_anz)
|
||||||
{
|
{
|
||||||
|
// yes, we have parameters, so we need to pp_replace them
|
||||||
|
// as well.
|
||||||
|
char fti[MAXLINE],fto[MAXLINE];
|
||||||
|
|
||||||
|
// copy replacement into temp buffer
|
||||||
(void)strcpy(fti,liste[n].replace);
|
(void)strcpy(fti,liste[n].replace);
|
||||||
|
|
||||||
if(rlist+liste[n].p_anz>=ANZDEF || memfre<MAXLINE*2)
|
// boundary checks ...
|
||||||
|
if(blist+liste[n].p_anz>=ANZDEF || memfre<MAXLINE*2)
|
||||||
er=E_NOMEM;
|
er=E_NOMEM;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
y=t+sl;
|
// ... passed
|
||||||
x=liste[n].search+sl+1;
|
// y points to the char behind the input name (i.e. the '(')
|
||||||
if(*y!='(')
|
char *y=t+sl;
|
||||||
|
// x points into the pp definition, with the parameter definition names
|
||||||
|
// following the definition name, separated by \0. Starts here behind the
|
||||||
|
// name - i.e. now points to the name of the first parameter
|
||||||
|
char *x=liste[n].search+sl+1;
|
||||||
|
// does the input actually have a '(' as parameter marker?
|
||||||
|
if(*y!='(') {
|
||||||
|
// no. Should probably get an own error (E_PARAMETER_EXPECTED)
|
||||||
er=E_SYNTAX;
|
er=E_SYNTAX;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mx=mem-1;
|
// mx now points to next free memory (mem current pointer in text table)
|
||||||
for(i=0;i<liste[n].p_anz;i++)
|
char *mx=mem-1;
|
||||||
|
// walk through the pp parameters
|
||||||
|
// by creating "fake" preprocessor definitions at the end
|
||||||
|
// of the current definition list, i.e. in liste[] after index
|
||||||
|
// rlist.
|
||||||
|
for(int i=0;i<liste[n].p_anz;i++)
|
||||||
{
|
{
|
||||||
liste[rlist+i].search=x;
|
// create new replacement entry
|
||||||
liste[rlist+i].s_len=(int)strlen(x);
|
liste[blist+i].search=x;
|
||||||
|
liste[blist+i].s_len=(int)strlen(x);
|
||||||
|
liste[blist+i].p_anz=0;
|
||||||
|
liste[blist+i].replace=mx+1;
|
||||||
|
// move x over to the next parameter name
|
||||||
x+=strlen(x)+1;
|
x+=strlen(x)+1;
|
||||||
liste[rlist+i].p_anz=0;
|
// points to first char of the parameter name in the input
|
||||||
liste[rlist+i].replace=mx+1;
|
// copy over first char into text memory (note that the position
|
||||||
c=*(++mx)=*(++y);
|
// is already stored in liste[].replace above)
|
||||||
hkfl=klfl=0;
|
char c=*(++mx)=*(++y);
|
||||||
|
int hkfl=0; // quote flag
|
||||||
|
int klfl=0; // brackets counter
|
||||||
|
// copy over the other characters
|
||||||
while(c!='\0'
|
while(c!='\0'
|
||||||
&& ((hkfl!=0
|
&& ((hkfl!=0
|
||||||
|| klfl!=0)
|
|| klfl!=0)
|
||||||
@ -524,64 +545,128 @@ int pp_replace(char *to, char *ti, int a,int b)
|
|||||||
}
|
}
|
||||||
c=*(++mx)=*(++y);
|
c=*(++mx)=*(++y);
|
||||||
}
|
}
|
||||||
|
// zero-terminate stored string
|
||||||
*mx='\0';
|
*mx='\0';
|
||||||
|
// if i is for the last parameter, then check if the
|
||||||
|
// last copied char was ')', otherwise it should be ','
|
||||||
|
// as separator for the next parameter
|
||||||
if(c!=((i==liste[n].p_anz-1) ? ')' : ','))
|
if(c!=((i==liste[n].p_anz-1) ? ')' : ','))
|
||||||
{
|
{
|
||||||
er=E_ANZPAR;
|
er=E_ANZPAR;
|
||||||
|
// note: this break only exits the innermost loop!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// at this point we have "augmented" the pp definitions
|
||||||
|
// with a list of new definitions for the macro parameters
|
||||||
|
// so that when pp_replace'ing them recursively the macro parameters
|
||||||
|
// will automatically be replaced.
|
||||||
|
|
||||||
|
// if we ran into an error, report so
|
||||||
|
if (er != E_OK) {
|
||||||
|
return (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let mx point to first free (and not last non-free) byte
|
||||||
|
mx++;
|
||||||
|
|
||||||
|
// before we use the parameter replacements, we need to
|
||||||
|
// recursively evaluate and replace them as well.
|
||||||
|
|
||||||
#ifdef DEBUG_RECMAC
|
#ifdef DEBUG_RECMAC
|
||||||
printf("replace:\n");
|
printf("replace (er=%d):\n", er);
|
||||||
printf("%s=%s\n",liste[n].search,liste[n].replace);
|
printf("%s=%s\n",liste[n].search,liste[n].replace);
|
||||||
#endif
|
#endif
|
||||||
for(i=0;i<liste[n].p_anz;i++) {
|
// loop over all arguments
|
||||||
|
for(int i=0;i<liste[n].p_anz;i++) {
|
||||||
/* recursively evaluate arguments */
|
/* recursively evaluate arguments */
|
||||||
char nfto[MAXLINE];
|
char nfto[MAXLINE];
|
||||||
char nfwas[MAXLINE];
|
char nfwas[MAXLINE];
|
||||||
int j = 0;
|
//int j = 0;
|
||||||
int k;
|
//int k = 0;
|
||||||
|
|
||||||
(void)strcpy(nfwas, liste[rlist+i].replace);
|
// copy over the replacement string into a buffer nfwas
|
||||||
if (!er)
|
(void)strcpy(nfwas, liste[blist+i].replace);
|
||||||
er=pp_replace(nfto,nfwas,-1,rlist);
|
if (!er) {
|
||||||
|
// replace the tokens in the parameter, adding possible pseudo params
|
||||||
|
// on top of the liste[] into nfto
|
||||||
|
er=pp_replace(nfto,nfwas,-1,blist+liste[n].p_anz);
|
||||||
|
}
|
||||||
#ifdef DEBUG_RECMAC
|
#ifdef DEBUG_RECMAC
|
||||||
printf("-%s=%s\n",liste[rlist+i].search,liste[rlist+i].replace);
|
printf("-%s=%s\n",liste[rlist+i].search,liste[rlist+i].replace);
|
||||||
printf("SUBB: -%s=%s\n", nfwas, nfto);
|
printf("SUBB: -%s=%s\n", nfwas, nfto);
|
||||||
#endif
|
#endif
|
||||||
|
#if 0
|
||||||
|
// as long as the strings don't match, loop...
|
||||||
while ((k = strcmp(nfto, nfwas))) {
|
while ((k = strcmp(nfto, nfwas))) {
|
||||||
|
// copy original from nfwas back to nfto
|
||||||
(void)strcpy(nfto, nfwas);
|
(void)strcpy(nfto, nfwas);
|
||||||
if (!er)
|
if (!er) {
|
||||||
|
// save-guard our replacement strings in global memory for the
|
||||||
|
// recursive pp_replace call. Note: is cleaned up after return,
|
||||||
|
// so need to restore mem only at the end of this function.
|
||||||
|
mem = mx;
|
||||||
|
// replace tokens
|
||||||
er=pp_replace(nfto,nfwas,-1,rlist);
|
er=pp_replace(nfto,nfwas,-1,rlist);
|
||||||
|
}
|
||||||
|
// and copy result into input buffer
|
||||||
(void)strcpy(nfwas, nfto);
|
(void)strcpy(nfwas, nfto);
|
||||||
#ifdef DEBUG_RECMAC
|
#ifdef DEBUG_RECMAC
|
||||||
printf("SUBB2 (%i): -%s=%s\n", k, liste[rlist+i].replace, nfto);
|
printf("SUBB2 (%i): -%s=%s\n", k, liste[rlist+i].replace, nfto);
|
||||||
#endif
|
#endif
|
||||||
if (++j>10)
|
if (++j>10) {
|
||||||
|
// we ran into 10 recursions deep - that does not look sound, bail out
|
||||||
errout(E_ORECMAC);
|
errout(E_ORECMAC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(void)strcpy(liste[rlist+i].replace, nfto);
|
#endif
|
||||||
|
// copy over the replacement string into free memory (using mx as pointer)
|
||||||
|
(void)strcpy(mx, nfto);
|
||||||
|
// replace the pointer to the (now obsolete) old replacement with the one we just created
|
||||||
|
// Note that due to the nature of the (more or less static) memory allocation, this is not
|
||||||
|
// being freed. Oh well...
|
||||||
|
liste[blist+i].replace = mx;
|
||||||
|
mx += strlen(mx)+1;
|
||||||
|
|
||||||
#ifdef DEBUG_RECMAC
|
#ifdef DEBUG_RECMAC
|
||||||
printf("FINAL: -%s=%s\n",liste[rlist+i].search,liste[rlist+i].replace);
|
printf("FINAL: -%s=%s\n",liste[rlist+i].search,liste[rlist+i].replace);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if(!er)
|
|
||||||
er=pp_replace(fto,fti,rlist,rlist+i);
|
if(!er) {
|
||||||
|
// safe-guard our memory allocations
|
||||||
|
mem = mx;
|
||||||
|
// only change (of two) from recursive: rlist is 0 there
|
||||||
|
#ifdef DEBUG_RECMAC
|
||||||
|
printf("replace macro: recursive=%d, blist=%d, -> b=%d\n", recursive, blist, blist+liste[n].p_anz);
|
||||||
|
printf(" from: %s\n", fti);
|
||||||
|
#endif
|
||||||
|
er=pp_replace(fto,fti,recursive ? 0 : blist,blist+liste[n].p_anz);
|
||||||
|
#ifdef DEBUG_RECMAC
|
||||||
|
printf(" to: %s\n", fto);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
/* if(flag) printf("sl=%d,",sl);*/
|
/* if(flag) printf("sl=%d,",sl);*/
|
||||||
sl=(int)((long)y+1L-(long)t);
|
sl=(int)((long)y+1L-(long)t);
|
||||||
/* if(flag) printf("sl=%d\n",sl);*/
|
/* if(flag) printf("sl=%d\n",sl);*/
|
||||||
rs=fto;
|
rs=fto;
|
||||||
/* printf("->%s\n",fto);*/
|
#ifdef DEBUG_RECMAC
|
||||||
|
printf("->%s\n",fto);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(er)
|
if(er) {
|
||||||
|
mem = saved_mem;
|
||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
} // end if(liste[n].p_anz), i.e. if it has parameters
|
||||||
|
|
||||||
d=(int)strlen(rs)-sl;
|
int d=(int)strlen(rs)-sl;
|
||||||
|
|
||||||
if(strlen(to)+d>=MAXLINE)
|
if(strlen(to)+d>=MAXLINE) {
|
||||||
|
mem = saved_mem;
|
||||||
return(E_NOMEM);
|
return(E_NOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(d<0)
|
if(d<0)
|
||||||
@ -596,129 +681,153 @@ int pp_replace(char *to, char *ti, int a,int b)
|
|||||||
t[ll+d]=t[ll];
|
t[ll+d]=t[ll];
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if(d)
|
if(d) {
|
||||||
(void)strcpy(t+sl+d,ti+sl);
|
// d can be positive or negative, so strcpy cannot be used, use memmove instead
|
||||||
|
(void)memmove(t+sl+d,t+sl, strlen(t) - sl + 1);
|
||||||
|
}
|
||||||
|
|
||||||
i=0;
|
int i=0;
|
||||||
while((c=rs[i]))
|
char c;
|
||||||
|
while((c=rs[i])) {
|
||||||
t[i++]=c;
|
t[i++]=c;
|
||||||
l=sl+d;/*=0;*/
|
}
|
||||||
break;
|
// other change from recursive. there sl is missing from add
|
||||||
}
|
//*l=(recursive ? 0 : sl) + d;/*=0;*/
|
||||||
|
*l=sl + d;/*=0;*/
|
||||||
|
|
||||||
|
mem = saved_mem;
|
||||||
|
|
||||||
|
return (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy the input string pointed to by ti into
|
||||||
|
* an output string buffer pointed to by to, replacing all
|
||||||
|
* preprocessor definitions in the process.
|
||||||
|
*
|
||||||
|
* Note: this method is called recursively, with "a" being -1
|
||||||
|
* when called from the "outside" respectively in a new context
|
||||||
|
* (like macro parameters)
|
||||||
|
*
|
||||||
|
* The "b" parameter denotes the index in the list from which on
|
||||||
|
* pseudo replacement entries are being created for replacement
|
||||||
|
* parameters
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int pp_replace(char *to, char *ti, int a,int b)
|
||||||
|
{
|
||||||
|
char *t=to;
|
||||||
|
int l,n,sl,er=E_OK;
|
||||||
|
int ld; // length of name/token to analyse
|
||||||
|
/*
|
||||||
|
int flag=!strncmp(ti,"TOUT",4);
|
||||||
|
if(flag) printf("flag=%d\n",flag);
|
||||||
|
*/
|
||||||
|
// t points to to, so copy input to output 1:1
|
||||||
|
// then below work on the copy in-place
|
||||||
|
(void)strcpy(t,ti);
|
||||||
|
|
||||||
|
// if there are replacements in the list of replacements
|
||||||
|
if(rlist)
|
||||||
|
{
|
||||||
|
// loop over the whole input
|
||||||
|
while(t[0]!='\0' && t[0] != ';')
|
||||||
|
{
|
||||||
|
// skip over the whitespace
|
||||||
|
// comment handling is NASTY NASTY NASTY
|
||||||
|
// but I currently don't see another way, as comments and colons
|
||||||
|
// can (and do) appear in preprocessor replacements
|
||||||
|
char quotefl = 0;
|
||||||
|
char commentfl = 0;
|
||||||
|
while((t[0] != 0) && (commentfl || ((!isalpha(t[0]) && t[0]!='_')))) {
|
||||||
|
if (t[0]=='\0') {
|
||||||
|
break; /*return(E_OK);*/
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (t[0] == ';' && !quotefl) {
|
||||||
|
commentfl = 1;
|
||||||
|
}
|
||||||
|
if (t[0] == ':' && !quotefl && !ca65 && !masm) {
|
||||||
|
// note that both ca65 and masm allow colons in comments
|
||||||
|
// so in these cases we cannot reset the comment handling here
|
||||||
|
commentfl = 0;
|
||||||
|
}
|
||||||
|
if (quotefl) {
|
||||||
|
// ignore other quotes within a quote
|
||||||
|
if (t[0] == quotefl) {
|
||||||
|
quotefl = 0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (t[0] == '"' || t[0] == '\'') {
|
||||||
|
quotefl = t[0];
|
||||||
|
}
|
||||||
|
t++;
|
||||||
|
ti++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine the length of the name
|
||||||
|
for(l=0;isalnum(t[l])||t[l]=='_';l++);
|
||||||
|
// store in ld
|
||||||
|
ld=l;
|
||||||
|
#ifdef DEBUG_RECMAC
|
||||||
|
printf("l=%d,a=%d,b=%d, t=%s\n",l,a, b ,t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the following if() is executed when being called from an
|
||||||
|
// 'external' context, i.e. not from a recursion
|
||||||
|
if(a<0)
|
||||||
|
{
|
||||||
|
// when called from an external context, not by recursion
|
||||||
|
|
||||||
|
// compute hashcode for the name for the search index entry (liste[n])
|
||||||
|
n=hashindex[hashcode(t,l)];
|
||||||
|
|
||||||
|
// loop over all entries in linked list for hash code (think: hash collisions)
|
||||||
|
do // while(1);
|
||||||
|
{
|
||||||
|
// length of name of pp definition
|
||||||
|
sl=liste[n].s_len;
|
||||||
|
|
||||||
|
// does pp definition match what we have found?
|
||||||
|
if(sl && (sl==l) && check_name(t, n))
|
||||||
|
{
|
||||||
|
er = pp_replace_part(to, t, n, sl, 0, &l, b);
|
||||||
|
if (er != E_OK) {
|
||||||
|
return er;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(!n)
|
if(!n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// next index in linked list for given hash code
|
||||||
n=liste[n].nextindex;
|
n=liste[n].nextindex;
|
||||||
|
|
||||||
} while(1);
|
} while(1);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
// called when in recursive call
|
||||||
|
// loop over all the replacement entries from the given b down to 0
|
||||||
|
// that allows to replace the parameters first (as they were added at
|
||||||
|
// the end of the list)
|
||||||
for(n=b-1;n>=a;n--)
|
for(n=b-1;n>=a;n--)
|
||||||
{
|
{
|
||||||
sl=liste[n].s_len;
|
sl=liste[n].s_len;
|
||||||
|
|
||||||
if(sl && (sl==l))
|
if(sl && (sl==l) && check_name(t, n))
|
||||||
{
|
{
|
||||||
i=0;
|
er = pp_replace_part(to, t, n, sl, 1, &l, b);
|
||||||
x=liste[n].search;
|
break;
|
||||||
while(t[i]==*x++ && t[i])
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if(i==sl)
|
|
||||||
{
|
|
||||||
rs=liste[n].replace;
|
|
||||||
if(liste[n].p_anz)
|
|
||||||
{
|
|
||||||
(void)strcpy(fti,liste[n].replace);
|
|
||||||
if(rlist+liste[n].p_anz>=ANZDEF || memfre<MAXLINE*2)
|
|
||||||
er=E_NOMEM;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
y=t+sl;
|
|
||||||
x=liste[n].search+sl+1;
|
|
||||||
if(*y!='(')
|
|
||||||
er=E_SYNTAX;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mx=mem-1;
|
|
||||||
for(i=0;i<liste[n].p_anz;i++)
|
|
||||||
{
|
|
||||||
liste[rlist+i].search=x;
|
|
||||||
liste[rlist+i].s_len=strlen(x);
|
|
||||||
x+=strlen(x)+1;
|
|
||||||
liste[rlist+i].p_anz=0;
|
|
||||||
liste[rlist+i].replace=mx+1;
|
|
||||||
c=*(++mx)=*(++y);
|
|
||||||
hkfl=klfl=0;
|
|
||||||
while(c!='\0'
|
|
||||||
&& ((hkfl!=0
|
|
||||||
|| klfl!=0)
|
|
||||||
|| (c!=','
|
|
||||||
&& c!=')')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if(c=='\"')
|
|
||||||
hkfl=hkfl^1;
|
|
||||||
if(!hkfl)
|
|
||||||
{
|
|
||||||
if(c=='(')
|
|
||||||
klfl++;
|
|
||||||
if(c==')')
|
|
||||||
klfl--;
|
|
||||||
}
|
|
||||||
c=*(++mx)=*(++y);
|
|
||||||
}
|
|
||||||
*mx='\0';
|
|
||||||
if(c!=((i==liste[n].p_anz-1) ? ')' : ','))
|
|
||||||
{
|
|
||||||
er=E_ANZPAR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!er)
|
|
||||||
er=pp_replace(fto,fti,0,rlist+i);
|
|
||||||
sl=(int)((long)y+1L-(long)t);
|
|
||||||
rs=fto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(er)
|
|
||||||
return(er);
|
|
||||||
}
|
|
||||||
d=(int)strlen(rs)-sl;
|
|
||||||
|
|
||||||
if(strlen(to)+d>=MAXLINE)
|
|
||||||
return(E_NOMEM);
|
|
||||||
/*
|
|
||||||
if(d<0)
|
|
||||||
{
|
|
||||||
y=t+sl+d;
|
|
||||||
x=t+sl;
|
|
||||||
while(*y++=*x++);
|
|
||||||
}
|
|
||||||
if(d>0)
|
|
||||||
{
|
|
||||||
for(ll=strlen(t);ll>=sl;ll--)
|
|
||||||
t[ll+d]=t[ll];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if(d)
|
|
||||||
(void)strcpy(t+sl+d,ti+sl);
|
|
||||||
|
|
||||||
i=0;
|
|
||||||
while((c=rs[i]))
|
|
||||||
t[i++]=c;
|
|
||||||
l+=d;/*0;*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// advance input by length of name
|
||||||
ti+=ld;
|
ti+=ld;
|
||||||
|
// advance output by l
|
||||||
t+=l;
|
t+=l;
|
||||||
}
|
} /* end while(t[0] != 0) */
|
||||||
}
|
} /* end if(rlist) */
|
||||||
return(E_OK);
|
return(E_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,14 +861,16 @@ int pp_open(char *name)
|
|||||||
|
|
||||||
fp=xfopen(name,"r");
|
fp=xfopen(name,"r");
|
||||||
|
|
||||||
|
int l = strlen(name);
|
||||||
|
|
||||||
/* we have to alloc it dynamically to make the name survive another
|
/* we have to alloc it dynamically to make the name survive another
|
||||||
pp_open - it's used in the cross-reference list */
|
pp_open - it's used in the cross-reference list */
|
||||||
flist[0].fname = malloc(strlen(name)+1);
|
flist[0].fname = malloc(l+1);
|
||||||
if(!flist[0].fname) {
|
if(!flist[0].fname) {
|
||||||
fprintf(stderr,"Oops, no more memory!\n");
|
fprintf(stderr,"Oops, no more memory!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
(void)strcpy(flist[0].fname,name);
|
(void)strncpy(flist[0].fname,name,l+1);
|
||||||
flist[0].fline=0;
|
flist[0].fline=0;
|
||||||
flist[0].bdepth=b_depth();
|
flist[0].bdepth=b_depth();
|
||||||
flist[0].filep=fp;
|
flist[0].filep=fp;
|
||||||
@ -826,14 +937,17 @@ int icl_open(char *tt)
|
|||||||
|
|
||||||
fsp++;
|
fsp++;
|
||||||
|
|
||||||
|
char *namep = s+i;
|
||||||
|
int len = strlen(namep);
|
||||||
|
|
||||||
/* we have to alloc it dynamically to make the name survive another
|
/* we have to alloc it dynamically to make the name survive another
|
||||||
pp_open - it's used in the cross-reference list */
|
pp_open - it's used in the cross-reference list */
|
||||||
flist[fsp].fname = malloc(strlen(s+i)+1);
|
flist[fsp].fname = malloc(len+1);
|
||||||
if(!flist[fsp].fname) {
|
if(!flist[fsp].fname) {
|
||||||
fprintf(stderr,"Oops, no more memory!\n");
|
fprintf(stderr,"Oops, no more memory!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
strcpy(flist[fsp].fname,s+i);
|
strncpy(flist[fsp].fname,namep, len+1);
|
||||||
flist[fsp].fline=0;
|
flist[fsp].fline=0;
|
||||||
flist[fsp].bdepth=b_depth();
|
flist[fsp].bdepth=b_depth();
|
||||||
flist[fsp].flinep=NULL;
|
flist[fsp].flinep=NULL;
|
||||||
@ -843,6 +957,51 @@ int icl_open(char *tt)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parses the current line for double-slash comments,
|
||||||
|
* handling single- and double-quotes appropriately
|
||||||
|
* shortens the line if a comment is found, returns
|
||||||
|
* the new line length.
|
||||||
|
*/
|
||||||
|
int double_slash_comments(char *line) {
|
||||||
|
int p = 0;
|
||||||
|
int qfl = 0; // if set, contains the current quote char (others are then ignored)
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (line[p] != 0) {
|
||||||
|
c = line[p];
|
||||||
|
if (c == qfl) {
|
||||||
|
// always in quote, c==0 not possible due to loop condition
|
||||||
|
// found matching quote char, so end of quote
|
||||||
|
qfl = 0;
|
||||||
|
} else
|
||||||
|
if ((c == '\'' || c == '"') && !qfl) {
|
||||||
|
// not in quote, but finding quote char
|
||||||
|
qfl = c;
|
||||||
|
}
|
||||||
|
if (c == '^' && qfl) {
|
||||||
|
// xa65 escape character in strings (quoted)
|
||||||
|
if (line[p+1] != 0) {
|
||||||
|
// skip the next char in test
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == '/' && !qfl) {
|
||||||
|
// found '/' outside quote
|
||||||
|
if (line[p+1] == '/') {
|
||||||
|
// gotcha
|
||||||
|
//printf("shorten at %d: %s\n", p, line);
|
||||||
|
// shorten line
|
||||||
|
line[p] = 0;
|
||||||
|
// return new length
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
int pgetline(char *t)
|
int pgetline(char *t)
|
||||||
{
|
{
|
||||||
int c,er=E_OK;
|
int c,er=E_OK;
|
||||||
@ -854,15 +1013,25 @@ int pgetline(char *t)
|
|||||||
filep =flist+fsp;
|
filep =flist+fsp;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
c=fgetline(in_line, MAXLINE, &rlen, flist[fsp].filep);
|
int is_continuation = 0;
|
||||||
/* continuation lines */
|
tlen = 0; // start of current line in in_line[]
|
||||||
tlen = rlen;
|
do {
|
||||||
while(c=='\n' && tlen && in_line[tlen-1]=='\\') {
|
c=fgetline(in_line + tlen, MAXLINE, &rlen, flist[fsp].filep);
|
||||||
c=fgetline(in_line + tlen-1, MAXLINE-tlen, &rlen, flist[fsp].filep);
|
|
||||||
tlen += rlen-1;
|
/* check for continuation lines */
|
||||||
|
is_continuation = ((c == '\n') && (rlen > 0) && (in_line[tlen + rlen - 1]=='\\'));
|
||||||
|
if (is_continuation) {
|
||||||
|
// cut off the continuation character
|
||||||
|
rlen--;
|
||||||
|
in_line[tlen + rlen] = 0;
|
||||||
}
|
}
|
||||||
if(in_line[0]=='#' || in_line[0] == altppchar)
|
rlen = double_slash_comments(in_line + tlen);
|
||||||
{
|
|
||||||
|
tlen += rlen;
|
||||||
|
} while (is_continuation);
|
||||||
|
|
||||||
|
if(in_line[0]=='#' || in_line[0] == altppchar)
|
||||||
|
{
|
||||||
if (in_line[1]==' ') { /* cpp comment -- pp_comand doesn't
|
if (in_line[1]==' ') { /* cpp comment -- pp_comand doesn't
|
||||||
handle this right */
|
handle this right */
|
||||||
er=pp_cpp(in_line+1);
|
er=pp_cpp(in_line+1);
|
||||||
@ -876,10 +1045,10 @@ int pgetline(char *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
er=1;
|
er=1;
|
||||||
|
|
||||||
if(c==EOF) {
|
if(c==EOF) {
|
||||||
if (loopfl && fsp) {
|
if (loopfl && fsp) {
|
||||||
char bletch[MAXLINE];
|
char bletch[MAXLINE];
|
||||||
sprintf(bletch,
|
sprintf(bletch,
|
||||||
@ -896,22 +1065,21 @@ int pgetline(char *t)
|
|||||||
errout(E_OPENPP);
|
errout(E_OPENPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle the double-slash comment (like in C++) */
|
|
||||||
p = strchr(in_line, '/');
|
|
||||||
if (p != NULL) {
|
|
||||||
if (p[1] == '/') {
|
|
||||||
*p = 0; /* terminate string */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!er || loopfl) {
|
if(!er || loopfl) {
|
||||||
in_line[0]='\0';
|
in_line[0]='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
er= (er==1) ? E_OK : er ;
|
er= (er==1) ? E_OK : er ;
|
||||||
|
|
||||||
if(!er)
|
if(!er) {
|
||||||
|
#ifdef DEBUG_REPLACE
|
||||||
|
// printf("<<<: %s\n", in_line);
|
||||||
|
#endif
|
||||||
er=pp_replace(t,in_line,-1,rlist);
|
er=pp_replace(t,in_line,-1,rlist);
|
||||||
|
#ifdef DEBUG_REPLACE
|
||||||
|
printf(">>>: %s\n", t);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if(!er && nff)
|
if(!er && nff)
|
||||||
er=E_NEWFILE;
|
er=E_NEWFILE;
|
||||||
@ -929,7 +1097,7 @@ int pgetline(char *t)
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
/* this is the most disgusting code I have ever written, but Andre drove me
|
/* this is the most disgusting code I have ever written, but Andre drove me
|
||||||
to it because I can't think of any other F$%Y#*U(%&Y##^#KING way to fix the
|
to it because I can't think of any other way to fix the
|
||||||
last line bug ... a very irritated Cameron */
|
last line bug ... a very irritated Cameron */
|
||||||
|
|
||||||
/* however, it also solved the problem of open #ifdefs not bugging out */
|
/* however, it also solved the problem of open #ifdefs not bugging out */
|
||||||
@ -996,6 +1164,11 @@ int rgetc(FILE *fp)
|
|||||||
return(c-'\t'?c:' ');
|
return(c-'\t'?c:' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that the line returned is always zero-terminated,
|
||||||
|
* the rlen out parameter is just convenience, so that
|
||||||
|
* a further strlen() can be saved
|
||||||
|
*/
|
||||||
int fgetline(char *t, int len, int *rlen, FILE *fp)
|
int fgetline(char *t, int len, int *rlen, FILE *fp)
|
||||||
{
|
{
|
||||||
static int c,i;
|
static int c,i;
|
||||||
|
@ -30,6 +30,9 @@ void pp_end(void);
|
|||||||
int pgetline(char *t);
|
int pgetline(char *t);
|
||||||
Datei *pp_getidat(void);
|
Datei *pp_getidat(void);
|
||||||
|
|
||||||
|
/* needed for .include pseudo opcode */
|
||||||
|
int icl_open(char*);
|
||||||
|
|
||||||
int ga_pp(void);
|
int ga_pp(void);
|
||||||
int gm_pp(void);
|
int gm_pp(void);
|
||||||
long gm_ppm(void);
|
long gm_ppm(void);
|
||||||
|
22
xa/src/xar.c
22
xa/src/xar.c
@ -34,18 +34,22 @@ File *afile = NULL;
|
|||||||
|
|
||||||
int rmode = RMODE_RELOC;
|
int rmode = RMODE_RELOC;
|
||||||
|
|
||||||
|
/*
|
||||||
int r_set(int pc, int afl, int l) {
|
int r_set(int pc, int afl, int l) {
|
||||||
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d\n",pc, l, afl,segment);*/
|
|
||||||
if(segment==SEG_TEXT) return rt_set(pc,afl,l,0);
|
if(segment==SEG_TEXT) return rt_set(pc,afl,l,0);
|
||||||
if(segment==SEG_DATA) return rd_set(pc,afl,l,0);
|
if(segment==SEG_DATA) return rd_set(pc,afl,l,0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
int u_set(int pc, int afl, int label, int l) {
|
int u_set(int pc, int afl, int label, int l) {
|
||||||
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d, label=%d\n",
|
/*printf("set relocation @$%04x, l=%d, afl=%04x, segment=%d, label=%d\n",
|
||||||
pc, l, afl,segment, label);*/
|
pc, l, afl,segment, label);*/
|
||||||
if((afl & A_FMASK) == (SEG_UNDEF<<8))
|
if(((afl & A_FMASK) == (SEG_UNDEF<<8))
|
||||||
|
|| ((afl & A_FMASK) == (SEG_UNDEFZP<<8))
|
||||||
|
) {
|
||||||
label = u_label(label); /* set label as undefined */
|
label = u_label(label); /* set label as undefined */
|
||||||
|
}
|
||||||
if(segment==SEG_TEXT) return rt_set(pc,afl,l,label);
|
if(segment==SEG_TEXT) return rt_set(pc,afl,l,label);
|
||||||
if(segment==SEG_DATA) return rd_set(pc,afl,l,label);
|
if(segment==SEG_DATA) return rd_set(pc,afl,l,label);
|
||||||
return 0;
|
return 0;
|
||||||
@ -77,7 +81,9 @@ int rt_set(int pc, int afl, int l, int lab) {
|
|||||||
/*printf("Warning: byte relocation in word value at PC=$%04x!\n",pc);*/
|
/*printf("Warning: byte relocation in word value at PC=$%04x!\n",pc);*/
|
||||||
}
|
}
|
||||||
if(l==1 && ((afl&A_MASK)==A_ADR)) {
|
if(l==1 && ((afl&A_MASK)==A_ADR)) {
|
||||||
if((afl & A_FMASK) != (SEG_ZERO<<8)) {
|
if(((afl & A_FMASK) != (SEG_ZERO<<8))
|
||||||
|
&& ((afl & A_FMASK) != (SEG_UNDEFZP<<8))
|
||||||
|
) {
|
||||||
/*printf("afl=%04x\n",afl);*/
|
/*printf("afl=%04x\n",afl);*/
|
||||||
errout(W_ADRRELOC);
|
errout(W_ADRRELOC);
|
||||||
}
|
}
|
||||||
@ -147,10 +153,16 @@ int rt_write(FILE *fp, int pc) {
|
|||||||
}
|
}
|
||||||
fputc(pc2-pc, fp);
|
fputc(pc2-pc, fp);
|
||||||
pc=pc2;
|
pc=pc2;
|
||||||
fputc((afl>>8)&255, fp);
|
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEFZP<<8)) {
|
||||||
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
fputc( (((afl & ~A_FMASK)>>8)&255)|SEG_UNDEF, fp);
|
||||||
|
fputc(afile->rt.rlist[p].lab & 255, fp);
|
||||||
|
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
||||||
|
} else {
|
||||||
|
fputc( (afl>>8)&255, fp);
|
||||||
|
if((afile->rt.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
||||||
fputc(afile->rt.rlist[p].lab & 255, fp);
|
fputc(afile->rt.rlist[p].lab & 255, fp);
|
||||||
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
fputc((afile->rt.rlist[p].lab>>8) & 255, fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
extern File *alloc_file(void);
|
extern File *alloc_file(void);
|
||||||
|
|
||||||
/* jumps to r[td]_set, depending on segment */
|
/* jumps to r[td]_set, depending on segment */
|
||||||
int r_set(int pc, int reloc, int len);
|
/*int r_set(int pc, int reloc, int len);*/
|
||||||
int u_set(int pc, int reloc, int label, int len);
|
int u_set(int pc, int reloc, int label, int len);
|
||||||
|
|
||||||
int rt_set(int pc, int reloc, int len, int label);
|
int rt_set(int pc, int reloc, int len, int label);
|
||||||
|
@ -111,11 +111,17 @@ int rd_write(FILE *fp, int pc) {
|
|||||||
}
|
}
|
||||||
fputc(pc2-pc, fp);
|
fputc(pc2-pc, fp);
|
||||||
pc=pc2;
|
pc=pc2;
|
||||||
fputc((afl>>8)&255, fp);
|
if((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEFZP<<8)) {
|
||||||
if((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8)) {
|
fputc((((afl & ~A_FMASK)>>8)&255)|SEG_UNDEF, fp);
|
||||||
|
fputc(afile->rd.rlist[p].lab & 255, fp);
|
||||||
|
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
||||||
|
} else {
|
||||||
|
fputc((afl>>8)&255, fp);
|
||||||
|
if(((afile->rd.rlist[p].afl&A_FMASK)==(SEG_UNDEF<<8))) {
|
||||||
fputc(afile->rd.rlist[p].lab & 255, fp);
|
fputc(afile->rd.rlist[p].lab & 255, fp);
|
||||||
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
fputc((afile->rd.rlist[p].lab>>8) & 255, fp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
if((afl&A_MASK)==A_HIGH) fputc(afl&255,fp);
|
||||||
}
|
}
|
||||||
p=afile->rd.rlist[p].next;
|
p=afile->rd.rlist[p].next;
|
||||||
|
765
xa/src/xat.c
765
xa/src/xat.c
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,11 @@
|
|||||||
extern int dsb_len;
|
extern int dsb_len;
|
||||||
|
|
||||||
int t_p1(signed char *s, signed char *t, int *ll, int *al);
|
int t_p1(signed char *s, signed char *t, int *ll, int *al);
|
||||||
int t_p2(signed char *t, int *ll, int fl, int *al);
|
int t_p2_l(signed char *t, int *ll, int *al);
|
||||||
int b_term(char *s, int *v, int *l, int pc);
|
int b_term(char *s, int *v, int *l, int pc);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
#endif /* __XA65_XAT_H__ */
|
#endif /* __XA65_XAT_H__ */
|
||||||
|
7
xa/tests/Makefile
Normal file
7
xa/tests/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
TESTS=adrm binclude chardelimiter charset comcom fordef incerr
|
||||||
|
|
||||||
|
tests:
|
||||||
|
for i in $(TESTS); do (cd $$i; make tests); done
|
||||||
|
|
||||||
|
|
@ -27,6 +27,8 @@ incerr/ 1) .xl/.al should error without -w 2) error should be in
|
|||||||
binclude/ Binary include code with some weird casing
|
binclude/ Binary include code with some weird casing
|
||||||
chppch/ Changing preprocessor characters (-p)
|
chppch/ Changing preprocessor characters (-p)
|
||||||
charset/ Tests of when charsets should be honoured and when not
|
charset/ Tests of when charsets should be honoured and when not
|
||||||
|
cc65/ Compatibility tests for ca65 compatibility
|
||||||
|
relmode/ tests concerning switches between segments and absolute mode
|
||||||
|
|
||||||
Cameron Kaiser, André Fachat
|
Cameron Kaiser, André Fachat
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
# xa should not allow this to happen. if it does, this test is no good.
|
# xa should not allow this to happen. if it does, this test is no good.
|
||||||
../../xa 816.asm || exit 0 && exit 1
|
../../xa 816.asm || exit 0 && exit 1
|
||||||
@ -18,3 +19,7 @@ default:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
|
|
||||||
|
tests:
|
||||||
|
./runtest.sh -q -C
|
||||||
|
|
||||||
|
BIN
xa/tests/adrm/a.out-02
Normal file
BIN
xa/tests/adrm/a.out-02
Normal file
Binary file not shown.
BIN
xa/tests/adrm/a.out-c02
Normal file
BIN
xa/tests/adrm/a.out-c02
Normal file
Binary file not shown.
BIN
xa/tests/adrm/a.out-zab
Normal file
BIN
xa/tests/adrm/a.out-zab
Normal file
Binary file not shown.
BIN
xa/tests/adrm/a.out-zab2
Normal file
BIN
xa/tests/adrm/a.out-zab2
Normal file
Binary file not shown.
BIN
xa/tests/adrm/a.out-zpa
Normal file
BIN
xa/tests/adrm/a.out-zpa
Normal file
Binary file not shown.
BIN
xa/tests/adrm/a.out-zpa2
Normal file
BIN
xa/tests/adrm/a.out-zpa2
Normal file
Binary file not shown.
28
xa/tests/adrm/bip2.inc
Normal file
28
xa/tests/adrm/bip2.inc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
- tbasic.0.asm: if you make vecwri absolute with !, then the branch gets
|
||||||
|
generated as if it were NOT absolute. works okay without it (and
|
||||||
|
gets a warning)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
test lda !$0095
|
||||||
|
bne test
|
||||||
|
|
||||||
|
ldx #13
|
||||||
|
lup0 lda !vecwri,x
|
||||||
|
sta $2005,x
|
||||||
|
dex
|
||||||
|
bne lup0
|
||||||
|
lda #$00
|
||||||
|
sta $0020
|
||||||
|
lda #$02
|
||||||
|
sta $0021
|
||||||
|
lda #$ff
|
||||||
|
sta $0022
|
||||||
|
lda #$13
|
||||||
|
sta $0023
|
||||||
|
jmp $2003
|
||||||
|
|
||||||
|
vectors .byt $4c, $5a, $1e, $4c, $a0, $1e, $4c, $00, $01
|
||||||
|
vecwri = vectors - 1
|
35
xa/tests/adrm/runtest.sh
Executable file
35
xa/tests/adrm/runtest.sh
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run a test script
|
||||||
|
|
||||||
|
#THISDIR=`dirname $0`
|
||||||
|
THISDIR=`pwd`
|
||||||
|
|
||||||
|
#echo "0=$0"
|
||||||
|
#echo "THISDIR=$THISDIR"
|
||||||
|
|
||||||
|
declare -A opts
|
||||||
|
#opts=([816.asm]="-w")
|
||||||
|
opts[02.asm]="-C"
|
||||||
|
opts[816.asm]="-w"
|
||||||
|
opts[zab.asm]="-w"
|
||||||
|
opts[zpa.asm]="-w"
|
||||||
|
|
||||||
|
#ASMFLAGS=-v
|
||||||
|
ASMFLAGS=
|
||||||
|
|
||||||
|
# exclude filter from *.asm if no explicit file is given
|
||||||
|
EXCLUDE=
|
||||||
|
|
||||||
|
# test files used
|
||||||
|
TESTFILES="bip.inc bip2.inc"
|
||||||
|
|
||||||
|
# files to compare afterwards, against <file>-<script>
|
||||||
|
COMPAREFILES=a.out
|
||||||
|
|
||||||
|
XA=$THISDIR/../../xa
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# actual code
|
||||||
|
. ../func.sh
|
||||||
|
|
4
xa/tests/adrm/zab2.asm
Normal file
4
xa/tests/adrm/zab2.asm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.word $4000
|
||||||
|
* = $4000
|
||||||
|
|
||||||
|
#include "bip2.inc"
|
4
xa/tests/adrm/zpa2.asm
Normal file
4
xa/tests/adrm/zpa2.asm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.word $0000
|
||||||
|
* = $0000
|
||||||
|
|
||||||
|
#include "bip2.inc"
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
../../xa test.asm -o test.o
|
../../xa test.asm -o test.o
|
||||||
../hextool -cmp=test.ok < test.o
|
../hextool -cmp=test.ok < test.o
|
||||||
@ -10,3 +11,5 @@ default:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
|
|
||||||
|
|
||||||
|
34
xa/tests/ca65/Makefile
Normal file
34
xa/tests/ca65/Makefile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# Makefile for tests
|
||||||
|
#
|
||||||
|
|
||||||
|
XA=../../xa
|
||||||
|
|
||||||
|
CA65=ca65
|
||||||
|
LD65=ld65
|
||||||
|
|
||||||
|
tests: unnamed1 unnamed2 escape1 escape2 clean
|
||||||
|
|
||||||
|
|
||||||
|
unnamed1: unnamed1.a65
|
||||||
|
#${CA65} $<; ${LD65} -t none -o unnamed1.ca65 unnamed1.o; rm unnamed1.o
|
||||||
|
${XA} -XCA65 $<
|
||||||
|
cmp unnamed1.ca65 a.o65
|
||||||
|
|
||||||
|
unnamed2: unnamed2.a65
|
||||||
|
#${CA65} $<; ${LD65} -t none -o unnamed2.ca65 unnamed2.o; rm unnamed2.o
|
||||||
|
${XA} -XCA65 $< 2>a.err || true
|
||||||
|
cmp unnamed2.ca65 a.o65
|
||||||
|
|
||||||
|
escape1: escape1.a65
|
||||||
|
${XA} $<
|
||||||
|
cmp escape1.out a.o65
|
||||||
|
|
||||||
|
escape2: escape2.a65
|
||||||
|
#${CA65} $<; ${LD65} -t none -o escape2.ca65 escape2.o; rm escape2.o
|
||||||
|
${XA} -XCA65 $< 2>a.err || true
|
||||||
|
cmp escape2.ca65 a.o65
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f a.err a.o65
|
||||||
|
|
6
xa/tests/ca65/escape1.a65
Normal file
6
xa/tests/ca65/escape1.a65
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
*=$1000
|
||||||
|
|
||||||
|
lda #"^^"
|
||||||
|
|
||||||
|
|
1
xa/tests/ca65/escape1.out
Normal file
1
xa/tests/ca65/escape1.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
ゥ^
|
6
xa/tests/ca65/escape2.a65
Normal file
6
xa/tests/ca65/escape2.a65
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
.org $1000
|
||||||
|
|
||||||
|
lda #'^'
|
||||||
|
|
||||||
|
|
1
xa/tests/ca65/escape2.ca65
Normal file
1
xa/tests/ca65/escape2.ca65
Normal file
@ -0,0 +1 @@
|
|||||||
|
ゥ^
|
15
xa/tests/ca65/unnamed1.a65
Normal file
15
xa/tests/ca65/unnamed1.a65
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
; test of unnamed labels
|
||||||
|
|
||||||
|
start: .org $4000
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
: iny ; first
|
||||||
|
bne :- ; go to first
|
||||||
|
beq :++ ; go to third
|
||||||
|
: ; second
|
||||||
|
jmp :- ; go to second
|
||||||
|
jmp :++
|
||||||
|
: ldy #1 ; third
|
||||||
|
: nop
|
||||||
|
|
BIN
xa/tests/ca65/unnamed1.ca65
Normal file
BIN
xa/tests/ca65/unnamed1.ca65
Normal file
Binary file not shown.
17
xa/tests/ca65/unnamed2.a65
Normal file
17
xa/tests/ca65/unnamed2.a65
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
; test of unnamed labels
|
||||||
|
|
||||||
|
start: .org $4000
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
: iny ; first
|
||||||
|
bne :- ; go to first
|
||||||
|
beq :++ ; go to third
|
||||||
|
.scope
|
||||||
|
: ; second
|
||||||
|
jmp :- ; go to second
|
||||||
|
jmp :++
|
||||||
|
: ldy #1 ; third
|
||||||
|
.endscope
|
||||||
|
: nop
|
||||||
|
|
BIN
xa/tests/ca65/unnamed2.ca65
Normal file
BIN
xa/tests/ca65/unnamed2.ca65
Normal file
Binary file not shown.
3
xa/tests/ca65/unnamed2.err
Normal file
3
xa/tests/ca65/unnamed2.err
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
unnamed2.a65:line 9: 4007:Label '(null)' not defined
|
||||||
|
unnamed2.a65:line 13: 400e:Label '(null)' not defined
|
||||||
|
Break after 2 errors
|
5
xa/tests/chardelimiter/Makefile
Normal file
5
xa/tests/chardelimiter/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
tests:
|
||||||
|
./runtest.sh -q -C
|
||||||
|
|
||||||
|
|
32
xa/tests/chardelimiter/runtest.sh
Executable file
32
xa/tests/chardelimiter/runtest.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run a test script
|
||||||
|
|
||||||
|
#THISDIR=`dirname $0`
|
||||||
|
THISDIR=`pwd`
|
||||||
|
|
||||||
|
#echo "0=$0"
|
||||||
|
#echo "THISDIR=$THISDIR"
|
||||||
|
|
||||||
|
#declare -A opts
|
||||||
|
#opts=([816.asm]="-w")
|
||||||
|
#opts[02.asm]="-C"
|
||||||
|
|
||||||
|
#ASMFLAGS=-v
|
||||||
|
ASMFLAGS=
|
||||||
|
|
||||||
|
# exclude filter from *.asm if no explicit file is given
|
||||||
|
EXCLUDE=
|
||||||
|
|
||||||
|
# test files used
|
||||||
|
TESTFILES=""
|
||||||
|
|
||||||
|
# files to compare afterwards, against <file>-<script>
|
||||||
|
COMPAREFILES=a.out
|
||||||
|
|
||||||
|
XA=$THISDIR/../../xa
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# actual code
|
||||||
|
. ../func.sh
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
../../xa test.s
|
../../xa test.s
|
||||||
../hextool -cmp=no-charset.o < a.o65
|
../hextool -cmp=no-charset.o < a.o65
|
||||||
@ -10,3 +11,7 @@ default:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf a.o65
|
rm -rf a.o65
|
||||||
|
|
||||||
|
tests:
|
||||||
|
./runtest.sh -q -C
|
||||||
|
|
||||||
|
BIN
xa/tests/charset/a.out-test
Normal file
BIN
xa/tests/charset/a.out-test
Normal file
Binary file not shown.
32
xa/tests/charset/runtest.sh
Executable file
32
xa/tests/charset/runtest.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run a test script
|
||||||
|
|
||||||
|
#THISDIR=`dirname $0`
|
||||||
|
THISDIR=`pwd`
|
||||||
|
|
||||||
|
#echo "0=$0"
|
||||||
|
#echo "THISDIR=$THISDIR"
|
||||||
|
|
||||||
|
declare -A opts
|
||||||
|
#opts=([816.asm]="-w")
|
||||||
|
opts[testpet.asm]="-OPETSCII"
|
||||||
|
|
||||||
|
#ASMFLAGS=-v
|
||||||
|
ASMFLAGS=
|
||||||
|
|
||||||
|
# exclude filter from *.asm if no explicit file is given
|
||||||
|
EXCLUDE=
|
||||||
|
|
||||||
|
# test files used
|
||||||
|
TESTFILES="README.1st test2.s"
|
||||||
|
|
||||||
|
# files to compare afterwards, against <file>-<script>
|
||||||
|
COMPAREFILES=a.out
|
||||||
|
|
||||||
|
XA=$THISDIR/../../xa
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# actual code
|
||||||
|
. ../func.sh
|
||||||
|
|
16
xa/tests/charset/testpet.asm
Normal file
16
xa/tests/charset/testpet.asm
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.word $9000
|
||||||
|
* = $9000
|
||||||
|
|
||||||
|
w = 10
|
||||||
|
.bin 0,10+w,"README.1st"
|
||||||
|
.bin 0,10,"README.1st"
|
||||||
|
#include "test2.s"
|
||||||
|
.byt "FooBar"
|
||||||
|
.aasc "FooBar"
|
||||||
|
.asc "FooBar",65,97,10
|
||||||
|
.aasc "FooBar"
|
||||||
|
.bin 0,10,"README.1st"
|
||||||
|
.aasc "Barfoo",65,97,10
|
||||||
|
|
||||||
|
lda #'A'
|
||||||
|
lda #"A"
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
# this should fail.
|
# this should fail.
|
||||||
../../xa scomcom.asm || exit 0 && exit 1
|
../../xa scomcom.asm || exit 0 && exit 1
|
||||||
@ -12,3 +13,7 @@ default:
|
|||||||
clean:
|
clean:
|
||||||
rm -f a.o65
|
rm -f a.o65
|
||||||
|
|
||||||
|
tests:
|
||||||
|
./runtest.sh -q -C
|
||||||
|
|
||||||
|
|
||||||
|
BIN
xa/tests/comcom/a.out-comcom
Normal file
BIN
xa/tests/comcom/a.out-comcom
Normal file
Binary file not shown.
1
xa/tests/comcom/a.out-scomcom
Normal file
1
xa/tests/comcom/a.out-scomcom
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><01>
|
1
xa/tests/comcom/comcom2.asm
Symbolic link
1
xa/tests/comcom/comcom2.asm
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
comcom.asm
|
33
xa/tests/comcom/runtest.sh
Executable file
33
xa/tests/comcom/runtest.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run a test script
|
||||||
|
|
||||||
|
#THISDIR=`dirname $0`
|
||||||
|
THISDIR=`pwd`
|
||||||
|
|
||||||
|
#echo "0=$0"
|
||||||
|
#echo "THISDIR=$THISDIR"
|
||||||
|
|
||||||
|
declare -A opts
|
||||||
|
#opts=([816.asm]="-w")
|
||||||
|
opts[comcom2.asm]="-M"
|
||||||
|
opts[scomcom.asm]="-M"
|
||||||
|
|
||||||
|
#ASMFLAGS=-v
|
||||||
|
ASMFLAGS=
|
||||||
|
|
||||||
|
# exclude filter from *.asm if no explicit file is given
|
||||||
|
EXCLUDE=
|
||||||
|
|
||||||
|
# test files used
|
||||||
|
TESTFILES=""
|
||||||
|
|
||||||
|
# files to compare afterwards, against <file>-<script>
|
||||||
|
COMPAREFILES=a.out
|
||||||
|
|
||||||
|
XA=$THISDIR/../../xa
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# actual code
|
||||||
|
. ../func.sh
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
# this must not pass.
|
# this must not pass.
|
||||||
../../xa -DFAIL test3.asm || exit 0 && exit 1
|
../../xa -DFAIL test3.asm || exit 0 && exit 1
|
||||||
@ -12,3 +13,6 @@ default:
|
|||||||
clean:
|
clean:
|
||||||
rm -f a.o65 test.out
|
rm -f a.o65 test.out
|
||||||
|
|
||||||
|
tests:
|
||||||
|
./runtest.sh -q -C
|
||||||
|
|
||||||
|
Binary file not shown.
34
xa/tests/fordef/runtest.sh
Executable file
34
xa/tests/fordef/runtest.sh
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run a test script
|
||||||
|
|
||||||
|
#THISDIR=`dirname $0`
|
||||||
|
THISDIR=`pwd`
|
||||||
|
|
||||||
|
#echo "0=$0"
|
||||||
|
#echo "THISDIR=$THISDIR"
|
||||||
|
|
||||||
|
declare -A opts
|
||||||
|
#opts=([816.asm]="-w")
|
||||||
|
#opts[02.asm]="-C"
|
||||||
|
declare -A errs
|
||||||
|
errs[test4.asm]=1
|
||||||
|
|
||||||
|
#ASMFLAGS=-v
|
||||||
|
ASMFLAGS=
|
||||||
|
|
||||||
|
# exclude filter from *.asm if no explicit file is given
|
||||||
|
EXCLUDE=
|
||||||
|
|
||||||
|
# test files used
|
||||||
|
TESTFILES="test2.s"
|
||||||
|
|
||||||
|
# files to compare afterwards, against <file>-<script>
|
||||||
|
COMPAREFILES="a.out test.asm.err test4.asm.err"
|
||||||
|
|
||||||
|
XA=$THISDIR/../../xa
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# actual code
|
||||||
|
. ../func.sh
|
||||||
|
|
@ -16,5 +16,5 @@ t1 lda `forward1
|
|||||||
sta `forward2
|
sta `forward2
|
||||||
rts
|
rts
|
||||||
|
|
||||||
#include "test2.asm"
|
#include "test2.s"
|
||||||
|
|
||||||
|
4
xa/tests/fordef/test.asm.err-test
Normal file
4
xa/tests/fordef/test.asm.err-test
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Copyright (C) 1989-2009 Andre Fachat, Jolse Maginnis, David Weinehall
|
||||||
|
and Cameron Kaiser.
|
||||||
|
test.asm:line 6: 0400: Warning - Can't optimize forward-defined label; using absolute addressing
|
||||||
|
test.asm:line 7: 0403: Warning - Can't optimize forward-defined label; using absolute addressing
|
@ -18,4 +18,4 @@
|
|||||||
lda (forward1),y
|
lda (forward1),y
|
||||||
jmp forward3
|
jmp forward3
|
||||||
|
|
||||||
#include "test2.asm"
|
#include "test2.s"
|
||||||
|
18
xa/tests/fordef/test4.asm
Normal file
18
xa/tests/fordef/test4.asm
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.word $0400
|
||||||
|
*=$0400
|
||||||
|
|
||||||
|
/* define this if you want to crash and burn */
|
||||||
|
|
||||||
|
jmp `forward3
|
||||||
|
bne `forward3
|
||||||
|
lda (`forward1),y
|
||||||
|
lda (`forward3),y
|
||||||
|
|
||||||
|
sta `forward3
|
||||||
|
|
||||||
|
/* this looks like it should fail, but won't because there is no ambiguity */
|
||||||
|
|
||||||
|
lda (forward1),y
|
||||||
|
jmp forward3
|
||||||
|
|
||||||
|
#include "test2.s"
|
7
xa/tests/fordef/test4.asm.err
Normal file
7
xa/tests/fordef/test4.asm.err
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Copyright (C) 1989-2009 Andre Fachat, Jolse Maginnis, David Weinehall
|
||||||
|
and Cameron Kaiser.
|
||||||
|
test4.asm:line 6: 0400:Wrong addressing mode error
|
||||||
|
test4.asm:line 7: 0402:Wrong addressing mode error
|
||||||
|
test4.asm:line 8: 0401:Wrong addressing mode error
|
||||||
|
test4.asm:line 9: 0400:Wrong addressing mode error
|
||||||
|
test4.asm:line 9: 0409:Overflow error
|
319
xa/tests/func.sh
Executable file
319
xa/tests/func.sh
Executable file
@ -0,0 +1,319 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
declare -A errs
|
||||||
|
declare -A opts
|
||||||
|
|
||||||
|
|
||||||
|
function usage() {
|
||||||
|
echo "Assemble *.asm or *.a65 test files"
|
||||||
|
echo " $0 [options] [frs_scripts]"
|
||||||
|
echo "Options:"
|
||||||
|
echo " -v verbose log"
|
||||||
|
echo " -o server log on console"
|
||||||
|
echo " -d <breakpoint> run xa with gdb and set given breakpoint. Can be "
|
||||||
|
echo " used multiple times"
|
||||||
|
echo " -k keep all files, even non-log and non-data files in run directory"
|
||||||
|
echo " -c clean up only non-log and non-data files from run directory,"
|
||||||
|
echo " keep rest (default)"
|
||||||
|
echo " -C always clean up complete run directory"
|
||||||
|
echo " -R <run directory> use given run directory instead of tmp folder (note:"
|
||||||
|
echo " will not be rmdir'd on -C"
|
||||||
|
echo " -q will suppress any output except whether test was successful"
|
||||||
|
echo " -h show this help"
|
||||||
|
}
|
||||||
|
|
||||||
|
function contains() {
|
||||||
|
local j
|
||||||
|
for j in "${@:2}"; do test "$j" == "$1" && return 0; done;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function hexdiff() {
|
||||||
|
diffres=0
|
||||||
|
if ! cmp -b "$1" "$2"; then
|
||||||
|
tmp1=`mktemp`
|
||||||
|
tmp2=`mktemp`
|
||||||
|
|
||||||
|
hexdump -C "$1" > $tmp1
|
||||||
|
hexdump -C "$2" > $tmp2
|
||||||
|
|
||||||
|
diff -u $tmp1 $tmp2
|
||||||
|
diffres=$?
|
||||||
|
|
||||||
|
rm $tmp1 $tmp2
|
||||||
|
fi;
|
||||||
|
return $diffres
|
||||||
|
}
|
||||||
|
|
||||||
|
VERBOSE=""
|
||||||
|
DEBUG=""
|
||||||
|
CLEAN=1
|
||||||
|
QUIET=0
|
||||||
|
LOGFILE=""
|
||||||
|
|
||||||
|
TMPDIR=`mktemp -d`
|
||||||
|
OWNDIR=1
|
||||||
|
|
||||||
|
while test $# -gt 0; do
|
||||||
|
case $1 in
|
||||||
|
-h)
|
||||||
|
usage
|
||||||
|
exit 0;
|
||||||
|
;;
|
||||||
|
-o)
|
||||||
|
LOGFILE="-"
|
||||||
|
shift;
|
||||||
|
;;
|
||||||
|
-v)
|
||||||
|
VERBOSE="-v"
|
||||||
|
shift;
|
||||||
|
;;
|
||||||
|
-d)
|
||||||
|
if test $# -lt 2; then
|
||||||
|
echo "Option -d needs the break point name for gdb as parameter"
|
||||||
|
exit -1;
|
||||||
|
fi;
|
||||||
|
DEBUG="$DEBUG $2"
|
||||||
|
shift 2;
|
||||||
|
;;
|
||||||
|
-k)
|
||||||
|
CLEAN=0
|
||||||
|
shift;
|
||||||
|
;;
|
||||||
|
-c)
|
||||||
|
CLEAN=1
|
||||||
|
shift;
|
||||||
|
;;
|
||||||
|
-C)
|
||||||
|
CLEAN=2
|
||||||
|
shift;
|
||||||
|
;;
|
||||||
|
-q)
|
||||||
|
QUIET=1
|
||||||
|
shift;
|
||||||
|
;;
|
||||||
|
-R)
|
||||||
|
if test $# -lt 2; then
|
||||||
|
echo "Option -R needs the directory path as parameter"
|
||||||
|
exit -1;
|
||||||
|
fi;
|
||||||
|
TMPDIR="$2"
|
||||||
|
OWNDIR=0
|
||||||
|
shift 2;
|
||||||
|
;;
|
||||||
|
-?)
|
||||||
|
echo "Unknown option $1"
|
||||||
|
usage
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break;
|
||||||
|
;;
|
||||||
|
esac;
|
||||||
|
done;
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# test for executables
|
||||||
|
|
||||||
|
ERR=0
|
||||||
|
if test ! -e $XA; then
|
||||||
|
echo "$XA does not exist! Maybe forgot to compile?"
|
||||||
|
ERR=1
|
||||||
|
fi
|
||||||
|
if [ $ERR -ge 1 ]; then
|
||||||
|
echo "Aborting!"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# scripts to run
|
||||||
|
if [ "x$*" = "x" ]; then
|
||||||
|
shopt -s extglob
|
||||||
|
SCRIPTS=$THISDIR/*${FILTER}*.a[s6][m5]
|
||||||
|
SCRIPTS=`basename -a $SCRIPTS`;
|
||||||
|
|
||||||
|
TESTSCRIPTS=""
|
||||||
|
|
||||||
|
if test "x$EXCLUDE" != "x"; then
|
||||||
|
exarr=( $EXCLUDE )
|
||||||
|
scrarr=( $SCRIPTS )
|
||||||
|
for scr in "${scrarr[@]}"; do
|
||||||
|
if ! contains "${scr}" "${exarr[@]}"; then
|
||||||
|
TESTSCRIPTS="$TESTSCRIPTS $scr";
|
||||||
|
fi
|
||||||
|
done;
|
||||||
|
else
|
||||||
|
TESTSCRIPTS="$SCRIPTS"
|
||||||
|
fi;
|
||||||
|
else
|
||||||
|
TESTSCRIPTS="";
|
||||||
|
|
||||||
|
for i in "$@"; do
|
||||||
|
if test -f "$i".asm ; then
|
||||||
|
TESTSCRIPTS="$TESTSCRIPTS $i.asm";
|
||||||
|
else
|
||||||
|
if test -f "$i".a65 ; then
|
||||||
|
TESTSCRIPTS="$TESTSCRIPTS $i.a65";
|
||||||
|
else
|
||||||
|
TESTSCRIPTS="$TESTSCRIPTS $i";
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
#echo "TESTSCRIPTS=$TESTSCRIPTS"
|
||||||
|
|
||||||
|
########################
|
||||||
|
# tmp names
|
||||||
|
#
|
||||||
|
|
||||||
|
DEBUGFILE="$TMPDIR"/gdb.ex
|
||||||
|
|
||||||
|
########################
|
||||||
|
# stdout
|
||||||
|
|
||||||
|
# remember stdout for summary output
|
||||||
|
exec 5>&1
|
||||||
|
exec 6>&2
|
||||||
|
|
||||||
|
# redirect log when quiet
|
||||||
|
if test $QUIET -ge 1 ; then
|
||||||
|
exec 1>$TMPDIR/stdout.log
|
||||||
|
exec 2>$TMPDIR/stderr.log
|
||||||
|
fi
|
||||||
|
|
||||||
|
########################
|
||||||
|
# prepare files
|
||||||
|
#
|
||||||
|
|
||||||
|
for i in $TESTSCRIPTS; do
|
||||||
|
cp "$THISDIR/$i" "$TMPDIR"
|
||||||
|
done;
|
||||||
|
|
||||||
|
########################
|
||||||
|
# run scripts
|
||||||
|
#
|
||||||
|
|
||||||
|
for script in $TESTSCRIPTS; do
|
||||||
|
|
||||||
|
echo "Run script $script"
|
||||||
|
|
||||||
|
AFLAGS="${ASMFLAGS} ${opts[$script]}"
|
||||||
|
|
||||||
|
ALOG=
|
||||||
|
if test "x$LOGFILE" = "x"; then
|
||||||
|
ALOG="-P $script.log"
|
||||||
|
else
|
||||||
|
ALOG="-P $LOGFILE"
|
||||||
|
fi
|
||||||
|
ALOG="$ALOG -e $script.err"
|
||||||
|
|
||||||
|
# overwrite test files in each iteration, just in case
|
||||||
|
for i in $TESTFILES; do
|
||||||
|
if [ -f ${THISDIR}/${i}.gz ]; then
|
||||||
|
gunzip -c ${THISDIR}/${i}.gz > ${TMPDIR}/${i}
|
||||||
|
else
|
||||||
|
cp ${THISDIR}/${i} ${TMPDIR}/${i}
|
||||||
|
fi;
|
||||||
|
done;
|
||||||
|
|
||||||
|
if test "x$DEBUG" = "x"; then
|
||||||
|
############################################
|
||||||
|
# simply do assemble
|
||||||
|
|
||||||
|
echo "Run assembler:" $XA $AFLAGS $script
|
||||||
|
(cd $TMPDIR; $XA -o a.out $ALOG $AFLAGS $script)
|
||||||
|
RESULT=$?
|
||||||
|
|
||||||
|
# check if we actually expected an error
|
||||||
|
#echo "errs=${errs[$script]}"
|
||||||
|
if [ "x${errs[$script]}" != "x" ]; then
|
||||||
|
if [ "$RESULT" = ${errs[$script]} ]; then
|
||||||
|
echo "override error because was expected"
|
||||||
|
RESULT=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $RESULT -eq 0; then
|
||||||
|
echo "$script: Ok" >&5
|
||||||
|
else
|
||||||
|
echo "$script: errors: $RESULT" >&5
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo > $DEBUGFILE;
|
||||||
|
for i in $DEBUG; do
|
||||||
|
echo "break $i" >> $DEBUGFILE
|
||||||
|
done;
|
||||||
|
gdb -x $DEBUGFILE -ex "run -o $TMPDIR/a.out $ALOG $AFLAGS $script" $XA
|
||||||
|
fi;
|
||||||
|
|
||||||
|
#echo "Killing server (pid $SERVERPID)"
|
||||||
|
#kill -TERM $SERVERPID
|
||||||
|
|
||||||
|
if [ -f "${THISDIR}/$script.err" ]; then
|
||||||
|
echo "Comparing file ${script}.err"
|
||||||
|
hexdiff ${THISDIR}/$script.err ${TMPDIR}/$script.err
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$COMPAREFILES" != "x"; then
|
||||||
|
testname=`basename $script .asm`
|
||||||
|
if [ "$script" = "$testname" ]; then
|
||||||
|
testname=`basename $script .a65`
|
||||||
|
fi
|
||||||
|
for i in $COMPAREFILES; do
|
||||||
|
NAME="${THISDIR}/${i}-${testname}"
|
||||||
|
if test -f ${NAME}; then
|
||||||
|
echo "Comparing file ${i} with ${NAME}"
|
||||||
|
hexdiff ${NAME} $TMPDIR/${i}
|
||||||
|
if test $? -ne 0; then
|
||||||
|
echo "$script: File ${i} differs!" >&5
|
||||||
|
fi;
|
||||||
|
fi
|
||||||
|
if test -f ${NAME}.gz; then
|
||||||
|
echo "Comparing file ${i} with ${NAME}.gz"
|
||||||
|
gunzip -c ${NAME}.gz > ${TMPDIR}/shouldbe_${i}
|
||||||
|
hexdiff ${TMPDIR}/shouldbe_${i} ${TMPDIR}/${i}
|
||||||
|
if test $? -ne 0; then
|
||||||
|
echo "$script: File ${i} differs!" >&5
|
||||||
|
fi;
|
||||||
|
rm -f ${TMPDIR}/shouldbe_${i}
|
||||||
|
fi
|
||||||
|
done;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $CLEAN -ge 1; then
|
||||||
|
rm -f $DEBUGFILE;
|
||||||
|
rm -f $TMPDIR/$script;
|
||||||
|
rm -f $TMPDIR/a.out;
|
||||||
|
fi
|
||||||
|
done;
|
||||||
|
|
||||||
|
if test $CLEAN -ge 2; then
|
||||||
|
echo "Cleaning up directory $TMPDIR"
|
||||||
|
|
||||||
|
for script in $TESTSCRIPTS; do
|
||||||
|
rm -f $TMPDIR/$script.log
|
||||||
|
rm -f $TMPDIR/$script.err
|
||||||
|
done;
|
||||||
|
|
||||||
|
# gzipped test files are unzipped
|
||||||
|
for i in $TESTFILES; do
|
||||||
|
rm -f $TMPDIR/$i;
|
||||||
|
done;
|
||||||
|
|
||||||
|
rm -f $TMPDIR/stdout.log
|
||||||
|
rm -f $TMPDIR/stderr.log
|
||||||
|
|
||||||
|
# only remove work dir if we own it (see option -R)
|
||||||
|
if test $OWNDIR -ge 1; then
|
||||||
|
rmdir $TMPDIR
|
||||||
|
fi;
|
||||||
|
else
|
||||||
|
echo "Find debug info in $TMPDIR" >&5
|
||||||
|
fi;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
# in 6502 mode, it will fail.
|
# in 6502 mode, it will fail.
|
||||||
../../xa test.s || exit 0 && exit 1
|
../../xa test.a65 || exit 0 && exit 1
|
||||||
# in 65816 mode, it will pass.
|
# in 65816 mode, it will pass.
|
||||||
../../xa -w test.s
|
../../xa -w test.a65
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f a.o65
|
rm -f a.o65
|
||||||
|
|
||||||
|
tests:
|
||||||
|
./runtest.sh -q -C
|
||||||
|
|
||||||
|
31
xa/tests/incerr/runtest.sh
Executable file
31
xa/tests/incerr/runtest.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run a test script
|
||||||
|
|
||||||
|
#THISDIR=`dirname $0`
|
||||||
|
THISDIR=`pwd`
|
||||||
|
|
||||||
|
#echo "0=$0"
|
||||||
|
#echo "THISDIR=$THISDIR"
|
||||||
|
|
||||||
|
declare -A opts
|
||||||
|
opts=([test.a65]="-w")
|
||||||
|
|
||||||
|
#ASMFLAGS=-v
|
||||||
|
ASMFLAGS=
|
||||||
|
|
||||||
|
# exclude filter from *.asm if no explicit file is given
|
||||||
|
EXCLUDE=
|
||||||
|
|
||||||
|
# test files used
|
||||||
|
TESTFILES="test.6502"
|
||||||
|
|
||||||
|
# files to compare afterwards, against <file>-<script>
|
||||||
|
COMPAREFILES=
|
||||||
|
|
||||||
|
XA=$THISDIR/../../xa
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# actual code
|
||||||
|
. ../func.sh
|
||||||
|
|
6
xa/tests/line/Makefile
Normal file
6
xa/tests/line/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
all: test1
|
||||||
|
|
||||||
|
%:%.a65
|
||||||
|
../../xa $<
|
||||||
|
|
20
xa/tests/line/test1.a65
Normal file
20
xa/tests/line/test1.a65
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* tests the internal line presentation getting over 128
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_ENDPOINTS 4
|
||||||
|
|
||||||
|
*=$c000
|
||||||
|
|
||||||
|
txmax .dsb MAX_ENDPOINTS, 0 ; max transfer length per endpoint
|
||||||
|
txpos .dsb MAX_ENDPOINTS, 0 ; endpoint buffer position per endpoint, calculated at usbd_start
|
||||||
|
txlen .dsb MAX_ENDPOINTS, 0 ; endpoint buffer length, set per transaction
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tests the internal line presentation getting over 256
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
txpos2 .byt MAX_ENDPOINTS, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; endpoint buffer position per endpoint, calculated at usbd_start and even more comments, but the many values alone use 5 byte per value internally...
|
||||||
|
|
39
xa/tests/listing/Makefile
Normal file
39
xa/tests/listing/Makefile
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#
|
||||||
|
# Makefile for tests
|
||||||
|
#
|
||||||
|
|
||||||
|
XA=../../xa
|
||||||
|
|
||||||
|
CA65=ca65
|
||||||
|
LD65=ld65
|
||||||
|
|
||||||
|
tests: linebreak include1 listblocks listca65 listca65_2 clean
|
||||||
|
|
||||||
|
|
||||||
|
include1: include1.a65
|
||||||
|
${XA} -P- $< > a.out
|
||||||
|
cmp include1.out a.out
|
||||||
|
|
||||||
|
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 listca65.ca65 listca65.o; rm listca65.o
|
||||||
|
cmp listca65.html a.out
|
||||||
|
cmp listca65.ca65 a.o65
|
||||||
|
|
||||||
|
listca65_2: listca65_2.a65
|
||||||
|
${XA} -XCA65 -P- -Fhtml listca65_2.a65 > a.out
|
||||||
|
${CA65} $<; ${LD65} -t none -o listca65_2.ca65 listca65_2.o; rm listca65_2.o
|
||||||
|
cmp listca65_2.html a.out
|
||||||
|
cmp listca65_2.ca65 a.o65
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f a.err a.o65 a.out
|
||||||
|
|
8
xa/tests/listing/include1.a65
Normal file
8
xa/tests/listing/include1.a65
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
.org $1000
|
||||||
|
|
||||||
|
#include "include1a.a65"
|
||||||
|
|
||||||
|
.include "include1a.a65"
|
||||||
|
|
||||||
|
|
23
xa/tests/listing/include1.out
Normal file
23
xa/tests/listing/include1.out
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
include1.a65
|
||||||
|
|
||||||
|
|
||||||
|
2 A:1000 *= $1000
|
||||||
|
|
||||||
|
include1a.a65
|
||||||
|
|
||||||
|
|
||||||
|
2 A:1000 a9 00 lda #$00
|
||||||
|
|
||||||
|
include1.a65
|
||||||
|
|
||||||
|
|
||||||
|
6 A:1002 .include "include1a.a65"
|
||||||
|
|
||||||
|
include1a.a65
|
||||||
|
|
||||||
|
|
||||||
|
2 A:1002 a9 00 lda #$00
|
||||||
|
|
||||||
|
include1.a65
|
||||||
|
|
3
xa/tests/listing/include1a.a65
Normal file
3
xa/tests/listing/include1a.a65
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
lda #$00
|
||||||
|
|
160
xa/tests/listing/linebreak.a65
Normal file
160
xa/tests/listing/linebreak.a65
Normal file
@ -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
|
||||||
|
|
||||||
|
.)
|
||||||
|
|
||||||
|
|
162
xa/tests/listing/linebreak.out
Normal file
162
xa/tests/listing/linebreak.out
Normal file
@ -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 .)
|
23
xa/tests/listing/listblocks.a65
Normal file
23
xa/tests/listing/listblocks.a65
Normal 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
|
||||||
|
|
24
xa/tests/listing/listblocks.html
Normal file
24
xa/tests/listing/listblocks.html
Normal 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>
|
24
xa/tests/listing/listca65.a65
Normal file
24
xa/tests/listing/listca65.a65
Normal 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 :--
|
||||||
|
|
BIN
xa/tests/listing/listca65.ca65
Normal file
BIN
xa/tests/listing/listca65.ca65
Normal file
Binary file not shown.
30
xa/tests/listing/listca65.html
Normal file
30
xa/tests/listing/listca65.html
Normal 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
BIN
xa/tests/listing/listca65.o
Normal file
Binary file not shown.
15
xa/tests/listing/listca65_2.a65
Normal file
15
xa/tests/listing/listca65_2.a65
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
; tests the html listing feature with blocks that
|
||||||
|
; contain the same label names, but in different scopes
|
||||||
|
|
||||||
|
.org $1000
|
||||||
|
|
||||||
|
: lda #$00
|
||||||
|
|
||||||
|
.include "listca65_2b.a65"
|
||||||
|
|
||||||
|
label2: iny
|
||||||
|
beq label2
|
||||||
|
|
||||||
|
jmp :-
|
||||||
|
|
BIN
xa/tests/listing/listca65_2.ca65
Normal file
BIN
xa/tests/listing/listca65_2.ca65
Normal file
Binary file not shown.
32
xa/tests/listing/listca65_2.html
Normal file
32
xa/tests/listing/listca65_2.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<html><head><title>(null)</title></head><body><pre>
|
||||||
|
|
||||||
|
listca65_2.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 .include "listca65_2b.a65"
|
||||||
|
|
||||||
|
listca65_2b.a65
|
||||||
|
|
||||||
|
|
||||||
|
2 A:1002 ; to be included in listca65_2.a65
|
||||||
|
3 A:1002 ; to check HTML linkage of unnamed labels across files
|
||||||
|
|
||||||
|
5 A:1002 c8 <a name="0U1"> </a>: iny
|
||||||
|
6 A:1003 d0 fd bne <a href="#0U1">:-</a>
|
||||||
|
|
||||||
|
listca65_2.a65
|
||||||
|
|
||||||
|
|
||||||
|
11 A:1005 <a name="0_label2"> </a>label2
|
||||||
|
11 A:1005 c8 iny
|
||||||
|
12 A:1006 f0 fd beq <a href="#0_label2">label2</a>
|
||||||
|
|
||||||
|
14 A:1008 4c 02 10 jmp <a href="#0U1">:-</a>
|
||||||
|
</pre></body></html>
|
7
xa/tests/listing/listca65_2b.a65
Normal file
7
xa/tests/listing/listca65_2b.a65
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
; to be included in listca65_2.a65
|
||||||
|
; to check HTML linkage of unnamed labels across files
|
||||||
|
|
||||||
|
: iny
|
||||||
|
bne :-
|
||||||
|
|
13
xa/tests/ppdefines/Makefile
Normal file
13
xa/tests/ppdefines/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
XA=../../xa
|
||||||
|
|
||||||
|
all: test1 test2 test3 test4 test5 test6 test6a test6b test7 clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm a.o65
|
||||||
|
|
||||||
|
%:%.a65
|
||||||
|
${XA} -XC $<
|
||||||
|
cmp a.o65 $@.o65
|
||||||
|
|
||||||
|
|
32
xa/tests/ppdefines/test1.a65
Normal file
32
xa/tests/ppdefines/test1.a65
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
#define macro1() \
|
||||||
|
lda #0
|
||||||
|
|
||||||
|
#define macro2(a) \
|
||||||
|
lda #(a)
|
||||||
|
|
||||||
|
#define macro3(a,b) \
|
||||||
|
lda #(a): \
|
||||||
|
ldy #(b)
|
||||||
|
|
||||||
|
#define const1 $40
|
||||||
|
|
||||||
|
#define func1(a) (a) | $20
|
||||||
|
|
||||||
|
*=$c000
|
||||||
|
|
||||||
|
macro1()
|
||||||
|
|
||||||
|
macro2(2)
|
||||||
|
|
||||||
|
macro3(2,3)
|
||||||
|
|
||||||
|
lda #(2) | $20
|
||||||
|
lda #func1(2)
|
||||||
|
|
||||||
|
macro2(func1(3))
|
||||||
|
|
||||||
|
macro3(const1, func1(5))
|
||||||
|
|
||||||
|
macro3(func1(const1), func1(func1(const1)))
|
||||||
|
|
BIN
xa/tests/ppdefines/test1.o65
Normal file
BIN
xa/tests/ppdefines/test1.o65
Normal file
Binary file not shown.
33
xa/tests/ppdefines/test2.a65
Normal file
33
xa/tests/ppdefines/test2.a65
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tests the definition of macro parameters with spaces
|
||||||
|
* between the name and the brackers / comma
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define wreg(reg, val) \
|
||||||
|
lda #(reg) | 0x02 :\
|
||||||
|
lda #(val)
|
||||||
|
|
||||||
|
#define wreg2( reg , val , val2 ) \
|
||||||
|
lda #(reg) | 0x02 :\
|
||||||
|
lda #(val) :\
|
||||||
|
ldx #(val2)
|
||||||
|
|
||||||
|
#define wreg3(reg, val, val2) \
|
||||||
|
.byt reg, val, val2
|
||||||
|
|
||||||
|
#define P1 1
|
||||||
|
#define P2 2
|
||||||
|
#define P3 3
|
||||||
|
|
||||||
|
|
||||||
|
*=$c000
|
||||||
|
|
||||||
|
wreg(P1, P2)
|
||||||
|
|
||||||
|
wreg2(P1, P2, P3)
|
||||||
|
|
||||||
|
wreg3( P1 , P2 , P3 )
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user