mirror of
https://github.com/fachat/xa65.git
synced 2024-09-29 00:55:56 +00:00
break out listing code from xat.c into separate file
This commit is contained in:
parent
f296538a90
commit
93d832b04a
@ -1,4 +1,4 @@
|
|||||||
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
|
||||||
|
550
xa/src/xalisting.c
Normal file
550
xa/src/xalisting.c
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
/* xa65 - 65xx/65816 cross-assembler and utility suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 1989-1997 André Fachat (a.fachat@physik.tu-chemnitz.de)
|
||||||
|
* maintained by Cameron Kaiser
|
||||||
|
*
|
||||||
|
* Core tokenizing module/pass 1 and pass 2
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
buf = outline;
|
||||||
|
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc + i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (overflow) {
|
||||||
|
// are we at the last byte?
|
||||||
|
if (n_hexb + 1 == bincode_len) {
|
||||||
|
// just print the last byte
|
||||||
|
buf = buf + list_byte(buf, bincode[i]);
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
} else {
|
||||||
|
// display "..."
|
||||||
|
buf = buf + list_nchar(buf, '.', 3);
|
||||||
|
}
|
||||||
|
n_hexb++;
|
||||||
|
}
|
||||||
|
i = n_hexb % 16;
|
||||||
|
if (i > num_last_line) {
|
||||||
|
// make a break (Note: with original PC, as now the assembler text follows
|
||||||
|
buf[0] = 0;
|
||||||
|
fprintf(listfp, "%s\n", outline);
|
||||||
|
buf = outline;
|
||||||
|
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
i = num_last_line - i;
|
||||||
|
buf = buf + list_nchar(buf, ' ', i * 3);
|
||||||
|
|
||||||
|
buf = buf + list_sp(buf);
|
||||||
|
|
||||||
|
buf += list_tokens(buf, listing + 3, listing_len - 3);
|
||||||
|
|
||||||
|
#ifdef LISTING_DEBUG
|
||||||
|
/* for now only do a hex dump so we see what actually happens */
|
||||||
|
i = buf - outline;
|
||||||
|
if (i<80) buf += list_nchar(buf, ' ', 80-i);
|
||||||
|
|
||||||
|
buf += list_string(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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_char(buf+outp, input[inp+1]);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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 (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 (is_cll) outp += list_char(buf+outp, '@');
|
||||||
|
outp += list_string(buf+outp, name);
|
||||||
|
/*
|
||||||
|
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_char(buf+outp, 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, arith_ops[op]);
|
||||||
|
inp += 1;
|
||||||
|
}
|
||||||
|
operator = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
return outp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_string(char *buf, char *string) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
24
xa/src/xalisting.h
Normal file
24
xa/src/xalisting.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* 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 do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len);
|
||||||
|
|
||||||
|
#endif /* __XA65_XALISTING_H__ */
|
522
xa/src/xat.c
522
xa/src/xat.c
@ -51,7 +51,7 @@ static void tg_hex(signed char*,int*,int*);
|
|||||||
static void tg_oct(signed char*,int*,int*);
|
static void tg_oct(signed char*,int*,int*);
|
||||||
static void tg_bin(signed char*,int*,int*);
|
static void tg_bin(signed char*,int*,int*);
|
||||||
static int t_p2(signed char *t, int *ll, int fl, int *al);
|
static int t_p2(signed char *t, int *ll, int fl, int *al);
|
||||||
static void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len);
|
//static void do_listing(signed char *listing, int listing_len, signed char *bincode, int bincode_len);
|
||||||
|
|
||||||
void list_setbytes(int number_of_bytes_per_line);
|
void list_setbytes(int number_of_bytes_per_line);
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ void list_setbytes(int number_of_bytes_per_line);
|
|||||||
* .export/.exportzp could be implemented with a commandline switch to NOT export
|
* .export/.exportzp could be implemented with a commandline switch to NOT export
|
||||||
* global labels, where .exported labels would still be exported in an o65 file.
|
* global labels, where .exported labels would still be exported in an o65 file.
|
||||||
*/
|
*/
|
||||||
static char *kt[] ={
|
char *kt[] ={
|
||||||
/* 1 2 3 4 5 6 7 8 9 10 */
|
/* 1 2 3 4 5 6 7 8 9 10 */
|
||||||
"adc","and","asl","bbr","bbs","bcc","bcs","beq","bit","bmi",
|
"adc","and","asl","bbr","bbs","bcc","bcs","beq","bit","bmi",
|
||||||
"bne","bpl","bra","brk","bvc","bvs","brl","clc","cld","cli",
|
"bne","bpl","bra","brk","bvc","bvs","brl","clc","cld","cli",
|
||||||
@ -99,7 +99,7 @@ static char *kt[] ={
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* arithmetic operators (purely for listing, parsing is done programmatically */
|
/* arithmetic operators (purely for listing, parsing is done programmatically */
|
||||||
static char *arith_ops[] = {
|
char *arith_ops[] = {
|
||||||
"", "+", "-",
|
"", "+", "-",
|
||||||
"*", "/",
|
"*", "/",
|
||||||
">>", "<<",
|
">>", "<<",
|
||||||
@ -172,6 +172,8 @@ static int lp[]= { 0,1,1,1,1,2,2,1,1,1,2,2,2,1,1,1,2,2 };
|
|||||||
#define Kreloc (Anzkey-256) /* *= (relocation mode) */
|
#define Kreloc (Anzkey-256) /* *= (relocation mode) */
|
||||||
#define Ksegment (Anzkey+1-256) /* this actually now is above 127, which might be a problem as char is signed ... */
|
#define Ksegment (Anzkey+1-256) /* this actually now is above 127, which might be a problem as char is signed ... */
|
||||||
|
|
||||||
|
int number_of_valid_tokens = Anzkey;
|
||||||
|
|
||||||
/* array used for hashing tokens (26 entries, a-z) */
|
/* array used for hashing tokens (26 entries, a-z) */
|
||||||
|
|
||||||
static int ktp[]={ 0,3,17,25,28,29,29,29,29,32,34,34,38,40,41,42,58,
|
static int ktp[]={ 0,3,17,25,28,29,29,29,29,32,34,34,38,40,41,42,58,
|
||||||
@ -2525,518 +2527,4 @@ fprintf(stderr, "tg_asc token = %i\n", n);
|
|||||||
return(er);
|
return(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************/
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
buf = outline;
|
|
||||||
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc + i + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (overflow) {
|
|
||||||
// are we at the last byte?
|
|
||||||
if (n_hexb + 1 == bincode_len) {
|
|
||||||
// just print the last byte
|
|
||||||
buf = buf + list_byte(buf, bincode[i]);
|
|
||||||
buf = buf + list_sp(buf);
|
|
||||||
} else {
|
|
||||||
// display "..."
|
|
||||||
buf = buf + list_nchar(buf, '.', 3);
|
|
||||||
}
|
|
||||||
n_hexb++;
|
|
||||||
}
|
|
||||||
i = n_hexb % 16;
|
|
||||||
if (i > num_last_line) {
|
|
||||||
// make a break (Note: with original PC, as now the assembler text follows
|
|
||||||
buf[0] = 0;
|
|
||||||
fprintf(listfp, "%s\n", outline);
|
|
||||||
buf = outline;
|
|
||||||
buf = list_preamble(buf, list_lineno, lst_seg, lst_pc);
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
i = num_last_line - i;
|
|
||||||
buf = buf + list_nchar(buf, ' ', i * 3);
|
|
||||||
|
|
||||||
buf = buf + list_sp(buf);
|
|
||||||
|
|
||||||
buf += list_tokens(buf, listing + 3, listing_len - 3);
|
|
||||||
|
|
||||||
#ifdef LISTING_DEBUG
|
|
||||||
/* for now only do a hex dump so we see what actually happens */
|
|
||||||
i = buf - outline;
|
|
||||||
if (i<80) buf += list_nchar(buf, ' ', 80-i);
|
|
||||||
|
|
||||||
buf += list_string(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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 < Anzkey) {
|
|
||||||
outp += list_string(buf+outp, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmp >= 0 && tmp < Anzkey) {
|
|
||||||
/* 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 (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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (inp < len) {
|
|
||||||
int operator = 0;
|
|
||||||
|
|
||||||
switch(input[inp]) {
|
|
||||||
case T_CAST:
|
|
||||||
outp += list_char(buf+outp, input[inp+1]);
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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 (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 (is_cll) outp += list_char(buf+outp, '@');
|
|
||||||
outp += list_string(buf+outp, name);
|
|
||||||
/*
|
|
||||||
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_char(buf+outp, 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, arith_ops[op]);
|
|
||||||
inp += 1;
|
|
||||||
}
|
|
||||||
operator = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end:
|
|
||||||
return outp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int list_string(char *buf, char *string) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,4 +29,8 @@ int b_term(char *s, int *v, int *l, int pc);
|
|||||||
void list_line(int l); /* set line number for the coming listing output */
|
void list_line(int l); /* set line number for the coming listing output */
|
||||||
void list_filename(char *fname);/* set file name for the coming listing output */
|
void list_filename(char *fname);/* set file name for the coming listing output */
|
||||||
|
|
||||||
|
extern char *kt[]; // table of key words, needed for listing
|
||||||
|
extern char *arith_ops[]; // table of arithmetic operators, needed for listing
|
||||||
|
extern int number_of_valid_tokens; // as it says, in the "kt" table
|
||||||
|
|
||||||
#endif /* __XA65_XAT_H__ */
|
#endif /* __XA65_XAT_H__ */
|
||||||
|
@ -4,9 +4,13 @@
|
|||||||
|
|
||||||
XA=../../xa
|
XA=../../xa
|
||||||
|
|
||||||
tests: linebreak clean
|
tests: linebreak include1 clean
|
||||||
|
|
||||||
|
|
||||||
|
include1: include1.a65
|
||||||
|
${XA} -P- $< > a.out
|
||||||
|
cmp include1.out a.out
|
||||||
|
|
||||||
linebreak: linebreak.a65
|
linebreak: linebreak.a65
|
||||||
${XA} -P- $< > a.out
|
${XA} -P- $< > a.out
|
||||||
cmp linebreak.out a.out
|
cmp linebreak.out 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user