diff options
Diffstat (limited to 'listbas.c')
-rw-r--r-- | listbas.c | 187 |
1 files changed, 147 insertions, 40 deletions
@@ -11,28 +11,41 @@ #include "bas.h" #include "bcdfp.h" #include "tokens.h" +#include "atables.h" -int immediate = 0, a8cat = 1, magazine = 0; +#define C_RED 1 +#define C_GREEN 2 +#define C_YELLOW 3 +#define C_PURPLE 5 +#define C_CYAN 6 + +int immediate = 0, utf8 = 1, magazine = 0, inv = 0, color = 1, bold = 0; + +const char **table = ata2utf; FILE *outfh; void print_help(void) { - printf("Usage: %s [-v] [-i] [-a|-u] <inputfile>\n", self); + printf("Usage: %s [-v] [-i] [-n] [-a|-m] <inputfile>\n", self); printf(" -v: verbose.\n"); printf(" -i: show immediate mode command (line 32768).\n"); printf(" -a: output raw ATASCII.\n"); printf(" -m: magazine style listing (see a8cat(1)).\n"); + printf(" -n: disable color syntax highlighting.\n"); + printf(" -b: use bold for color output.\n"); } void parse_args(int argc, char **argv) { int opt; - while( (opt = getopt(argc, argv, "viamh")) != -1) { + while( (opt = getopt(argc, argv, "viamnbh")) != -1) { switch(opt) { case 'v': verbose = 1; break; case 'i': immediate = 1; break; - case 'a': a8cat = magazine = 0; break; - case 'm': a8cat = magazine = 1; break; + case 'a': utf8 = magazine = 0; color = 0; break; + case 'm': utf8 = 0 ; magazine = 1; color = 0; table = ata2mag; break; + case 'n': color = 0; break; + case 'b': bold = 1; break; case 'h': print_help(); exit(0); default: print_help(); @@ -47,38 +60,13 @@ void parse_args(int argc, char **argv) { } void setup_outfh(void) { - const char *cmd; - - /* search current dir before PATH. no easy way to detect errors here, - have to wait until we call pclose(). */ - if(a8cat) { - if(magazine) - cmd = "./a8cat -m 2>/dev/null || a8cat -m 2>/dev/null || exit 1"; - else - cmd = "./a8cat 2>/dev/null || a8cat 2>/dev/null || exit 1"; - } else { + if(! (utf8 || magazine) ) { if(isatty(fileno(stdout))) { die("Refusing to write ATASCII data to the terminal."); } - outfh = stdout; - return; - } - - outfh = popen(cmd, "w"); - if(!outfh) { - /* fork() or pipe() failed. does NOT detect if the command - wasn't found. */ - perror(self); - exit(1); - } -} - -void close_outfh(void) { - if(a8cat) { - if(pclose(outfh)) { - die("output filter failed; a8cat not in current dir or $PATH."); - } } + outfh = stdout; + return; } void outchr(char c) { @@ -110,18 +98,100 @@ double bcd2double(const unsigned char *num) { return result; } +void color_on(unsigned char c) { + printf("\x1b[%d;3%dm", bold, c); +} + +void color_off(void) { + fputs("\x1b[0m", outfh); +} + void print_number(unsigned int pos) { + if(color) color_on(C_RED); fprintf(outfh, "%G", bcd2double(program + pos)); + if(color) color_off(); +} + +/* only called in magazine mode. cursor control characters + like a bell in the middle of a non-inverse string + should not cause it to print {inv}{bell}{norm}. The {bell} + is "inherently" inverse (since its high bit is set) but doesn't + need to be printed that way. */ +int affects_inv(unsigned char c) { + switch(c) { + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + case 0x9b: + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + case 0x7d: + case 0x7e: + case 0x7f: + case 0xfd: + case 0xfe: + case 0xff: + return 0; + default: + return 1; + } +} + +void start_inv(unsigned char c) { + if(utf8) { + fputs("\x1b[7m", outfh); + inv = 1; + } else if(magazine) { + if(affects_inv(c)) { + fputs("{inv}", outfh); + inv = 1; + } + } +} + +void end_inv(unsigned char c) { + if(utf8) { + fputs("\x1b[0m", outfh); + inv = 0; + } else if(magazine) { + if(affects_inv(c)) { + fputs("{norm}", outfh); + inv = 0; + } + } +} + +void print_ata_chr(unsigned char c) { + if(c & 0x80) { + if(!inv) { + start_inv(c); + } + } else { + if(inv) { + end_inv(c); + } + } + fputs(table[c & 0x7f], outfh); } void print_string(unsigned int pos, unsigned int len) { + inv = 0; + if(color) color_on(C_RED); outchr('"'); - while(len--) outchr(program[pos++]); + while(len--) print_ata_chr(program[pos++]); + if(inv) end_inv(0); outchr('"'); + if(color) color_off(); } CALLBACK(print_lineno) { + if(color) color_on(C_CYAN); fprintf(outfh, "%d ", lineno); + if(color) color_off(); } CALLBACK(print_cmd) { @@ -129,10 +199,12 @@ CALLBACK(print_cmd) { if(tok == CMD_ILET) return; + if(color) color_on(C_YELLOW); if(tok > last_command || (!(name = commands[tok]))) fprintf(outfh, "(bad cmd token $%02x) ", tok); else fprintf(outfh, "%s ", name); + if(color) color_off(); } CALLBACK(print_op) { @@ -150,36 +222,72 @@ CALLBACK(print_op) { default: break; } + if(color) { + if(tok > 0x3c) + color_on(C_PURPLE); + else if(tok == OP_UMINUS) + color_on(C_RED); /* show leading - in same color as the number */ + else if((tok >= 0x17 && tok <= 0x1b) || (tok >= 0x28 && tok <= 0x2a)) + color_on(C_YELLOW); + else + color_on(C_GREEN); + } if(tok > last_operator || (!(name = operators[tok]))) fprintf(outfh, "(bad op token $%02x)", tok); else fprintf(outfh, "%s", name); + if(color) color_off(); } CALLBACK(print_varname) { int i, count; - unsigned char c; + unsigned char c, c_on = 0;; tok &= 0x7f; for(i = vnstart, count = 0; count < tok; i++) { if(program[i] & 0x80) count++; } do { - outchr( (c = program[i++]) & 0x7f); + c = program[i++]; + if(color && c == ('(' | 0x80)) { + color_on(C_GREEN); + c_on = 1; + } + outchr(c & 0x7f); } while (c < 0x80); + if(c_on) color_off(); } CALLBACK(print_text) { - while(program[pos] != 0x9b) outchr(program[pos++]); + unsigned char c, is_data = program[pos - 1] == CMD_DATA, comma = 0; + + inv = 0; + if(color) color_on(C_CYAN); + while(program[pos] != 0x9b) { + c = program[pos++]; + if(color && is_data && c == ',') { + color_off(); + comma = 1; + } else { + comma = 0; + } + print_ata_chr(c); + if(comma) + color_on(C_CYAN); + } + if(inv) end_inv(0); + if(color) color_off(); } CALLBACK(print_newline) { - outchr(0x9b); + if(utf8 || magazine) + outchr('\n'); + else + outchr(0x9b); } CALLBACK(code_prot) { fprintf(stderr, "%s: Program is code-protected, stopping at line %d.\n", self, lineno); - close_outfh(); exit(0); } @@ -207,7 +315,6 @@ int main(int argc, char **argv) { setup_outfh(); list(); - close_outfh(); return 0; } |