From d7de9038eb0599232a8840ac48e97d9bb4462ab0 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 8 Jul 2024 17:23:12 -0400 Subject: whichbas: improve BXL/BXE string array detection. Still not 100% perfect. --- whichbas.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/whichbas.c b/whichbas.c index 2b39a44..780af6a 100644 --- a/whichbas.c +++ b/whichbas.c @@ -313,7 +313,7 @@ CALLBACK(handle_op) { DIM A$(10,10) is illegal in Atari/Turbo. partial: this only works if the first dimension is either a constant or a scalar variable (not an array element or an - expression). + expression). fortunately most programs use constants in DIM. */ if(tok == OP_DIM_STR_LPAR) { int str2d = 0; @@ -373,11 +373,26 @@ CALLBACK(handle_op) { } break; case 0x59: /* INKEY$ (0 arg pseudo-func) in TB, string array separator semicolon in BXL/BXE */ - /* TODO: it might be better to detect INKEY$ by looking for end of line - or statement, or OP_ARR_COMMA. INKEY$ can't be followed by anything else, - AFAICT, but I'm not *that* certain yet... */ - if(nexttok == OP_NUMCONST || nexttok == OP_HEXCONST || nexttok >= 0x80) { - /* INKEY$ may not be followed by a numeric constant or a variable of any kind */ + /* 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) { + /* the semicolon can't be the last token on the line (needs at least + a right-paren), but INKEY$ can. */ + remove_type(BT_BXL_BXE); + } else if(pos == last_cmd_pos + 1) { + /* INKEY$ can be the first operator after the command, e.g if the command + is IF. The semicolon cannot. */ + remove_type(BT_BXL_BXE); + } else if(last_op_tok == OP_STR_ASSIGN) { + /* catches A$=INKEY$, for what that's worth. */ + remove_type(BT_BXL_BXE); + } else if(last_op_tok == OP_NUMCONST || last_op_tok == OP_HEXCONST || last_op_tok == OP_STRCONST || last_op_tok >= 0x80) { + /* INKEY$ can't directly follow a constant or a variable. */ + remove_type(BT_TURBO); + } else if(nexttok == OP_NUMCONST || nexttok == OP_HEXCONST || nexttok >= 0x80 || nexttok == OP_GRP_LPAR) { + /* INKEY$ may not be followed by a numeric constant or a variable of any kind, or + a parenthesized expression. */ remove_type(BT_TURBO); } break; @@ -587,9 +602,15 @@ void check_variables(void) { bas_type = BT_TURBO; print_result(); } - /* TODO: check for BXL/BXE string arrays, if I can ever - figure out how to do it. */ } + + /* I was hoping to check for BXL/BXE string arrays here. However, + looking at a SAVEd file, they look identical to regular string + variables (variable type $80, rest of the VVTP entry all $00). + When the program's actually in memory, BXL/BXE sets the + variable type byte to $91 for DIMed string array var and + $81 (same as Atari/Turbo) for a regular DIMed string var. + Unfortunately in the SAVE file, it's always $80. */ } int main(int argc, char **argv) { -- cgit v1.2.3