aboutsummaryrefslogtreecommitdiff
path: root/cxrefbas.c
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-06-16 17:33:22 -0400
committerB. Watson <urchlay@slackware.uk>2024-06-16 17:33:22 -0400
commite2250e5cb71c9a06bf75d59e9c0369efd65b1206 (patch)
treeae87da4b129ca29c5066e27d375f080d0cac9d72 /cxrefbas.c
parentdecd8312b033235cb64db2fcd3ffa4829bd21af7 (diff)
downloadbw-atari8-tools-e2250e5cb71c9a06bf75d59e9c0369efd65b1206.tar.gz
cxrefbas: added.
Diffstat (limited to 'cxrefbas.c')
-rw-r--r--cxrefbas.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/cxrefbas.c b/cxrefbas.c
new file mode 100644
index 0000000..45369d4
--- /dev/null
+++ b/cxrefbas.c
@@ -0,0 +1,198 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "bas.h"
+#include "bcdfp.h"
+
+unsigned short *linerefs[32769];
+int refcounts[32769];
+int lines_exist[32769];
+int last_cmd;
+int last_cmd_pos;
+
+void add_lineref(unsigned short from, unsigned short to) {
+ unsigned short *p;
+ int c;
+
+ if(to > 32767) return;
+
+ p = linerefs[to];
+ c = refcounts[to];
+
+ if(c) {
+ p = realloc(p, sizeof(unsigned short) * (c + 1));
+ } else {
+ p = malloc(sizeof(unsigned short));
+ }
+
+ if(!p) die("Out of memory.");
+
+ linerefs[to] = p;
+ p[c] = from;
+ c++;
+ refcounts[to] = c;
+}
+
+/* makes sure a numeric constant isn't start of an expression. */
+int is_standalone_num(unsigned short pos) {
+ if(program[pos] != OP_NUMCONST) return 0;
+ switch(program[pos + 7]) {
+ case OP_EOS:
+ case OP_EOL:
+ case OP_COMMA:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+CALLBACK(start_stmt) {
+ lines_exist[lineno] = 1;
+}
+
+CALLBACK(got_cmd) {
+ last_cmd = tok;
+ last_cmd_pos = pos;
+}
+
+void computed_msg(unsigned char tok, unsigned short lineno) {
+ static int last_lineno = -1;
+ char *cmd;
+
+ /* avoid duplicate warnings */
+ if(lineno == last_lineno) return;
+ last_lineno = lineno;
+
+ switch(tok) {
+ case CMD_GOTO:
+ cmd = "GOTO"; break;
+ case CMD_GO_TO:
+ cmd = "GO TO"; break;
+ case CMD_GOSUB:
+ cmd = "GOSUB"; break;
+ case CMD_RESTORE:
+ cmd = "RESTORE"; break;
+ case CMD_TRAP:
+ cmd = "TRAP"; break;
+ case CMD_ON:
+ cmd = "ON"; break;
+ default: /* should never happen! */
+ cmd = "???"; break;
+ }
+
+ fprintf(stderr, "Computed %s at line %d\n", cmd, lineno);
+}
+
+CALLBACK(got_var) {
+ switch(last_cmd) {
+ case CMD_GOTO:
+ case CMD_GO_TO:
+ case CMD_GOSUB:
+ case CMD_RESTORE:
+ case CMD_TRAP:
+ computed_msg(last_cmd, lineno);
+ break;
+ default:
+ break;
+ }
+}
+
+CALLBACK(got_exp) {
+ int standalone;
+
+ if(tok != OP_NUMCONST) return;
+ standalone = is_standalone_num(pos);
+
+ switch(last_cmd) {
+ case CMD_GOTO:
+ case CMD_GO_TO:
+ case CMD_GOSUB:
+ case CMD_RESTORE:
+ case CMD_TRAP:
+ if((pos == last_cmd_pos + 1) && standalone) {
+ add_lineref(lineno, fp2int(program + pos + 1));
+ } else {
+ computed_msg(last_cmd, lineno);
+ }
+ break;
+ case CMD_ON: {
+ unsigned char last_tok = program[pos - 1];
+ switch(last_tok) {
+ case OP_GOTO:
+ case OP_GOSUB:
+ case OP_COMMA:
+ if(standalone)
+ add_lineref(lineno, fp2int(program + pos + 1));
+ else
+ computed_msg(last_cmd, lineno);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void build_ref_table(void) {
+ on_start_stmt = start_stmt;
+ on_cmd_token = got_cmd;
+ on_exp_token = got_exp;
+ on_var_token = got_var;
+ walk_all_code();
+}
+
+void print_ref_table(void) {
+ int i, j;
+ for(i = 0; i < 32768; i++) {
+ if(refcounts[i]) {
+ if(!lines_exist[i]) putchar('!');
+ printf("%d: ", i);
+ for(j = 0; j < refcounts[i]; j++) {
+ printf("%d ", linerefs[i][j]);
+ }
+ putchar('\n');
+ }
+ }
+}
+
+void print_help(void) {
+ fprintf(stderr, "Usage: %s [-v] program.bas\n", self);
+ exit(0);
+}
+
+void parse_args(int argc, char **argv) {
+ int opt;
+
+ while( (opt = getopt(argc, argv, "v")) != -1) {
+ switch(opt) {
+ case 'v': verbose = 1; break;
+ default: print_help(); exit(1);
+ }
+ }
+
+ if(optind >= argc)
+ die("No input file given (use - for stdin).");
+ else
+ open_input(argv[optind]);
+}
+
+int main(int argc, char **argv) {
+ set_self(*argv);
+ parse_general_args(argc, argv, print_help);
+ parse_args(argc, argv);
+
+ readfile();
+ parse_header();
+
+ build_ref_table();
+ print_ref_table();
+
+ return 0;
+}