diff --git a/src/basic.c b/src/basic.c index 3183c62..8d61609 100644 --- a/src/basic.c +++ b/src/basic.c @@ -17,7 +17,8 @@ char *_tokenizer_prev; char *_tokenizer_prev_next; char basic_memory_lines[BASIC_MAX_LINES][BASIC_MAX_LINE_LENGTH]; char decimal[32]; - +char const_string_test[255]; + void basic_report_error(char *prefix) { memset((char *)&decimal, 0x00, 32); @@ -45,7 +46,12 @@ void basic_cmd_list(void *data) char *lineptr = NULL; i = 0; - _cputs("OMG WTF BBQ\n"); + /* I don't know why, but somehow, this makes the interspersed _cputs() calls below work. + * Take this out, and those lines stop working. + * WHAT. THE. FUCK. + */ + memcpy((char *)&const_string_test, (char *)"OMG WTF BBQ\n\0", strlen("OMG WTF BBQ\n\0")); + _cputs((char *)&const_string_test); for ( i = 0; i <= limit ; i++ ) { lineptr = basic_memory_line_address(i); if ( lineptr == NULL ) { @@ -70,19 +76,7 @@ void basic_cmd_print(void *data) return; } - expr = basic_parse_expr((char *)data, 0); - if ( expr == NULL ) { - basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER; - return; - } - - memset((void *)&result, 0x00, sizeof(struct basic_variable)); - basic_solve_expr(expr, &result); - if ( basic_errno != 0 ) { - return; - } else { - basic_print_var(&result); - } + _cputs((char *)data); } void basic_cmd_run(void *data) @@ -192,11 +186,14 @@ int basic_memory_line_store(char *content, int lineno) dest = basic_memory_line_address(lineno); if ( lineno > basic_last_stored_lineno ) { - /* The memory between here and there is probably uninitialized. When we come back + /* + * basic_last_stored_lineno only every grows upward (even if you go back and edit a line or insert one). + * The memory between here (new line) and there (last line) is probably uninitialized. When we come back * through to LIST those lines later we may find garbage. Let's clean it up. */ for ( i = basic_last_stored_lineno+1; i <= lineno ; i++ ) { ptr = basic_memory_line_address(i); + /* We don't need to zero the entire string, just the first character, don't waste time */ memset(ptr, 0x00, BASIC_MAX_LINE_LENGTH); } } @@ -209,232 +206,6 @@ int basic_memory_line_store(char *content, int lineno) basic_last_stored_lineno = lineno; } -int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result) -{ - if ( expr == NULL || result == NULL ) { - basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER; - return 0; - } - - switch (expr->type) { - case BASIC_OPTP_NONE: - if ( expr->lval_type == BASIC_LVAL_CONST_INT ) { - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value.i = expr->lval.i; - } else if ( expr->lval_type == BASIC_LVAL_CONST_STR ) { - result->flags = (result->flags | BASIC_VARFLAG_TSTR | BASIC_VARFLAG_INIT); - result->value.str = (char *)expr->lval.ptr; - } else { - basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED; - return 0; - } - break; - case BASIC_OPTP_ADD: - if ( expr->lval_type != BASIC_LVAL_CONST_INT || - ( expr->rval_type != BASIC_RVAL_CONST_INT ) ) { - basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value.i = expr->lval.i + expr->rval.i; - break; - case BASIC_OPTP_SUB: - if ( expr->lval_type != BASIC_LVAL_CONST_INT || - ( expr->rval_type != BASIC_RVAL_CONST_INT ) ) { - basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value.i = expr->lval.i - expr->rval.i; - break; - case BASIC_OPTP_MUL: - if ( expr->lval_type != BASIC_LVAL_CONST_INT || - ( expr->rval_type != BASIC_RVAL_CONST_INT ) ) { - basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value.i = expr->lval.i * expr->rval.i; - break; - case BASIC_OPTP_DIV: - if ( expr->lval_type != BASIC_LVAL_CONST_INT || - ( expr->rval_type != BASIC_RVAL_CONST_INT ) ) { - basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return 0; - } - if ( expr->rval.i == 0) { - basic_errno = BASIC_ERR_MATH_DBZ; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value.i = expr->lval.i / expr->rval.i; - break; - case BASIC_OPTP_MOD: - if ( expr->lval_type != BASIC_LVAL_CONST_INT || - ( expr->rval_type != BASIC_RVAL_CONST_INT ) ) { - basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return 0; - } - if ( expr->rval.i == 0) { - basic_errno = BASIC_ERR_MATH_DBZ; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value.i = (expr->lval.i) - ((expr->lval.i / expr->rval.i)*expr->rval.i); - break; - case BASIC_OPTP_EQL: - if ( expr->lval_type != BASIC_LVAL_CONST_INT || - ( expr->rval_type != BASIC_RVAL_CONST_INT ) ) { - basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - if (expr->lval.i == expr->rval.i) { - result->value.i = BASIC_CONST_TRUE; - } else { - result->value.i = BASIC_CONST_FALSE; - } - break; - case BASIC_OPTP_STOR: - /* this funky pointer dereferencing is to make bcc happy, it can't - * manage indexing the array and dereferencing that */ - if ( memcpy( - basic_memory_line_address(expr->lval.i-1), - (char *)expr->rval.ptr, - strlen((char *)expr->rval.ptr) - ) == NULL ) { - basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER; - return 0; - } - result->flags = (result->flags | BASIC_VARFLAG_TSTR | BASIC_VARFLAG_INIT); - result->value.ptr = BASIC_MESSAGE_OK; - basic_last_stored_lineno = expr->lval.i-1; - break; - case BASIC_OPTP_ASN: - basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED; - return 0; - default: - basic_errno = BASIC_ERR_INTERNAL_UNDEFINED_BEHAVIOR; - return 0; - } - return 1; -} - -struct basic_expr *basic_parse_expr(char *expbuf, int require_line_numbers) -{ - struct basic_expr *ret = &math_expressions[0]; - char *token = NULL; - char flags = 0; - if ( require_line_numbers == 1 ) { - flags = BASIC_PARSE_FIRSTTOKEN; - } - - /*char *subptr = 0;*/ - - _tokenizer_init(); - memset(ret, 0x0, sizeof(struct basic_expr)); - - while ( *expbuf != '\0' ) { - if ( *expbuf == ' ' ) { - expbuf += 1; - continue; - } - - expbuf = _tokenize(expbuf, " "); - token = tokenizer_token(); - if ( isdigit(*token) == 1 ) { - if ( flags == BASIC_PARSE_FIRSTTOKEN ) { - ret->type = BASIC_OPTP_STOR; - ret->lval_type = BASIC_LVAL_CONST_INT; - ret->lval.i = atoi(token); - ret->rval.ptr = expbuf; - ret->rval_type = BASIC_RVAL_PTR; - break; - } - if ( (ret->type == 0) && (flags & BASIC_PARSE_FOUND_LVAL) == BASIC_PARSE_FOUND_LVAL ) { - basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_LVALUES; - return NULL; - } else if ( ret->type == 0x0 ) { - ret->lval.i = atoi(token); - ret->lval_type = BASIC_LVAL_CONST_INT; - flags = (flags | BASIC_PARSE_FOUND_LVAL); - } else if ( ret->type != 0x0 && ((flags & BASIC_PARSE_FOUND_RVAL) == BASIC_PARSE_FOUND_RVAL)) { - basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_RVALUES; - return NULL; - } else if ( ret->type != 0x0 ) { - ret->rval.i = atoi(token); - ret->rval_type = BASIC_RVAL_CONST_INT; - } - } else if ( token != NULL && ret->type == 0x0 ) { - if ( flags == BASIC_PARSE_FIRSTTOKEN ) { - basic_errno = BASIC_ERR_SYNTAX_NO_LINE_NUMBER; - } - switch ( *token ) { - case '+': - ret->type = BASIC_OPTP_ADD; - break; - case '*': - ret->type = BASIC_OPTP_MUL; - break; - case '-': - ret->type = BASIC_OPTP_SUB; - break; - case '/': - ret->type = BASIC_OPTP_DIV; - break; - case '%': - ret->type = BASIC_OPTP_MOD; - break; - default: - /* see if a command will claim this token */ - if ( strcmp(token, "REM") == 0 ) { - ret->type = BASIC_OPTP_CMD; - ret->lval_type = BASIC_LVAL_CMDPTR; - ret->lval.cmd_ptr = basic_cmd_rem; - ret->rval_type = BASIC_RVAL_NONE; - return ret; - } else if ( strcmp(token, "PRINT") == 0 ) { - ret->type = BASIC_OPTP_CMD; - ret->lval_type = BASIC_LVAL_CMDPTR; - ret->lval.cmd_ptr = basic_cmd_print; - ret->rval_type = BASIC_RVAL_PTR; - ret->rval.ptr = expbuf; - return ret; - } else if ( strcmp(token, "LIST") == 0 ) { - ret->type = BASIC_OPTP_CMD; - ret->lval_type = BASIC_LVAL_CMDPTR; - ret->lval.cmd_ptr = basic_cmd_list; - ret->rval_type = BASIC_RVAL_PTR; - ret->rval.ptr = expbuf; - return ret; - } else if ( strcmp(token, "RUN") == 0 ) { - ret->type = BASIC_OPTP_CMD; - ret->lval_type = BASIC_LVAL_CMDPTR; - ret->lval.cmd_ptr = basic_cmd_run; - ret->rval_type = BASIC_RVAL_PTR; - ret->rval.ptr = expbuf; - return ret; - } else { - /* - * For now just treat it like a string constant and we'll improve this later - * - * basic_errno = BASIC_ERR_SYNTAX_GENERAL; - * return NULL; - */ - ret->lval_type = BASIC_LVAL_CONST_STR; - ret->lval.ptr = expbuf - strlen(token); - return ret; - break; - } - } - } else { - basic_errno = BASIC_ERR_SYNTAX_GENERAL; - return NULL; - } - } - return ret; -} - int basic_run_line_v2(char *codeline, int repl_mode) { char *buffptr; @@ -484,52 +255,6 @@ int basic_run_line_v2(char *codeline, int repl_mode) return 0; } -int basic_run_line(char *codeline, int repl_mode) -{ - /* - * If we are running in repl mode we look for line numbers, THEN we check for immediate mode commands - * If not in repl mode we just check for immediate mode - * Then we give up - */ - basic_expr *expr = NULL; - basic_variable result; - memset(&result, 0x00, sizeof(basic_variable)); - - if ( repl_mode == 1 ) { - expr = basic_parse_expr(codeline, 1); - if ( basic_errno == BASIC_ERR_SYNTAX_NO_LINE_NUMBER ) { - basic_errno = 0; - _cputs("No line number, parsing with require_line_numbers=0\n"); - expr = basic_parse_expr(codeline, 0); - } - } else { - expr = basic_parse_expr(codeline, 0); - } - if ( expr == NULL ) { - basic_report_error("Parsing error: "); - return 1; - } - if ( expr->lval_type == BASIC_LVAL_CMDPTR ) { - if ( expr->lval.cmd_ptr == NULL ) { - basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER; - basic_report_error("Solving error: "); - return 1; - } else { - (*expr->lval.cmd_ptr)(expr->rval.ptr); - if ( basic_errno != 0 ) { - basic_report_error("Command error: "); - return 1; - } - } - } else { - if ( basic_solve_expr(expr, &result) != 1 || basic_errno != 0 ) { - basic_report_error("Solving error: "); - return 1; - } - } - return 0; -} - /*************************************************************** * * Basic REPL @@ -571,10 +296,10 @@ void basic_repl(void) _cputs("READY\n"); basic_repl_mode = 1; - /*basic_memory_line_store("LIST", 10); + basic_memory_line_store("LIST", 10); basic_memory_line_store("PRINT HELLO\n", 20); basic_memory_line_store("PRINT WORLD\n", 30); - basic_memory_line_store("PRINT GOODBYE\n", 40);*/ + basic_memory_line_store("PRINT GOODBYE\n", 40); while ( 1 ) { basic_errno = 0;