Phase 1: expression calculator with direct mode
GW-BASIC reimplementation in C11, using Microsoft's open-sourced 8088 assembly as the authoritative reference. Tokenizer (CRUNCH/LIST), expression evaluator with operator precedence, all math functions (SIN, COS, TAN, ATN, SQR, LOG, EXP, RND, etc.), string functions (LEFT$, RIGHT$, MID$, CHR$, ASC, VAL, STR$, etc.), PRINT statement with comma/semicolon zones, TAB(), SPC(). Handles integer/single/double types with correct promotion, D exponent for double-precision literals, type suffixes (%, !, #), &H hex/&O octal literals, MBF conversion routines, and GW-BASIC-compatible number formatting. Platform-independent via HAL vtable; POSIX backend included.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
#ifndef GW_ERROR_H
|
||||
#define GW_ERROR_H
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
/* Error codes matching GW-BASIC's ERRTAB */
|
||||
#define ERR_NF 1 /* NEXT without FOR */
|
||||
#define ERR_SN 2 /* Syntax error */
|
||||
#define ERR_RG 3 /* RETURN without GOSUB */
|
||||
#define ERR_OD 4 /* Out of DATA */
|
||||
#define ERR_FC 5 /* Illegal function call */
|
||||
#define ERR_OV 6 /* Overflow */
|
||||
#define ERR_OM 7 /* Out of memory */
|
||||
#define ERR_UL 8 /* Undefined line number */
|
||||
#define ERR_BS 9 /* Subscript out of range */
|
||||
#define ERR_DD 10 /* Duplicate Definition */
|
||||
#define ERR_DZ 11 /* Division by zero */
|
||||
#define ERR_ID 12 /* Illegal direct */
|
||||
#define ERR_TM 13 /* Type mismatch */
|
||||
#define ERR_OS 14 /* Out of string space */
|
||||
#define ERR_LS 15 /* String too long */
|
||||
#define ERR_ST 16 /* String formula too complex */
|
||||
#define ERR_CN 17 /* Can't continue */
|
||||
#define ERR_UF 18 /* Undefined user function */
|
||||
#define ERR_NR 19 /* No RESUME */
|
||||
#define ERR_RW 20 /* RESUME without error */
|
||||
#define ERR_UE 21 /* Unprintable error */
|
||||
#define ERR_MO 22 /* Missing operand */
|
||||
#define ERR_BO 23 /* Line buffer overflow */
|
||||
#define ERR_DT 24 /* Device Timeout */
|
||||
#define ERR_DF 25 /* Device Fault */
|
||||
#define ERR_FW 26 /* FOR without NEXT */
|
||||
#define ERR_OP 27 /* Out of Paper */
|
||||
#define ERR_WH 29 /* WHILE without WEND */
|
||||
#define ERR_WE 30 /* WEND without WHILE */
|
||||
|
||||
/* Disk errors (starting at 50) */
|
||||
#define ERR_FO 50 /* FIELD overflow */
|
||||
#define ERR_IE 51 /* Internal error */
|
||||
#define ERR_BN 52 /* Bad file number */
|
||||
#define ERR_FF 53 /* File not found */
|
||||
#define ERR_BM 54 /* Bad file mode */
|
||||
#define ERR_AO 56 /* File already open */
|
||||
#define ERR_IO 58 /* Device I/O Error */
|
||||
#define ERR_FE 60 /* File already exists */
|
||||
#define ERR_FL 62 /* Disk full */
|
||||
#define ERR_EF 63 /* Input past end */
|
||||
#define ERR_RN 64 /* Bad record number */
|
||||
#define ERR_NM 65 /* Bad file name */
|
||||
#define ERR_DS 67 /* Direct statement in file */
|
||||
#define ERR_TF 68 /* Too many files */
|
||||
|
||||
const char *gw_error_msg(int errnum);
|
||||
void gw_error(int errnum);
|
||||
|
||||
/* Error recovery jump target - set in main loop */
|
||||
extern jmp_buf gw_error_jmp;
|
||||
extern int gw_errno;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef GW_EVAL_H
|
||||
#define GW_EVAL_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* Expression evaluator - recursive descent with precedence climbing */
|
||||
gw_value_t gw_eval(void); /* evaluate any expression */
|
||||
gw_value_t gw_eval_num(void); /* evaluate, require numeric */
|
||||
gw_value_t gw_eval_str(void); /* evaluate, require string */
|
||||
int16_t gw_eval_int(void); /* evaluate, require integer result */
|
||||
uint16_t gw_eval_uint16(void);
|
||||
|
||||
/* Force type conversions */
|
||||
int16_t gw_to_int(gw_value_t *v);
|
||||
float gw_to_sng(gw_value_t *v);
|
||||
double gw_to_dbl(gw_value_t *v);
|
||||
|
||||
/* Check for closing paren */
|
||||
void gw_expect_rparen(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef GW_MATH_H
|
||||
#define GW_MATH_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* Integer arithmetic with overflow detection */
|
||||
int16_t gw_int_add(int16_t a, int16_t b);
|
||||
int16_t gw_int_sub(int16_t a, int16_t b);
|
||||
int16_t gw_int_mul(int16_t a, int16_t b);
|
||||
int16_t gw_int_div(int16_t a, int16_t b);
|
||||
int16_t gw_int_mod(int16_t a, int16_t b);
|
||||
int16_t gw_int_idiv(int16_t a, int16_t b);
|
||||
int16_t gw_int_neg(int16_t a);
|
||||
|
||||
/* Float operations */
|
||||
double gw_fadd(double a, double b);
|
||||
double gw_fsub(double a, double b);
|
||||
double gw_fmul(double a, double b);
|
||||
double gw_fdiv(double a, double b);
|
||||
double gw_fpow(double base, double exp);
|
||||
double gw_fneg(double a);
|
||||
|
||||
/* Type promotion for binary ops */
|
||||
void gw_promote(gw_value_t *a, gw_value_t *b);
|
||||
|
||||
/* Transcendental functions */
|
||||
double gw_sin(double x);
|
||||
double gw_cos(double x);
|
||||
double gw_tan(double x);
|
||||
double gw_atn(double x);
|
||||
double gw_sqr(double x);
|
||||
double gw_log(double x);
|
||||
double gw_exp(double x);
|
||||
double gw_abs(double x);
|
||||
double gw_sgn(double x);
|
||||
double gw_int_fn(double x);
|
||||
double gw_fix(double x);
|
||||
double gw_rnd(double x);
|
||||
|
||||
/* Conversion functions */
|
||||
int16_t gw_cint(double x);
|
||||
float gw_csng(double x);
|
||||
double gw_cdbl(gw_value_t *v);
|
||||
|
||||
/* MBF conversion (for file I/O compatibility) */
|
||||
float gw_mbf_to_ieee_single(mbf_single_t mbf);
|
||||
double gw_mbf_to_ieee_double(mbf_double_t mbf);
|
||||
mbf_single_t gw_ieee_to_mbf_single(float f);
|
||||
mbf_double_t gw_ieee_to_mbf_double(double d);
|
||||
|
||||
/* Number formatting for PRINT */
|
||||
void gw_format_number(gw_value_t *v, char *buf, int bufsize);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef GWBASIC_H
|
||||
#define GWBASIC_H
|
||||
|
||||
#include "types.h"
|
||||
#include "tokens.h"
|
||||
#include "error.h"
|
||||
#include "hal.h"
|
||||
#include "interp.h"
|
||||
#include "eval.h"
|
||||
#include "gw_math.h"
|
||||
#include "strings.h"
|
||||
|
||||
#define GW_VERSION "0.1.0"
|
||||
#define GW_BANNER "GW-BASIC " GW_VERSION
|
||||
|
||||
/* Tokenizer */
|
||||
int gw_crunch(const char *text, uint8_t *out, int outsize);
|
||||
void gw_list_line(uint8_t *tokens, int len, char *out, int outsize);
|
||||
|
||||
/* PRINT statement */
|
||||
void gw_stmt_print(void);
|
||||
void gw_print_value(gw_value_t *v);
|
||||
void gw_print_newline(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef GW_HAL_H
|
||||
#define GW_HAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Hardware Abstraction Layer vtable */
|
||||
typedef struct hal_ops {
|
||||
/* Terminal I/O */
|
||||
void (*putch)(int ch);
|
||||
void (*puts)(const char *s);
|
||||
int (*getch)(void); /* blocking read */
|
||||
bool (*kbhit)(void); /* key available? */
|
||||
void (*locate)(int row, int col);
|
||||
int (*get_cursor_row)(void);
|
||||
int (*get_cursor_col)(void);
|
||||
void (*cls)(void);
|
||||
void (*set_width)(int cols);
|
||||
|
||||
/* Terminal properties */
|
||||
int screen_width;
|
||||
int screen_height;
|
||||
|
||||
/* Lifecycle */
|
||||
void (*init)(void);
|
||||
void (*shutdown)(void);
|
||||
} hal_ops_t;
|
||||
|
||||
extern hal_ops_t *gw_hal;
|
||||
|
||||
/* Platform implementations */
|
||||
hal_ops_t *hal_posix_create(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef GW_INTERP_H
|
||||
#define GW_INTERP_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Interpreter state - the global context */
|
||||
typedef struct {
|
||||
/* Text pointer (TXTPTR equivalent) */
|
||||
uint8_t *text_ptr;
|
||||
|
||||
/* Current accumulator (FAC equivalent) */
|
||||
gw_value_t fac;
|
||||
|
||||
/* Program state */
|
||||
uint16_t cur_line_num; /* CURLIN - 65535 = direct mode */
|
||||
program_line_t *prog_head; /* first line of program */
|
||||
bool trace_on; /* TRON/TROFF */
|
||||
|
||||
/* Tokenizer buffers */
|
||||
uint8_t kbuf[300]; /* crunch buffer */
|
||||
char buf[256]; /* input line buffer */
|
||||
|
||||
/* Default variable types for A-Z (DEFTBL) */
|
||||
gw_valtype_t def_type[26];
|
||||
|
||||
/* DATA pointer */
|
||||
uint8_t *data_ptr;
|
||||
uint16_t data_line;
|
||||
} interp_state_t;
|
||||
|
||||
extern interp_state_t gw;
|
||||
|
||||
/* Direct mode line number sentinel */
|
||||
#define LINE_DIRECT 65535
|
||||
|
||||
void gw_init(void);
|
||||
void gw_exec_line(uint8_t *tokens);
|
||||
void gw_exec_direct(const char *line);
|
||||
|
||||
/* CHRGET/CHRGOT - advance/peek the text pointer */
|
||||
uint8_t gw_chrget(void);
|
||||
uint8_t gw_chrgot(void);
|
||||
void gw_skip_spaces(void);
|
||||
bool gw_is_letter(uint8_t ch);
|
||||
bool gw_is_digit(uint8_t ch);
|
||||
|
||||
/* Expect a specific token, else syntax error */
|
||||
void gw_expect(uint8_t tok);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef GW_STRINGS_H
|
||||
#define GW_STRINGS_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* String creation/management */
|
||||
gw_string_t gw_str_alloc(int len);
|
||||
gw_string_t gw_str_from_cstr(const char *s);
|
||||
gw_string_t gw_str_copy(gw_string_t *s);
|
||||
void gw_str_free(gw_string_t *s);
|
||||
char *gw_str_to_cstr(gw_string_t *s); /* caller must free */
|
||||
|
||||
/* String functions */
|
||||
gw_value_t gw_fn_len(gw_value_t *s);
|
||||
gw_value_t gw_fn_left(gw_value_t *s, int n);
|
||||
gw_value_t gw_fn_right(gw_value_t *s, int n);
|
||||
gw_value_t gw_fn_mid(gw_value_t *s, int start, int len);
|
||||
gw_value_t gw_fn_chr(int code);
|
||||
gw_value_t gw_fn_asc(gw_value_t *s);
|
||||
gw_value_t gw_fn_val(gw_value_t *s);
|
||||
gw_value_t gw_fn_str(gw_value_t *v);
|
||||
gw_value_t gw_fn_space(int n);
|
||||
gw_value_t gw_fn_strings(int n, int code);
|
||||
gw_value_t gw_fn_instr(int start, gw_value_t *haystack, gw_value_t *needle);
|
||||
gw_value_t gw_fn_hex(int16_t n);
|
||||
gw_value_t gw_fn_oct(int16_t n);
|
||||
|
||||
/* Concatenation */
|
||||
gw_value_t gw_str_concat(gw_value_t *a, gw_value_t *b);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
#ifndef GW_TOKENS_H
|
||||
#define GW_TOKENS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Token values derived from IBMRES.ASM.
|
||||
* Single-byte tokens: 0x80-0xF9
|
||||
* Two-byte tokens: 0xFD xx (extended functions), 0xFE xx (extended stmts),
|
||||
* 0xFF xx (built-in functions)
|
||||
*/
|
||||
|
||||
/* Statement tokens (STMDSP) - starting at 128 */
|
||||
#define TOK_END 0x80 /* 128 */
|
||||
#define TOK_FOR 0x81 /* 129 */
|
||||
#define TOK_NEXT 0x82 /* 130 */
|
||||
#define TOK_DATA 0x83 /* 131 */
|
||||
#define TOK_INPUT 0x84 /* 132 */
|
||||
#define TOK_DIM 0x85 /* 133 */
|
||||
#define TOK_READ 0x86 /* 134 */
|
||||
#define TOK_LET 0x87 /* 135 */
|
||||
#define TOK_GOTO 0x88 /* 136 */
|
||||
#define TOK_RUN 0x89 /* 137 */
|
||||
#define TOK_IF 0x8A /* 138 */
|
||||
#define TOK_RESTORE 0x8B /* 139 */
|
||||
#define TOK_GOSUB 0x8C /* 140 */
|
||||
#define TOK_RETURN 0x8D /* 141 */
|
||||
#define TOK_REM 0x8E /* 142 */
|
||||
#define TOK_STOP 0x8F /* 143 */
|
||||
#define TOK_PRINT 0x90 /* 144 */
|
||||
#define TOK_CLEAR 0x91 /* 145 */
|
||||
#define TOK_LIST 0x92 /* 146 */
|
||||
#define TOK_NEW 0x93 /* 147 */
|
||||
#define TOK_ON 0x94 /* 148 */
|
||||
#define TOK_WAIT 0x95 /* 149 */
|
||||
#define TOK_DEF 0x96 /* 150 */
|
||||
#define TOK_POKE 0x97 /* 151 */
|
||||
#define TOK_CONT 0x98 /* 152 */
|
||||
/* 153-154: padding (SNERR) */
|
||||
#define TOK_OUT 0x9B /* 155 */
|
||||
#define TOK_LPRINT 0x9C /* 156 */
|
||||
#define TOK_LLIST 0x9D /* 157 */
|
||||
/* 158: padding */
|
||||
#define TOK_WIDTH 0x9F /* 159 */
|
||||
#define TOK_ELSE 0xA0 /* 160 */
|
||||
#define TOK_TRON 0xA1 /* 161 */
|
||||
#define TOK_TROFF 0xA2 /* 162 */
|
||||
#define TOK_SWAP 0xA3 /* 163 */
|
||||
#define TOK_ERASE 0xA4 /* 164 */
|
||||
#define TOK_EDIT 0xA5 /* 165 */
|
||||
#define TOK_ERROR 0xA6 /* 166 */
|
||||
#define TOK_RESUME 0xA7 /* 167 */
|
||||
#define TOK_DELETE 0xA8 /* 168 */
|
||||
#define TOK_AUTO 0xA9 /* 169 */
|
||||
#define TOK_RENUM 0xAA /* 170 */
|
||||
#define TOK_DEFSTR 0xAB /* 171 */
|
||||
#define TOK_DEFINT 0xAC /* 172 */
|
||||
#define TOK_DEFSNG 0xAD /* 173 */
|
||||
#define TOK_DEFDBL 0xAE /* 174 */
|
||||
#define TOK_LINE 0xAF /* 175 */
|
||||
#define TOK_WHILE 0xB0 /* 176 */
|
||||
#define TOK_WEND 0xB1 /* 177 */
|
||||
#define TOK_CALL 0xB2 /* 178 */
|
||||
/* 179-181: padding */
|
||||
#define TOK_WRITE 0xB6 /* 182 */
|
||||
#define TOK_OPTION 0xB7 /* 183 */
|
||||
#define TOK_RANDOMIZE 0xB8 /* 184 */
|
||||
#define TOK_OPEN 0xB9 /* 185 */
|
||||
#define TOK_CLOSE 0xBA /* 186 */
|
||||
#define TOK_LOAD 0xBB /* 187 */
|
||||
#define TOK_MERGE 0xBC /* 188 */
|
||||
#define TOK_SAVE 0xBD /* 189 */
|
||||
#define TOK_COLOR 0xBE /* 190 */
|
||||
#define TOK_CLS 0xBF /* 191 */
|
||||
#define TOK_MOTOR 0xC0 /* 192 */
|
||||
#define TOK_BSAVE 0xC1 /* 193 */
|
||||
#define TOK_BLOAD 0xC2 /* 194 */
|
||||
#define TOK_SOUND 0xC3 /* 195 */
|
||||
#define TOK_BEEP 0xC4 /* 196 */
|
||||
#define TOK_PSET 0xC5 /* 197 */
|
||||
#define TOK_PRESET 0xC6 /* 198 */
|
||||
#define TOK_SCREEN 0xC7 /* 199 */
|
||||
#define TOK_KEY 0xC8 /* 200 */
|
||||
#define TOK_LOCATE 0xC9 /* 201 */
|
||||
|
||||
/* Non-statement keyword tokens */
|
||||
#define TOK_TO 0xCA /* 202 */
|
||||
#define TOK_THEN 0xCB /* 203 */
|
||||
#define TOK_TAB 0xCC /* 204 */
|
||||
#define TOK_STEP 0xCD /* 205 */
|
||||
#define TOK_USR 0xCE /* 206 */
|
||||
#define TOK_FN 0xCF /* 207 */
|
||||
#define TOK_SPC 0xD0 /* 208 */
|
||||
#define TOK_NOT 0xD1 /* 209 */
|
||||
#define TOK_ERL 0xD2 /* 210 */
|
||||
#define TOK_ERR 0xD3 /* 211 */
|
||||
#define TOK_STRINGS 0xD4 /* 212 - STRING$ */
|
||||
#define TOK_USING 0xD5 /* 213 */
|
||||
#define TOK_INSTR 0xD6 /* 214 */
|
||||
#define TOK_SQUOTE 0xD7 /* 215 - ' (single quote = REM) */
|
||||
#define TOK_VARPTR 0xD8 /* 216 */
|
||||
#define TOK_CSRLIN 0xD9 /* 217 */
|
||||
#define TOK_POINT 0xDA /* 218 */
|
||||
#define TOK_OFF 0xDB /* 219 */
|
||||
#define TOK_INKEYS 0xDC /* 220 - INKEY$ */
|
||||
|
||||
/* Operator tokens (after 7-byte gap at 221-227) */
|
||||
#define TOK_GT 0xE4 /* 228 - > */
|
||||
#define TOK_EQ 0xE5 /* 229 - = */
|
||||
#define TOK_LT 0xE6 /* 230 - < */
|
||||
#define TOK_PLUS 0xE7 /* 231 - + */
|
||||
#define TOK_MINUS 0xE8 /* 232 - - */
|
||||
#define TOK_MUL 0xE9 /* 233 - * */
|
||||
#define TOK_DIV 0xEA /* 234 - / */
|
||||
#define TOK_POW 0xEB /* 235 - ^ */
|
||||
#define TOK_AND 0xEC /* 236 */
|
||||
#define TOK_OR 0xED /* 237 */
|
||||
#define TOK_XOR 0xEE /* 238 */
|
||||
#define TOK_EQV 0xEF /* 239 */
|
||||
#define TOK_IMP 0xF0 /* 240 */
|
||||
#define TOK_MOD 0xF1 /* 241 */
|
||||
#define TOK_IDIV 0xF2 /* 242 - \ (integer division) */
|
||||
|
||||
/* Multi-byte token prefixes */
|
||||
#define TOK_PREFIX_FD 0xFD /* extended functions */
|
||||
#define TOK_PREFIX_FE 0xFE /* extended statements */
|
||||
#define TOK_PREFIX_FF 0xFF /* built-in functions */
|
||||
|
||||
/* Built-in function tokens (prefix 0xFF) */
|
||||
#define FUNC_LEFT 0x80 /* 128 */
|
||||
#define FUNC_RIGHT 0x81 /* 129 */
|
||||
#define FUNC_MID 0x82 /* 130 */
|
||||
#define FUNC_SGN 0x83 /* 131 */
|
||||
#define FUNC_INT 0x84 /* 132 */
|
||||
#define FUNC_ABS 0x85 /* 133 */
|
||||
#define FUNC_SQR 0x86 /* 134 */
|
||||
#define FUNC_RND 0x87 /* 135 */
|
||||
#define FUNC_SIN 0x88 /* 136 */
|
||||
#define FUNC_LOG 0x89 /* 137 */
|
||||
#define FUNC_EXP 0x8A /* 138 */
|
||||
#define FUNC_COS 0x8B /* 139 */
|
||||
#define FUNC_TAN 0x8C /* 140 */
|
||||
#define FUNC_ATN 0x8D /* 141 */
|
||||
#define FUNC_FRE 0x8E /* 142 */
|
||||
#define FUNC_INP 0x8F /* 143 */
|
||||
#define FUNC_POS 0x90 /* 144 */
|
||||
#define FUNC_LEN 0x91 /* 145 */
|
||||
#define FUNC_STR 0x92 /* 146 */
|
||||
#define FUNC_VAL 0x93 /* 147 */
|
||||
#define FUNC_ASC 0x94 /* 148 */
|
||||
#define FUNC_CHR 0x95 /* 149 */
|
||||
#define FUNC_PEEK 0x96 /* 150 */
|
||||
#define FUNC_SPACE 0x97 /* 151 */
|
||||
#define FUNC_OCT 0x98 /* 152 */
|
||||
#define FUNC_HEX 0x99 /* 153 */
|
||||
#define FUNC_LPOS 0x9A /* 154 */
|
||||
#define FUNC_CINT 0x9B /* 155 */
|
||||
#define FUNC_CSNG 0x9C /* 156 */
|
||||
#define FUNC_CDBL 0x9D /* 157 */
|
||||
#define FUNC_FIX 0x9E /* 158 */
|
||||
#define FUNC_PEN 0x9F /* 159 */
|
||||
#define FUNC_STICK 0xA0 /* 160 */
|
||||
#define FUNC_STRIG 0xA1 /* 161 */
|
||||
#define FUNC_EOF 0xA2 /* 162 */
|
||||
#define FUNC_LOC 0xA3 /* 163 */
|
||||
#define FUNC_LOF 0xA4 /* 164 */
|
||||
|
||||
/* Extended statement tokens (prefix 0xFE) */
|
||||
#define XSTMT_FILES 0x80
|
||||
#define XSTMT_FIELD 0x81
|
||||
#define XSTMT_SYSTEM 0x82
|
||||
#define XSTMT_NAME 0x83
|
||||
#define XSTMT_LSET 0x84
|
||||
#define XSTMT_RSET 0x85
|
||||
#define XSTMT_KILL 0x86
|
||||
#define XSTMT_PUT 0x87
|
||||
#define XSTMT_GET 0x88
|
||||
#define XSTMT_RESET 0x89
|
||||
#define XSTMT_COMMON 0x8A
|
||||
#define XSTMT_CHAIN 0x8B
|
||||
#define XSTMT_DATE 0x8C
|
||||
#define XSTMT_TIME 0x8D
|
||||
#define XSTMT_PAINT 0x8E
|
||||
#define XSTMT_COM 0x8F
|
||||
#define XSTMT_CIRCLE 0x90
|
||||
#define XSTMT_DRAW 0x91
|
||||
#define XSTMT_PLAY 0x92
|
||||
#define XSTMT_TIMER 0x93
|
||||
#define XSTMT_ERDEV 0x94
|
||||
#define XSTMT_IOCTL 0x95
|
||||
#define XSTMT_CHDIR 0x96
|
||||
#define XSTMT_MKDIR 0x97
|
||||
#define XSTMT_RMDIR 0x98
|
||||
#define XSTMT_SHELL 0x99
|
||||
#define XSTMT_ENVIRON 0x9A
|
||||
#define XSTMT_VIEW 0x9B
|
||||
#define XSTMT_WINDOW 0x9C
|
||||
#define XSTMT_PMAP 0x9D
|
||||
#define XSTMT_PALETTE 0x9E
|
||||
#define XSTMT_LCOPY 0x9F
|
||||
#define XSTMT_CALLS 0xA0
|
||||
|
||||
/* Extended function tokens (prefix 0xFD) */
|
||||
#define XFUNC_CVI 0x80
|
||||
#define XFUNC_CVS 0x81
|
||||
#define XFUNC_CVD 0x82
|
||||
#define XFUNC_MKI 0x83
|
||||
#define XFUNC_MKS 0x84
|
||||
#define XFUNC_MKD 0x85
|
||||
|
||||
/* Special token constants - embedded constant prefixes */
|
||||
#define TOK_COLON ':' /* statement separator (not tokenized) */
|
||||
#define TOK_INT2 0x0E /* 2-byte integer (int16_t follows) */
|
||||
#define TOK_INT1 0x0F /* 1-byte integer 0-255 (uint8_t follows) */
|
||||
/* 0x11-0x1A: literal integers 0-9 (no data bytes) */
|
||||
#define TOK_CONST_SNG 0x1C /* single-precision (4 bytes IEEE follow) */
|
||||
#define TOK_CONST_DBL 0x1F /* double-precision (8 bytes IEEE follow) */
|
||||
|
||||
/* Keyword table entry */
|
||||
typedef struct {
|
||||
const char *name;
|
||||
uint8_t token; /* token value (or second byte for multi-byte) */
|
||||
uint8_t prefix; /* 0 for single-byte, 0xFD/0xFE/0xFF for multi */
|
||||
} keyword_entry_t;
|
||||
|
||||
extern const keyword_entry_t gw_keywords[];
|
||||
extern int gw_keyword_count;
|
||||
|
||||
const char *gw_token_name(uint8_t prefix, uint8_t token);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef GW_TYPES_H
|
||||
#define GW_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Value types matching GW-BASIC's VALTYP */
|
||||
typedef enum {
|
||||
VT_INT = 2, /* 16-bit integer (%) */
|
||||
VT_SNG = 4, /* single precision (!) */
|
||||
VT_DBL = 8, /* double precision (#) */
|
||||
VT_STR = 3, /* string ($) */
|
||||
} gw_valtype_t;
|
||||
|
||||
/* String descriptor - matches original's 3-byte layout concept */
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
char *data; /* malloc'd, NOT null-terminated */
|
||||
} gw_string_t;
|
||||
|
||||
/* Unified value - the FAC (floating accumulator) equivalent */
|
||||
typedef struct {
|
||||
gw_valtype_t type;
|
||||
union {
|
||||
int16_t ival;
|
||||
float fval;
|
||||
double dval;
|
||||
gw_string_t sval;
|
||||
};
|
||||
} gw_value_t;
|
||||
|
||||
/* Program line stored in memory */
|
||||
typedef struct program_line {
|
||||
struct program_line *next;
|
||||
uint16_t num; /* line number 0-65529 */
|
||||
uint16_t len; /* token data length */
|
||||
uint8_t *tokens; /* tokenized line data */
|
||||
} program_line_t;
|
||||
|
||||
/* Variable entry */
|
||||
typedef struct {
|
||||
char name[2]; /* 2-char name (original GW-BASIC limit) */
|
||||
gw_valtype_t type;
|
||||
gw_value_t val;
|
||||
} var_entry_t;
|
||||
|
||||
/* MBF (Microsoft Binary Format) types for file compatibility */
|
||||
typedef struct {
|
||||
uint8_t mantissa[3];
|
||||
uint8_t exponent;
|
||||
} mbf_single_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t mantissa[7];
|
||||
uint8_t exponent;
|
||||
} mbf_double_t;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user