From 54bec63a3cbf149d6c3a542c2962ef5e6aac9965 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Tue, 9 Jul 2024 03:59:46 -0400 Subject: whichbas: fix logic for %0,%1,%2/LEFT$/RIGHT$/MID$ (ops 0x66/0x67/0x68). --- whichbas.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/whichbas.c b/whichbas.c index 3e652a7..2fe273e 100644 --- a/whichbas.c +++ b/whichbas.c @@ -186,7 +186,7 @@ CALLBACK(handle_cmd) { bas_type = BT_TURBO; print_result(); } - /* partial: we really should detect GET #1,A$. this is Turbo-only, but + /* PARTIAL: we really should detect GET #1,A$. this is Turbo-only, but probably nobody ever uses it because it doesn't seem to *work*, at least not in TB 1.5. A$ always ends up empty with length 0. */ break; @@ -247,6 +247,7 @@ CALLBACK(handle_cmd) { case 0x3d: /* UNTIL or ENDIF */ case 0x56: /* DEL or FAST */ case 0x62: /* CIRCLE (3 or 4 num args) or NORMAL (no args) */ + /* COMPLETE */ if(has_args) { remove_type(BT_BXL_BXE); } else { @@ -254,7 +255,7 @@ CALLBACK(handle_cmd) { } break; case 0x58: /* TRACE (optional + or -), EXTEND (BXE; no args) */ - /* partial: TRACE +/- detected, TRACE without arg can't be + /* PARTIAL: TRACE +/- detected, TRACE without arg can't be told from EXTEND. */ if(nexttok == OP_PLUS || nexttok == OP_MINUS) { bas_type = BT_TURBO; @@ -292,14 +293,14 @@ CALLBACK(handle_cmd) { } break; case 0x48: /* DIR (optional arg) or PROTECT (req'd arg) */ - /* partial: without args means TB, but with arg, + /* PARTIAL: without args means TB, but with arg, it could be either */ if(!has_args) { remove_type(BT_BXL_BXE); } break; case 0x4a: /* UNLOCK (req'd arg) or DIR (optional arg) */ - /* partial: without args means TB, but with arg, + /* PARTIAL: without args means TB, but with arg, it could be either */ if(!has_args) { remove_type(BT_TURBO); @@ -307,7 +308,7 @@ CALLBACK(handle_cmd) { break; case 0x3b: /* *F (optional + or -), TRACE (no arg) */ case 0x5e: /* *B (optional + or -) or EXIT (no arg) */ - /* partial: doesn't catch *F or *B by itself with no +/- */ + /* PARTIAL: doesn't catch *F or *B by itself with no +/- */ if(has_args) { remove_type(BT_BXL_BXE); } @@ -321,7 +322,7 @@ CALLBACK(handle_cmd) { } break; case 0x4e: /* TIME$= (1 string arg) or PMCLR (1 num arg) */ - /* partial: but almost complete. nothing happens if it's + /* PARTIAL: but almost complete. nothing happens if it's TIME$= with a string function (probably rare) or PMCLR with a complex expression. */ if(nexttok == OP_STRCONST) { @@ -335,12 +336,13 @@ CALLBACK(handle_cmd) { } break; case 0x50: /* EXEC (1 arg, *must* be variable) or PMGRAPHICS (1 num arg, may be const) */ - /* partial: PMGRAPHICS VAR won't be detected. but this usage is rare. */ + /* PARTIAL: PMGRAPHICS VAR won't be detected. but this usage is rare. */ if(!has_var_arg) { remove_type(BT_TURBO); } break; case 0x54: /* -- in TB, LVAR in BXL/BXE */ + /* COMPLETE */ /* we can tell these apart because TB gives us a next-statement offset of 5 when we use this (normally, the minimum offset is 6, but there's no OP_EOS after this token for some reason). */ @@ -354,6 +356,8 @@ CALLBACK(handle_cmd) { case 0x57: /* DUMP (1 optional string arg) or LOCAL (1 *numeric* variable arg) */ /* BXL/BXE's LOCAL only works on scalars, not arrays or strings. so if there's no arg, or one string arg... */ + /* PARTIAL: almost complete, doesn't handle DUMP func$(arg), which I + doubt anyone uses anyway. */ if(!has_args) { /* only Turbo allows no arg... */ remove_type(BT_BXL_BXE); @@ -369,6 +373,8 @@ CALLBACK(handle_cmd) { } case 0x5c: /* GO# (1 arg only) or SORTUP (optional 2nd arg of USING, but no comma) */ case 0x5d: /* # (1 arg only) or SORTDOWN (optional 2nd arg of USING, but no comma) */ + /* COMPLETE but no longer needed (check_variables() already found the + 11xxxxxx variables) */ /* Turbo BASIC labels have the high 2 bits set to 11, which is illegal in Atari/BXL/BXE. */ if(vartype == 3) { @@ -378,7 +384,7 @@ CALLBACK(handle_cmd) { } break; case 0x60: /* CLS (optional IOCB with #) or HITCLR (no args) */ - /* partial: without args, can't tell them apart. */ + /* PARTIAL: without args, can't tell them apart. */ /* I doubt CLS #IOCB is actually used in many Turbo BASIC programs, because it's broken (at least in Turbo 1.5). It's supposed to only clear the screen of output that @@ -410,7 +416,7 @@ CALLBACK(handle_op) { /* attempt to detect BXL/BXE DIM for 2D string arrays. DIM A$(10,10) is illegal in Atari/Turbo. - partial: this only works if the first dimension is either a + PARTIAL: this only works if the first dimension is either a constant or a scalar variable (not an array element or an expression). fortunately most programs use constants in DIM. */ @@ -458,6 +464,7 @@ CALLBACK(handle_op) { case 0x55: /* DPEEK (function) TB, USING (infix, not a function) in BXL/BXE */ case 0x58: /* INSTR (function) or & (infix numeric) in BXE. */ case 0x5b: /* HEX$ (func, takes 1 num arg) or FIND( (pseudo-func, 3 args */ + /* COMPLETE */ if(nexttok == OP_FUNC_LPAR) { remove_type(BT_BXL_BXE); } else { @@ -465,7 +472,7 @@ CALLBACK(handle_op) { } break; case 0x59: /* INKEY$ (0 arg pseudo-func) in TB, string array separator semicolon in BXL/BXE */ - /* partial: ...but pretty good. we *can't* check nexttok == OP_GRP_RPAR, because + /* PARTIAL: ...but pretty good. we *can't* check nexttok == OP_GRP_RPAR, because VAL(INKEY$) or ASC(INKEY$) are legit Turbo code. This can fail to catch A$(X;Y) if X and Y are both complex expressions. */ if(nexttok == OP_EOS || nexttok == OP_EOL) { @@ -492,6 +499,7 @@ CALLBACK(handle_op) { break; case 0x5a: /* EXOR (infix num op) or BUMP( (pseudo-function, no OP_FUNC_LPAR) */ case 0x5d: /* DIV (infix num op) or RANDOM( (pseudo-func, 1 or 2 num args) */ + /* COMPLETE (I think, anyway) */ if(last_op_tok == OP_GRP_RPAR || last_op_tok == OP_NUMCONST || last_op_tok == OP_HEXCONST || last_op_tok >= 0x80) { /* if the last token was a variable or a numeric, or a right paren, this is infix (can't be a function, last token would have to have @@ -502,7 +510,7 @@ CALLBACK(handle_op) { } break; case 0x5c: /* DEC (function, takes str) in TB, HEX$ (function, takes num) in BXL/BXE */ - /* partial: won't catch HEX$(ASC("A")) (or any other nested function call) */ + /* PARTIAL: won't catch HEX$(ASC("A")) (or any other nested function call) */ if(nexttok2 == OP_STRCONST) { remove_type(BT_BXL_BXE); } else if(nexttok2 == OP_NUMCONST) { @@ -518,7 +526,7 @@ CALLBACK(handle_op) { case 0x5e: /* FRAC (num func, 1 arg) or DPEEK (num func, 1 arg) in BXL... however BXE has an optional 2nd arg. */ { - /* partial: This detects the 2nd arg for simple cases where the + /* PARTIAL: This detects the 2nd arg for simple cases where the 1st arg is a constant or a numeric variable, but not if the 1st arg is an expression or an array element. */ int has2 = 0; @@ -538,6 +546,7 @@ CALLBACK(handle_op) { case 0x60: /* TIME in TB, VSTICK (function) in BXL/BXE */ case 0x61: /* MOD (infix op) in TB, HSTICK (function) in BXL/BXE */ case 0x62: /* EXEC (infix op, with ON) in TB, PMADR (function) in BXL/BXE */ + /* COMPLETE */ if(nexttok == OP_FUNC_LPAR) { remove_type(BT_TURBO); } else { @@ -545,6 +554,7 @@ CALLBACK(handle_op) { } break; case 0x63: /* RND (pseudo-func, no arg) or ERR (func, 1 num arg) */ + /* COMPLETE */ if(nexttok != OP_FUNC_LPAR) { bas_type = BT_TURBO; print_result(); @@ -552,12 +562,13 @@ CALLBACK(handle_op) { case 0x66: /* %0 in TB, LEFT$( (pseudo-func, takes string) in BXL/BXE */ case 0x67: /* %1 in TB, RIGHT$( (pseudo-func, takes string) in BXL/BXE */ case 0x68: /* %2 in TB, MID$( (pseudo-func, takes string) in BXL/BXE */ + /* PARTIAL: doesn't handle LEFT$/etc first arg being a string func. */ if(nexttok == OP_STRCONST || nexttok >= 0x80) { /* %0 %1 %2 can't be followed by a string constant *or* a variable */ remove_type(BT_TURBO); - } else { - /* whereas LEFT$ RIGHT$ MID$ can't be followed by anything else */ - remove_type(BT_BXL_BXE); + /* Can't do, due to LEFT$(HEX$("1234"), 1) (or STR$, etc) */ + /* } else { + remove_type(BT_BXL_BXE); */ } break; default: @@ -593,7 +604,7 @@ CALLBACK(handle_end_stmt) { } break; case 0x42: /* BPUT or RGET */ - /* partial: + /* PARTIAL: Turbo BGET always takes 3 args, BXL/BXE RGET takes 2 or more. We can at least rule out Turbo if there aren't exactly 3 args. */ if(comma_count != 2) { @@ -601,7 +612,7 @@ CALLBACK(handle_end_stmt) { } break; case 0x43: /* BGET or BPUT */ - /* partial: + /* PARTIAL: Turbo BGET and BPUT always take 3 args. So does BXL BPUT. BXE BPUT takes 3 args and an optional 4th. */ if(comma_count != 2) { @@ -616,7 +627,7 @@ CALLBACK(handle_end_stmt) { } break; case 0x61: /* DSOUND (0 or 4 num args) or INVERSE (no args) */ - /* partial: can't tell no-argument DSOUND from INVERSE. */ + /* PARTIAL: can't tell no-argument DSOUND from INVERSE. */ if(comma_count) { remove_type(BT_BXL_BXE); } -- cgit v1.2.3