diff --git a/HISTORY b/HISTORY index 245284a..d07e730 100644 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,6 @@ +Dec. 16 2014 +Fixed a negative calculation bug in a function argument + Dec. 9 2014 Improved compatibility with BCB diff --git a/core/my_basic.c b/core/my_basic.c index 66dfb47..a6a7072 100644 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -3,7 +3,7 @@ ** ** For the latest info, see https://github.com/paladin-t/my_basic/ ** -** Copyright (c) 2011 - 2014 W. Renxin +** Copyright (C) 2011 - 2014 W. Renxin ** ** Permission is hereby granted, free of charge, to any person obtaining a copy of ** this software and associated documentation files (the "Software"), to deal in @@ -29,6 +29,7 @@ # endif /* _CRT_SECURE_NO_WARNINGS */ #endif /* _MSC_VER */ +#include "my_basic.h" #ifdef _MSC_VER # include # include @@ -42,7 +43,6 @@ #include #include #include -#include "my_basic.h" #ifdef __cplusplus extern "C" { @@ -78,9 +78,8 @@ extern "C" { /** Macros */ #define _VER_MAJOR 1 #define _VER_MINOR 0 -#define _VER_REVISION 43 +#define _VER_REVISION 44 #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) -#define _MB_VERSION_STRING "1.0.0043" /* Uncomment this line to treat warnings as error */ /*#define _WARING_AS_ERROR*/ @@ -222,9 +221,11 @@ static const char* _ERR_DESC[] = { "Invalid expression", "Out of memory", /** Extended abort */ - "Extended abort", + "Extended abort" }; +mb_static_assert(_countof(_ERR_DESC) == SE_COUNT); + /* Data type */ #define _EOS '\n' #define _NULL_STRING "(empty)" @@ -244,7 +245,7 @@ typedef enum _data_e { _DT_ARRAY, _DT_LABEL, /* Label type, used for GOTO, GOSUB statement */ _DT_SEP, /* Separator */ - _DT_EOS, /* End of statement */ + _DT_EOS /* End of statement */ } _data_e; typedef struct _func_t { @@ -300,12 +301,12 @@ static _object_t* _OBJ_BOOL_FALSE = 0; typedef enum _parsing_state_e { _PS_NORMAL = 0, _PS_STRING, - _PS_COMMENT, + _PS_COMMENT } _parsing_state_e; typedef enum _symbol_state_e { _SS_IDENTIFIER = 0, - _SS_OPERATOR, + _SS_OPERATOR } _symbol_state_e; typedef struct _parsing_context_t { @@ -326,6 +327,7 @@ typedef struct _running_context_t { mb_value_t intermediate_value; int_t no_eat_comma_mark; _ls_node_t* skip_to_eoi; + _ls_node_t* in_neg_expr; } _running_context_t; /* Expression processing */ @@ -822,11 +824,11 @@ static const _func_t _core_libs[] = { { "GOSUB", _core_gosub }, { "RETURN", _core_return }, - { "END", _core_end }, - #ifdef _MB_ENABLE_ALLOC_STAT { "MEM", _core_mem }, #endif /* _MB_ENABLE_ALLOC_STAT */ + + { "END", _core_end } }; static const _func_t _std_libs[] = { @@ -857,7 +859,7 @@ static const _func_t _std_libs[] = { { "VAL", _std_val }, { "PRINT", _std_print }, - { "INPUT", _std_input }, + { "INPUT", _std_input } }; /* ========================================================} */ @@ -1724,6 +1726,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) { _object_t* r = 0; _object_t* theta = 0; char pri = '\0'; + int* inep = 0; unsigned int arr_idx = 0; mb_value_u arr_val; @@ -1743,6 +1746,10 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) { optr = _ls_create(); opnd = _ls_create(); + inep = (int*)mb_malloc(sizeof(int)); + *inep = 0; + _ls_pushback(running->in_neg_expr, inep); + c = (_object_t*)(ast->data); do { if(c->type == _DT_STRING) { @@ -1934,6 +1941,7 @@ _exit: _ls_destroy(optr); _ls_destroy(opnd); *l = ast; + mb_free(_ls_popback(running->in_neg_expr)); return result; } @@ -2327,7 +2335,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) { } } /* _func_t */ - if(context->last_symbol && ((context->last_symbol->type == _DT_FUNC && context->last_symbol->data.func->pointer != _core_close_bracket)|| + if(context->last_symbol && ((context->last_symbol->type == _DT_FUNC && context->last_symbol->data.func->pointer != _core_close_bracket) || context->last_symbol->type == _DT_SEP)) { if(strcmp("-", sym) == 0) { *value = (void*)(intptr_t)(_core_neg); @@ -3232,7 +3240,10 @@ unsigned int mb_ver(void) { const char* mb_ver_string(void) { /* Get the version text of this MY-BASIC system */ - return _MB_VERSION_STRING; + static char buf[32] = { '\0' }; + if(!buf[0]) sprintf(buf, "%d.%d.%04d", _VER_MAJOR, _VER_MINOR, _VER_REVISION); + + return buf; } int mb_init(void) { @@ -3349,6 +3360,7 @@ int mb_open(mb_interpreter_t** s) { memset(running, 0, sizeof(_running_context_t)); running->temp_values = _ls_create(); + running->in_neg_expr = _ls_create(); running->sub_stack = _ls_create(); (*s)->running_context = running; @@ -3380,6 +3392,7 @@ int mb_close(mb_interpreter_t** s) { _ls_foreach(running->temp_values, _destroy_object); _ls_destroy(running->temp_values); + _ls_destroy(running->in_neg_expr); _ls_destroy(running->sub_stack); safe_free(running); @@ -3645,11 +3658,14 @@ int mb_pop_value(mb_interpreter_t* s, void** l, mb_value_t* val) { _object_t val_obj; _object_t* val_ptr = 0; _running_context_t* running = 0; + int* inep = 0; mb_assert(s && l && val); running = (_running_context_t*)(s->running_context); + inep = (int*)_ls_back(running->in_neg_expr)->data; + val_ptr = &val_obj; memset(val_ptr, 0, sizeof(_object_t)); @@ -3665,7 +3681,7 @@ int mb_pop_value(mb_interpreter_t* s, void** l, mb_value_t* val) { _ls_pushback(running->temp_values, val_ptr); } - if(running->no_eat_comma_mark < _NO_EAT_COMMA) { + if(running->no_eat_comma_mark < _NO_EAT_COMMA && !(*inep)) { if(ast && ((_object_t*)(ast->data))->type == _DT_SEP && ((_object_t*)(ast->data))->data.separator == ',') { ast = ast->next; } @@ -4092,15 +4108,25 @@ int _core_neg(mb_interpreter_t* s, void** l) { /* Operator - (negative) */ int result = MB_FUNC_OK; mb_value_t arg; + _running_context_t* running = 0; + int* inep = 0; mb_assert(s && l); + running = (_running_context_t*)(s->running_context); + + inep = (int*)_ls_back(running->in_neg_expr)->data; + + (*inep)++; + mb_check(mb_attempt_func_begin(s, l)); mb_check(mb_pop_value(s, l, &arg)); mb_check(mb_attempt_func_end(s, l)); + (*inep)--; + switch(arg.type) { case MB_DT_INT: arg.value.integer = -(arg.value.integer); diff --git a/core/my_basic.h b/core/my_basic.h index 76dd973..c1fcd02 100644 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -3,7 +3,7 @@ ** ** For the latest info, see https://github.com/paladin-t/my_basic/ ** -** Copyright (c) 2011 - 2014 W. Renxin +** Copyright (C) 2011 - 2014 W. Renxin ** ** Permission is hereby granted, free of charge, to any person obtaining a copy of ** this software and associated documentation files (the "Software"), to deal in @@ -76,6 +76,13 @@ extern "C" { # define mb_assert(__a) do { ((void)(__a)); assert(__a); } while(0) #endif /* mb_assert */ +#ifndef mb_static_assert +# define _static_assert_impl(cond, msg) typedef char static_assertion_##msg[(!!(cond)) * 2 - 1] +# define _compile_time_assert3(x, l) _static_assert_impl(x, static_assertion_at_line_##l) +# define _compile_time_assert2(x, l) _compile_time_assert3(x, l) +# define mb_static_assert(x) _compile_time_assert2(x, __LINE__) +#endif /* mb_static_assert */ + #ifndef mb_unrefvar # define mb_unrefvar(__v) ((void)(__v)) #endif /* mb_unrefvar */ @@ -161,13 +168,15 @@ typedef enum mb_error_e { SE_RN_OUT_OF_MEMORY, /** Extended abort */ SE_EA_EXTENDED_ABORT, + /** Extra */ + SE_COUNT } mb_error_e; typedef enum mb_data_e { MB_DT_NIL = -1, MB_DT_INT = 0, MB_DT_REAL, - MB_DT_STRING, + MB_DT_STRING } mb_data_e; typedef union mb_value_u { diff --git a/my_basic.vcproj b/my_basic.vcproj index e8d94cd..ce92e5d 100644 --- a/my_basic.vcproj +++ b/my_basic.vcproj @@ -196,7 +196,11 @@ > + + diff --git a/output/my_basic.exe b/output/my_basic.exe index 03c38a5..0236a69 100644 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 old mode 100755 new mode 100644 diff --git a/resource/my_basic.aps b/resource/my_basic.aps index bdf02bf..7be1fb8 100644 Binary files a/resource/my_basic.aps and b/resource/my_basic.aps differ diff --git a/resource/my_basic.rc b/resource/my_basic.rc index 72b719d..6dd31fb 100644 --- a/resource/my_basic.rc +++ b/resource/my_basic.rc @@ -34,7 +34,7 @@ END 2 TEXTINCLUDE BEGIN - "#include ""afxres.h""\r\n" + "#include ""windows.h""\r\n" "\0" END @@ -62,8 +62,8 @@ IDI_ICON_MAIN ICON "icon.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,42 - PRODUCTVERSION 1,0,0,42 + FILEVERSION 1,0,0,44 + PRODUCTVERSION 1,0,0,44 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -81,13 +81,13 @@ BEGIN VALUE "Comments", "MY-BASIC" VALUE "CompanyName", "W. Renxin" VALUE "FileDescription", "MY-BASIC interpreter" - VALUE "FileVersion", "1, 0, 0, 42" + VALUE "FileVersion", "1, 0, 0, 44" VALUE "InternalName", "my_basic" VALUE "LegalCopyright", "Copyright (C) 2011 - 2014 W. Renxin" VALUE "LegalTrademarks", "MY-BASIC" VALUE "OriginalFilename", "my_basic.exe" VALUE "ProductName", "MY-BASIC" - VALUE "ProductVersion", "1, 0, 0, 42" + VALUE "ProductVersion", "1, 0, 0, 44" END END BLOCK "VarFileInfo" diff --git a/shell/main.c b/shell/main.c index a76ab14..98cfa0a 100644 --- a/shell/main.c +++ b/shell/main.c @@ -3,7 +3,7 @@ ** ** For the latest info, see https://github.com/paladin-t/my_basic/ ** -** Copyright (c) 2011 - 2014 W. Renxin +** Copyright (C) 2011 - 2014 W. Renxin ** ** Permission is hereby granted, free of charge, to any person obtaining a copy of ** this software and associated documentation files (the "Software"), to deal in @@ -29,6 +29,7 @@ # endif /* _CRT_SECURE_NO_WARNINGS */ #endif /* _MSC_VER */ +#include "../core/my_basic.h" #ifdef _MSC_VER # include # include @@ -39,7 +40,6 @@ #include #include #include -#include "../core/my_basic.h" #ifdef _MSC_VER # pragma warning(disable : 4127) @@ -331,7 +331,7 @@ static void _kill_program(const char* path) { static void _show_tip(void) { printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string()); - printf("Copyright (c) 2011 - 2014 W. Renxin. All Rights Reserved.\n"); + printf("Copyright (C) 2011 - 2014 W. Renxin. All Rights Reserved.\n"); printf("For more information, see https://github.com/paladin-t/my_basic/.\n"); printf("Input HELP and hint enter to view help information.\n"); }