diff --git a/HISTORY b/HISTORY index a75d1ad..e31c71f 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,7 @@ +Sep. 18 2015 +Fixed a float number parsing bug, thanks to Cybermonkey342 for pointing it out +Added directly expression evaluation shell command + Sep. 17 2015 Allowed string in a boolean expression Added support for sub routine in PRINT diff --git a/core/my_basic.c b/core/my_basic.c index b06c568..7524d7b 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -79,7 +79,7 @@ extern "C" { /** Macros */ #define _VER_MAJOR 1 #define _VER_MINOR 1 -#define _VER_REVISION 70 +#define _VER_REVISION 71 #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) /* Uncomment the line below to treat warning as error */ diff --git a/core/my_basic.h b/core/my_basic.h index 7e78716..92a4d82 100755 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -50,18 +50,9 @@ extern "C" { # define MB_ENABLE_SOURCE_TRACE #endif /* MB_ENABLE_SOURCE_TRACE */ -#ifndef MB_COMPACT_MODE -# define MB_COMPACT_MODE -#endif /* MB_COMPACT_MODE */ - -#ifdef MB_COMPACT_MODE -# pragma pack(1) -#endif /* MB_COMPACT_MODE */ - #ifndef MB_CONVERT_TO_INT_LEVEL_NONE # define MB_CONVERT_TO_INT_LEVEL_NONE 0 #endif /* MB_CONVERT_TO_INT_LEVEL_NONE */ - #ifndef MB_CONVERT_TO_INT_LEVEL_ALL # define MB_CONVERT_TO_INT_LEVEL_ALL 1 #endif /* MB_CONVERT_TO_INT_LEVEL_ALL */ @@ -70,6 +61,14 @@ extern "C" { # define MB_CONVERT_TO_INT_LEVEL MB_CONVERT_TO_INT_LEVEL_ALL #endif /* MB_CONVERT_TO_INT_LEVEL */ +#ifndef MB_COMPACT_MODE +# define MB_COMPACT_MODE +#endif /* MB_COMPACT_MODE */ + +#ifdef MB_COMPACT_MODE +# pragma pack(1) +#endif /* MB_COMPACT_MODE */ + #ifndef true # define true (!0) #endif /* true */ @@ -261,6 +260,7 @@ typedef enum mb_data_e { MB_DT_REAL = 1 << 2, MB_DT_STRING = 1 << 3, MB_DT_USERTYPE = 1 << 4, + MB_DT_CLASS = 1 << 5, MB_DT_ARRAY = 1 << 12 } mb_data_e; @@ -269,6 +269,7 @@ typedef union mb_value_u { real_t float_point; char* string; void* usertype; + void* instance; void* array; } mb_value_u; diff --git a/output/my_basic.exe b/output/my_basic.exe index 7f62e4a..a0e1d7d 100755 Binary files a/output/my_basic.exe and b/output/my_basic.exe differ diff --git a/output/my_basic_mac b/output/my_basic_mac index 3e26a1b..02742a3 100755 Binary files a/output/my_basic_mac and b/output/my_basic_mac differ diff --git a/resource/my_basic.rc b/resource/my_basic.rc index df6167d..bc1e56b 100755 --- a/resource/my_basic.rc +++ b/resource/my_basic.rc @@ -36,8 +36,8 @@ IDI_ICON_MAIN ICON "icon.ico" VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,70,0 - PRODUCTVERSION 1,1,70,0 + FILEVERSION 1,1,71,0 + PRODUCTVERSION 1,1,71,0 FILEFLAGSMASK 0x17L # ifdef _DEBUG FILEFLAGS 0x1L @@ -55,13 +55,13 @@ VALUE "Comments", "MY-BASIC" VALUE "CompanyName", "Wang Renxin" VALUE "FileDescription", "MY-BASIC Interpreter for Windows" - VALUE "FileVersion", "1, 1, 70, 0" + VALUE "FileVersion", "1, 1, 71, 0" VALUE "InternalName", "my_basic" VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin" VALUE "LegalTrademarks", "MY-BASIC" VALUE "OriginalFilename", "my_basic.exe" VALUE "ProductName", "MY-BASIC" - VALUE "ProductVersion", "1, 1, 70, 0" + VALUE "ProductVersion", "1, 1, 71, 0" END END BLOCK "VarFileInfo" diff --git a/shell/main.c b/shell/main.c index be8041a..9db9459 100755 --- a/shell/main.c +++ b/shell/main.c @@ -63,6 +63,14 @@ ** Common declarations */ +#ifdef _MSC_VER +# define _BIN_FILE_NAME "my_basic" +#elif defined __APPLE__ +# define _BIN_FILE_NAME "my_basic_mac" +#else +# define _BIN_FILE_NAME "my_basic_bin" +#endif + #define _USE_MEM_POOL /* Comment this macro to disable memory pool */ #define _MAX_LINE_LENGTH 256 @@ -527,14 +535,14 @@ static void _load_program(const char* path) { printf("Load done. %d lines loaded.\n", c->count); } } else { - printf("Cannot load file \"%s\"\n", path); + printf("Cannot load file \"%s\".\n", path); } } static void _save_program(const char* path) { char* txt = _get_code(c); if(!_save_file(path, txt)) { - printf("Cannot save file \"%s\"\n", path); + printf("Cannot save file \"%s\".\n", path); } else { if(c->count == 1) { printf("Save done. %d line saved.\n", c->count); @@ -561,7 +569,11 @@ static void _show_tip(void) { } static void _show_help(void) { - printf("Commands:\n"); + printf("Parameters:\n"); + printf(" %s - Start interactive mode without arguments.\n", _BIN_FILE_NAME); + printf(" %s *.* - Load and run a file.\n", _BIN_FILE_NAME); + printf(" %s -e \"expr\" - Evaluate an expression directly.\n", _BIN_FILE_NAME); + printf("Interactive commands:\n"); printf(" CLS - Clear screen\n"); printf(" NEW - Clear current program\n"); printf(" RUN - Run current program\n"); @@ -647,6 +659,100 @@ static int _do_line(void) { /* ========================================================} */ +/* +** {======================================================== +** Parameter processing +*/ + +#define _CHECK_ARG(__c, __i, __e) \ + do { \ + if(__c <= __i + 1) { \ + printf(__e); \ + return; \ + } \ + } while(0) + +static void _run_file(char* path) { + if(mb_load_file(bas, path) == MB_FUNC_OK) { + mb_run(bas); + } else { + printf("Invalid file or error code.\n"); + } +} + +static void _evaluate_expression(char* p) { + char pr[8]; + int l = 0; + int k = 0; + bool_t a = true; + char* e = 0; + + const char* const print = "PRINT "; + + if(!p) { + printf("Invalid expression.\n"); + + return; + } + + l = (int)strlen(p); + k = (int)strlen(print); + if(l >= k) { + memcpy(pr, p, k); + pr[k] = '\0'; + if(_str_eq(pr, print)) + a = false; + } + if(a) { + e = (char*)malloc(l + k + 1); + memcpy(e, print, k); + memcpy(e + k, p, l); + e[l + k] = '\0'; + p = e; + } + if(mb_load_string(bas, p) == MB_FUNC_OK) { + mb_run(bas); + } else { + printf("Invalid expression.\n"); + } + if(a) { + free(e); + } +} + +static void _process_parameters(int argc, char* argv[]) { + int i = 1; + char* p = 0; + char m = '\0'; + + while(i < argc) { + if(!memcmp(argv[i], "-", 1)) { + if(!memcmp(argv[i] + 1, "e", 1)) { + m = 'e'; + _CHECK_ARG(argc, i, "-e: Expression expected.\n"); + p = argv[++i]; + } else { + printf("Unknown argument: %s.\n", argv[i]); + } + } else { + p = argv[i]; + } + + i++; + } + + switch(m) { + case '\0': + _run_file(p); + break; + case 'e': + _evaluate_expression(p); + break; + } +} + +/* ========================================================} */ + /* ** {======================================================== ** Scripting interfaces @@ -684,7 +790,7 @@ static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, char* f mb_unrefvar(f); mb_unrefvar(p); if(SE_NO_ERR != e) { - printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", row, col, e, m, abort_code); + printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d.\n", row, col, e, m, abort_code); } } @@ -753,14 +859,10 @@ int main(int argc, char* argv[]) { do { status = _do_line(); } while(_NO_END(status)); - } else if(argc == 2) { - if(mb_load_file(bas, argv[1]) == MB_FUNC_OK) { - mb_run(bas); - } else { - printf("Invalid file\n"); - } + } else if(argc >= 2) { + _process_parameters(argc, argv); } else { - printf("Unknown arguments\n"); + printf("Unknown arguments.\n"); _show_tip(); }