aboutsummaryrefslogtreecommitdiff
path: root/listbas.c
diff options
context:
space:
mode:
Diffstat (limited to 'listbas.c')
-rw-r--r--listbas.c187
1 files changed, 147 insertions, 40 deletions
diff --git a/listbas.c b/listbas.c
index 9577cec..0c807c2 100644
--- a/listbas.c
+++ b/listbas.c
@@ -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;
}