diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | listbas.c | 171 | ||||
-rw-r--r-- | tokens.c | 135 | ||||
-rw-r--r-- | tokens.h | 4 |
4 files changed, 314 insertions, 1 deletions
@@ -16,7 +16,7 @@ CC=gcc CFLAGS=-Wall $(COPT) -ansi -D_GNU_SOURCE -DVERSION=\"$(VERSION)\" # BINS and SCRIPTS go in $BINDIR, DOCS go in $DOCDIR -BINS=a8eol atr2xfd atrsize axe blob2c blob2xex cart2xex cxrefbas dumpbas fenders protbas renumbas rom2cart unmac65 unprotbas vxrefbas xex1to2 xexamine xexcat xexsplit xfd2atr +BINS=a8eol atr2xfd atrsize axe blob2c blob2xex cart2xex cxrefbas dumpbas fenders protbas renumbas rom2cart unmac65 unprotbas vxrefbas xex1to2 xexamine xexcat xexsplit xfd2atr listbas SCRIPTS=dasm2atasm a8utf8 MANS=a8eol.1 xfd2atr.1 atr2xfd.1 blob2c.1 cart2xex.1 fenders.1 xexsplit.1 xexcat.1 atrsize.1 rom2cart.1 unmac65.1 axe.1 dasm2atasm.1 a8utf8.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.1 renumbas.1 dumpbas.1 vxrefbas.1 cxrefbas.1 MAN5S=xex.5 @@ -61,6 +61,9 @@ vxrefbas: bas.o cxrefbas: bas.o bcdfp.o linetab.o +listbas: listbas.c bas.o bcdfp.o tokens.o + $(CC) $(CFLAGS) -o listbas listbas.c bas.o bcdfp.o tokens.o -lm + bas.o: bas.c bas.h subdirs: diff --git a/listbas.c b/listbas.c new file mode 100644 index 0000000..6469009 --- /dev/null +++ b/listbas.c @@ -0,0 +1,171 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <math.h> + +#include "bas.h" +#include "bcdfp.h" +#include "tokens.h" + +int immediate = 0; + +void print_help(void) { + printf("Usage: %s [-v] [-i] <inputfile>\n", self); +} + +void parse_args(int argc, char **argv) { + int opt; + + while( (opt = getopt(argc, argv, "vi")) != -1) { + switch(opt) { + case 'v': verbose = 1; break; + case 'i': immediate = 1; break; + default: + print_help(); + exit(1); + } + } + + if(optind >= argc) + die("No input file given (use - for stdin)."); + else + open_input(argv[optind]); +} + +double bcd2double(const unsigned char *num) { + double result = 0, sign; + int exp, i; + + exp = *num; + if(!exp) { + return 0.0; + } + + sign = (exp & 0x80 ? -1.0 : 1.0); + exp &= 0x7f; + exp -= 0x40; + + for(i = 1; i < 6; i++) { + result *= 100.0; + result += bcd2int(num[i]); + } + + result *= pow(100, exp - 4); + result *= sign; + + return result; +} + +void print_number(unsigned int pos) { + printf("%G", bcd2double(program + pos)); +} + +void print_string(unsigned int pos, unsigned int len) { + putchar('"'); + while(len--) putchar(program[pos++]); + putchar('"'); +} + +CALLBACK(print_lineno) { + printf("%d ", lineno); +} + +CALLBACK(print_cmd) { + int bad; + const char *name; + + if(tok == CMD_ILET) return; + + if(tok > last_command) { + bad = 1; + } else if( (name = commands[tok]) ) { + bad = 0; + } else { + bad = 1; + } + + if(bad) + printf("(bad cmd token $%02x)", tok); + else + printf("%s ", name); +} + +CALLBACK(print_op) { + int bad; + const char *name; + + switch(tok) { + case OP_NUMCONST: + print_number(pos + 1); + return; + case OP_STRCONST: + print_string(pos + 2, program[pos + 1]); + return; + case OP_EOL: + return; + default: break; + } + + + if(tok > last_operator) { + bad = 1; + } else if( (name = operators[tok]) ) { + bad = 0; + } else { + bad = 1; + } + + if(bad) + printf("(bad op token $%02x)", tok); + else + printf("%s", name); +} + +CALLBACK(print_varname) { + int i, count; + unsigned char c; + + tok &= 0x7f; + for(i = vnstart, count = 0; count < tok; i++) { + if(program[i] & 0x80) count++; + } + while(1) { + c = program[i++]; + putchar(c & 0x7f); + if(c & 0x80) break; + } +} + +CALLBACK(print_text) { + while(program[pos] != 0x9b) putchar(program[pos++]); +} + +CALLBACK(print_newline) { + putchar('\n'); +} + +void list(void) { + on_start_line = print_lineno; + on_cmd_token = print_cmd; + on_exp_token = print_op; + on_var_token = print_varname; + on_end_line = print_newline; + on_text = print_text; + walk_code(0, 32767 + immediate); +} + +int main(int argc, char **argv) { + set_self(*argv); + parse_general_args(argc, argv, print_help); + parse_args(argc, argv); + + readfile(); + parse_header(); + + list(); + + return 0; +} diff --git a/tokens.c b/tokens.c new file mode 100644 index 0000000..08cf48a --- /dev/null +++ b/tokens.c @@ -0,0 +1,135 @@ +const char *commands[] = { + "REM", + "DATA", + "INPUT", + "COLOR", + "LIST", + "ENTER", + "LET", + "IF", + "FOR", + "NEXT", + "GOTO", + "GO TO", + "GOSUB", + "TRAP", + "BYE", + "CONT", + "COM", + "CLOSE", + "CLR", + "DEG", + "DIM", + "END", + "NEW", + "OPEN", + "LOAD", + "SAVE", + "STATUS", + "NOTE", + "POINT", + "XIO", + "ON", + "POKE", + "PRINT", + "RAD", + "READ", + "RESTORE", + "RETURN", + "RUN", + "STOP", + "POP", + "?", + "GET", + "PUT", + "GRAPHICS", + "PLOT", + "POSITION", + "DOS", + "DRAWTO", + "SETCOLOR", + "LOCATE", + "SOUND", + "LPRINT", + "CSAVE", + "CLOAD", + "", /* implied LET */ + "ERROR -" +}; + +const unsigned short last_command = (sizeof(commands) / sizeof(char *)) - 1; + +const char *operators[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ",", + "$", + ":", + ";", + "", /* $16, EOL */ + " GOTO ", + " GOSUB ", /* $18 */ + " TO ", + " STEP ", + " THEN ", + "#", + "<=", + "<>", + ">=", + "<", /* $20 */ + ">", + "=", + "^", + "*", + "+", + "-", + "/", + " NOT ", /* $28 */ + " OR ", + " AND ", + "(", + ")", + "=", + "=", + "<=", + "<>", /* $30 */ + ">=", + "<", + ">", + "=", + "+", + "-", + "(", + "", /* $38, redunant for arrays */ + "", /* $39, ditto */ + "(", + "(", + ",", + "STR$", + "CHR$", + "USR", + "ASC", /* $40 */ + "VAL", + "LEN", + "ADR", + "ATN", + "COS", + "PEEK", + "SIN", + "RND", /* $48 */ + "FRE", + "EXP", + "LOG", + "CLOG", + "SQR", + "SGN", + "ABS", + "INT", /* $50 */ + "PADDLE", + "STICK", + "PTRIG", + "STRIG" /* $54 */ +}; + +const unsigned short last_operator = (sizeof(operators) / sizeof(char *)) - 1; diff --git a/tokens.h b/tokens.h new file mode 100644 index 0000000..265122e --- /dev/null +++ b/tokens.h @@ -0,0 +1,4 @@ +extern const char *commands[]; +extern const char *operators[]; +extern const unsigned short last_command; +extern const unsigned short last_operator; |