diff options
Diffstat (limited to 'listbas.c')
-rw-r--r-- | listbas.c | 146 |
1 files changed, 105 insertions, 41 deletions
@@ -30,12 +30,15 @@ #define MAG_NORM "{norm}" /* colors. don't use blue, it's fugly. */ +#define NO_COLOR -1 #define C_RED 1 #define C_GREEN 2 #define C_YELLOW 3 #define C_PURPLE 5 #define C_CYAN 6 +#define ENV_OPTS "LISTBAS_OPTS" + /* output modes */ #define M_UTF8 0 /* default */ #define M_UTF8_I 1 /* -x */ @@ -50,39 +53,77 @@ int color = 1; /* 0 with -n */ int immediate = 0; /* 1 with -i */ int underline = 0; /* 1 with -u */ +int color_cmd = C_YELLOW; +int color_op = C_GREEN; +int color_func = C_PURPLE; +int color_const = C_RED; +int color_lnum_text = C_CYAN; +int color_varnames = NO_COLOR; + int badtok = 0; /* set to 1 if we find a bad token */ int inv = 0; /* set to 1 when we're printing inverse */ int cur_color = -1; /* -1 = no color */ FILE *outfh; +int parse_color(char c) { + if(c == 'n') + return NO_COLOR; + + if(c >= '0' && c <= '7') + return c - '0'; + + fprintf(stderr, "%s: Invalid color '%c'.\n", self, c); + exit(1); +} + +void parse_color_scheme(const char *arg) { + if(!arg) return; + + if(strlen(arg) != 6) + die("Color scheme must be 6 characters."); + + color_cmd = parse_color(arg[0]); + color_op = parse_color(arg[1]); + color_func = parse_color(arg[2]); + color_const = parse_color(arg[3]); + color_lnum_text = parse_color(arg[4]); + color_varnames = parse_color(arg[5]); +} + void print_help(void) { printf("Usage: %s [-a | -d | -m | -x] [-b] [-i] [-n] [-v] <inputfile>\n", self); + printf(" -U: output ATASCII as Unicode/UTF-8 (this is the default).\n"); printf(" -a: output raw ATASCII.\n"); printf(" -d: use dots instead of Unicode/UTF-8.\n"); printf(" -m: magazine style listing (see a8cat(1)).\n"); printf(" -x: XL international character set (UTF-8).\n"); printf(" -b: use bold for color output.\n"); printf(" -i: show immediate mode command (line 32768).\n"); + printf(" -C: enable color syntax highlighting (this is the default).\n"); printf(" -n: disable color syntax highlighting.\n"); - printf(" -n: use underline for inverse video.\n"); + printf(" -u: use underline for inverse video.\n"); printf(" -v: verbose.\n"); } -void parse_args(int argc, char **argv) { +void parse_args(int argc, char **argv, int from_env) { int opt; - int opt_a = 0, opt_m = 0, opt_d = 0, opt_x = 0; - while( (opt = getopt(argc, argv, "viamnbdhxu")) != -1) { + optind = 1; + + while( (opt = getopt(argc, argv, "UCviamnbdhxuc:")) != -1) { switch(opt) { + case 'U': output_mode = M_UTF8; break; + case 'a': output_mode = M_ATASCII; break; + case 'm': output_mode = M_MAG; break; + case 'd': output_mode = M_DOTS; break; + case 'x': output_mode = M_UTF8_I; break; case 'v': verbose = 1; break; case 'i': immediate = 1; break; - case 'a': opt_a = 1; break; - case 'm': opt_m = 1; break; - case 'd': opt_d = 1; break; - case 'x': opt_x = 1; break; case 'b': bold = 1; break; case 'u': underline = 1; break; + case 'C': color = 1; break; case 'n': color = 0; break; + case 'c': parse_color_scheme(optarg); break; case 'h': print_help(); exit(0); default: print_help(); @@ -90,23 +131,40 @@ void parse_args(int argc, char **argv) { } } - if(opt_a + opt_d + opt_m + opt_x > 1) - die("Only use one of the -a, -d, -m, -x options."); - - if(opt_a) { - output_mode = M_ATASCII; - } else if(opt_d) { - output_mode = M_DOTS; - } else if(opt_m) { - output_mode = M_MAG; - } else if(opt_x) { - output_mode = M_UTF8_I; + if(!from_env) { + if(optind >= argc) + die("No input file given (use - for stdin)."); + else + open_input(argv[optind]); } +} - if(optind >= argc) - die("No input file given (use - for stdin)."); - else - open_input(argv[optind]); +/* make a fake argv and argc */ +void parse_env_args(void) { + int fargc; + char *fargv[10]; + char *env, *p; + + env = getenv(ENV_OPTS); + if(!env) return; + + if(verbose) + fprintf(stderr, "%s: read options from environment: \"%s\"\n.", self, env); + + fargv[0] = (char *)self; + fargv[1] = env; + fargc = 2; + + for(p = env; *p; p++) { + if(*p == ' ' || *p == '\t') { + *p = '\0'; + fargv[fargc++] = p + 1; + } + } + + fargv[fargc] = NULL; + + parse_args(fargc, fargv, 1); } void setup_outfh(void) { @@ -115,8 +173,11 @@ void setup_outfh(void) { die("Refusing to write ATASCII data to the terminal."); } } - /* TODO: reopen in binary mode! */ - outfh = stdout; + outfh = freopen(NULL, "wb", stdout); + if(!outfh) { + perror("freopen()"); + die("Can't reopen standard output in binary mode."); + } return; } @@ -151,7 +212,8 @@ double bcd2double(const unsigned char *num) { void color_on(unsigned char c) { cur_color = c; - printf(COLOR_FMT, bold, c); + if(c != NO_COLOR) + printf(COLOR_FMT, bold, c); } void color_off(void) { @@ -160,7 +222,7 @@ void color_off(void) { } void print_number(unsigned int pos) { - if(color) color_on(C_RED); + if(color) color_on(color_const); fprintf(outfh, "%G", bcd2double(program + pos)); if(color) color_off(); } @@ -274,7 +336,7 @@ void print_ata_chr(unsigned char c) { void print_string(unsigned int pos, unsigned int len) { inv = 0; outchr('"'); - if(color) color_on(C_RED); + if(color) color_on(color_const); while(len--) print_ata_chr(program[pos++]); if(inv) { end_inv(0); @@ -284,7 +346,7 @@ void print_string(unsigned int pos, unsigned int len) { } CALLBACK(print_lineno) { - if(color) color_on(C_CYAN); + if(color) color_on(color_lnum_text); fprintf(outfh, "%d ", lineno); if(color) color_off(); } @@ -294,7 +356,7 @@ CALLBACK(print_cmd) { if(tok == CMD_ILET) return; - if(color) color_on(C_YELLOW); + if(color) color_on(color_cmd); if(tok > last_command || (!(name = commands[tok]))) { fprintf(outfh, "(bad cmd token $%02x) ", tok); badtok = 1; @@ -321,13 +383,13 @@ CALLBACK(print_op) { if(color) { if(tok > 0x3c) - color_on(C_PURPLE); + color_on(color_func); else if(tok == OP_UMINUS) - color_on(C_RED); /* show leading - in same color as the number */ + color_on(color_const); /* show leading - in same color as the number */ else if((tok >= 0x17 && tok <= 0x1b) || (tok >= 0x28 && tok <= 0x2a)) - color_on(C_YELLOW); + color_on(color_cmd); else - color_on(C_GREEN); + color_on(color_op); } if(tok > last_operator || (!(name = operators[tok]))) { fprintf(outfh, "(bad op token $%02x)", tok); @@ -340,7 +402,9 @@ CALLBACK(print_op) { CALLBACK(print_varname) { int i, count; - unsigned char c, c_on = 0;; + unsigned char c; + + if(color) color_on(color_varnames); tok &= 0x7f; for(i = vnstart, count = 0; count < tok; i++) { @@ -349,19 +413,18 @@ CALLBACK(print_varname) { do { c = program[i++]; if(color && c == ('(' | 0x80)) { - color_on(C_GREEN); - c_on = 1; + if(color) color_on(color_op); } outchr(c & 0x7f); } while (c < 0x80); - if(c_on) color_off(); + if(color) color_off(); } CALLBACK(print_text) { unsigned char c, is_data = program[pos - 1] == CMD_DATA, comma = 0; inv = 0; - if(color) color_on(C_CYAN); + if(color) color_on(color_lnum_text); while(program[pos] != 0x9b) { c = program[pos++]; if(color && is_data && c == ',') { @@ -372,7 +435,7 @@ CALLBACK(print_text) { } print_ata_chr(c); if(comma) - color_on(C_CYAN); + color_on(color_lnum_text); } if(inv) end_inv(0); if(color) color_off(); @@ -404,7 +467,8 @@ void list(void) { int main(int argc, char **argv) { set_self(*argv); parse_general_args(argc, argv, print_help); - parse_args(argc, argv); + parse_env_args(); + parse_args(argc, argv, 0); readfile(); parse_header(); |