aboutsummaryrefslogtreecommitdiff
path: root/listbas.c
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-07-12 15:52:55 -0400
committerB. Watson <urchlay@slackware.uk>2024-07-12 15:52:55 -0400
commitaddd5eab935391075a063ae120e730ed37cf0fac (patch)
tree2b6efa4d10e54d46649c038afe76e6a032b36b2d /listbas.c
parentf9f49e0e20ea64e99372b77e49b7cd9b84c25acf (diff)
downloadbw-atari8-tools-addd5eab935391075a063ae120e730ed37cf0fac.tar.gz
listbas: make colors customizable (-c), add -U and -C options, add LISTBAS_OPTS environment variable.
Diffstat (limited to 'listbas.c')
-rw-r--r--listbas.c146
1 files changed, 105 insertions, 41 deletions
diff --git a/listbas.c b/listbas.c
index e3b4225..def855d 100644
--- a/listbas.c
+++ b/listbas.c
@@ -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();