+added a duplicate sub routine error handling; +added optional argument support for INPUT statement; *fixed a variable multiple freeing bug in sub routine; *polished document.

This commit is contained in:
tony 2015-09-11 22:29:16 +08:00
parent 3b7a983871
commit c6d7dcae8f
8 changed files with 167 additions and 47 deletions

17
HISTORY
View File

@ -1,7 +1,14 @@
Sep. 11 2015
Added a duplicate sub routine error handling
Added optional argument support for INPUT statement
Fixed a variable multiple freeing bug in sub routine
Polished document
Sep. 8 2015 Sep. 8 2015
Fixed a type parsing of sub routine bug Fixed a type parsing of sub routine bug
Fixed a scope processing bug Fixed a scope processing bug
Fixed a sub routine invoking bug without leading CALL statement or result receiver Fixed a sub routine invoking bug without leading CALL statement or result receiver
Added a makefile
Sep. 6 2015 Sep. 6 2015
Improved sub routine Improved sub routine
@ -12,7 +19,7 @@ Prompted more friendly dummy function message
Polished code and document Polished code and document
Sep. 1 2015 Sep. 1 2015
Added support for user customized routine by DEF/ENDDEF Added support for user customized sub routine by DEF/ENDDEF
Aug. 26 2015 Aug. 26 2015
Added a memory pool to interpreter shell in main.c Added a memory pool to interpreter shell in main.c
@ -56,7 +63,7 @@ Changed mb_dispose_value as public
Apr. 23 2015 Version 1.1 Apr. 23 2015 Version 1.1
Added debug APIs Added debug APIs
Added (nestable) multi line IF statement support Added (nestable) multiple line IF statement support
Apr. 15 2015 Apr. 15 2015
Added mb_pop_usertype, mb_push_usertype to support user defined type Added mb_pop_usertype, mb_push_usertype to support user defined type
@ -102,12 +109,12 @@ Added an mb_remove_reserved_func function which allows a user to disable/remove
May. 22 2014 May. 22 2014
Fixed a crash bug when missing colon in a combined line, thanks to Michael P. Welch for pointing it out Fixed a crash bug when missing colon in a combined line, thanks to Michael P. Welch for pointing it out
Fixed a missing lexical cursor stepping bug in INPUT function Fixed a missing lexical cursor stepping bug in INPUT statement
Mar. 17 2014 Mar. 17 2014
Added an XCode project Added an XCode project
Added a safe stdin reader function mb_gets Added a safe stdin reader function mb_gets
Fixed a crash bug in INPUT function Fixed a crash bug in INPUT statement
Feb. 17 2014 Feb. 17 2014
Added mod by zero processing Added mod by zero processing
@ -119,7 +126,7 @@ Jul. 19 2013
Fixed a crash bug in _execute_statement, thanks to Jon Mayo for pointing it out Fixed a crash bug in _execute_statement, thanks to Jon Mayo for pointing it out
Feb. 25 2013 Feb. 25 2013
Fixed a cross routine multi-statement execution bug, thanks to Bruce Kendall for pointing it out Fixed a cross routine multiple statement execution bug, thanks to Bruce Kendall for pointing it out
Fixed a memory corruption bug when loading a script file Fixed a memory corruption bug when loading a script file
Jan. 9 2013 Jan. 9 2013

View File

@ -1,18 +1,18 @@
![](resource/icon.ico) ![](resource/icon.ico)
Copyright (C) 2011 - 2015 [Wang Renxin](https://twitter.com/wangrenxin) Copyright (C) 2011 - 2015 [Wang Renxin](https://twitter.com/wangrenxin). All rights reserved.
[LinkedIn](https://cn.linkedin.com/pub/wang-renxin/43/494/20) [LinkedIn](https://cn.linkedin.com/pub/wang-renxin/43/494/20)
Why are existing script interpreters so complex? Why is it so difficult to integrate with them? Why not try MY-BASIC today! Why are existing script interpreters so complex? Why is it so difficult to integrate with them? Why not try MY-BASIC today! Scripting should be simple and enjoyable.
## Introduction ## Introduction
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 7000 lines of source code. Its grammar is similar to structured BASIC. It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is pretty light; all in a C source file and an associated header file. You can combine MY-BASIC with an existing C, C++, Objective-C, etc. project easily, scripting driven can make your projects more powerful, elegant and neat. MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 7000 lines of source code. Its grammar is similar to structured BASIC. It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is pretty light; all in a C source file and an associated header file. You are able to easily combine MY-BASIC with an existing project in C, C++, Objective-C, etc. Scripting driven can make your projects more powerful, elegant and neat.
## Main features ## Main features
* It is free * It is totally free to use MY-BASIC for individual or commercial purpose under the MIT license
* Written in clean ANSI C, source code portable * Written in clean ANSI C, source code portable
* With most common BASIC syntax * With most common BASIC syntax
* Small (within memory usage less than 128KB) and fast * Small (within memory usage less than 128KB) and fast
@ -26,11 +26,23 @@ MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in p
* Standard string functions * Standard string functions
* Debug APIs * Debug APIs
* High expansibility, easy to use APIs, easy to write customized scripting interfaces * High expansibility, easy to use APIs, easy to write customized scripting interfaces
* It's able to use it as a standalone interpreter, or integrate it with existing C, C++, Objective-C, etc. projects * It's able to use it as a standalone interpreter, or integrate it with existing projects in C, C++, Objective-C, etc.
* It's able to learn how to build an interpreter from scratch from MY-BASIC * It's able to learn how to build an interpreter from scratch from MY-BASIC
* It's able to build your own dialect based on MY-BASIC * It's able to build your own dialect based on MY-BASIC
* More features/modules under developing * More features/modules under developing
## Scripting at a glance
Come along with a traditional "hello world" script in MY-BASIC:
def foo(a, b)
print a + " " + b;
enddef
foo("Hello", "world!")
input
## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram) ## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
![](https://github.com/paladin-t/my_basic/blob/master/interpreter%20workflow%20diagram.png) ![](https://github.com/paladin-t/my_basic/blob/master/interpreter%20workflow%20diagram.png)
@ -57,7 +69,7 @@ You can definitely [link with MY-BASIC as a lib](https://github.com/paladin-t/my
For more details about using MY-BASIC when it's already integrated with exist projects, please see [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf). For more details about using MY-BASIC when it's already integrated with exist projects, please see [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf).
## [WIKI](https://github.com/paladin-t/my_basic/wiki) ## [Wiki](https://github.com/paladin-t/my_basic/wiki)
* [Passes](https://github.com/paladin-t/my_basic/wiki/Passes) * [Passes](https://github.com/paladin-t/my_basic/wiki/Passes)
* [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram) * [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)

View File

@ -52,6 +52,7 @@ extern "C" {
# pragma warning(push) # pragma warning(push)
# pragma warning(disable : 4127) # pragma warning(disable : 4127)
# pragma warning(disable : 4305) # pragma warning(disable : 4305)
# pragma warning(disable : 4996)
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#ifdef __APPLE__ #ifdef __APPLE__
@ -78,7 +79,7 @@ extern "C" {
/** Macros */ /** Macros */
#define _VER_MAJOR 1 #define _VER_MAJOR 1
#define _VER_MINOR 1 #define _VER_MINOR 1
#define _VER_REVISION 68 #define _VER_REVISION 69
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
/* Uncomment the line below to treat warning as error */ /* Uncomment the line below to treat warning as error */
@ -211,6 +212,7 @@ static const char* _ERR_DESC[] = {
"Don't suspend in a routine", "Don't suspend in a routine",
"Don't mix instructional and structured sub routines", "Don't mix instructional and structured sub routines",
"Routine expected", "Routine expected",
"Duplicate routine",
/** Extended abort */ /** Extended abort */
"Extended abort" "Extended abort"
}; };
@ -365,6 +367,7 @@ typedef struct _parsing_context_t {
_object_t* last_symbol; _object_t* last_symbol;
_parsing_state_e parsing_state; _parsing_state_e parsing_state;
_symbol_state_e symbol_state; _symbol_state_e symbol_state;
unsigned short class_state;
unsigned short routine_state; unsigned short routine_state;
unsigned short routine_params_state; unsigned short routine_params_state;
int parsing_pos; int parsing_pos;
@ -776,7 +779,9 @@ static bool_t _is_array(void* obj);
static bool_t _is_string(void* obj); static bool_t _is_string(void* obj);
static char* _extract_string(_object_t* obj); static char* _extract_string(_object_t* obj);
static void _init_instance(mb_interpreter_t* s, _class_t* instance, char* n); static void _init_class(mb_interpreter_t* s, _class_t* instance, char* n);
static void _begin_class(mb_interpreter_t* s);
static void _end_class(mb_interpreter_t* s);
static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n); static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n);
static void _begin_routine(mb_interpreter_t* s); static void _begin_routine(mb_interpreter_t* s);
static void _end_routine(mb_interpreter_t* s); static void _end_routine(mb_interpreter_t* s);
@ -843,11 +848,21 @@ static int _close_std_lib(mb_interpreter_t* s);
#ifdef _MSC_VER #ifdef _MSC_VER
# if _MSC_VER < 1300 # if _MSC_VER < 1300
# define _do_nothing(__s, __l, __exit, __result) do { static int i = 0; ++i; printf("Unaccessable function called %d times\n", i); mb_unrefvar(__s); mb_unrefvar(__l); mb_unrefvar(__result); goto _exit; } while(0) # define _do_nothing(__s, __l, __exit, __result) \
do { \
_ls_node_t* ast = 0; static int i = 0; ++i; \
printf("Unaccessable function called %d times\n", i); \
ast = (_ls_node_t*)(*(__l)); \
_handle_error_on_obj((__s), SE_RN_WRONG_FUNCTION_REACHED, 0, DON(ast), MB_FUNC_ERR, __exit, __result); \
} while(0)
# endif /* _MSC_VER < 1300 */ # endif /* _MSC_VER < 1300 */
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#ifndef _do_nothing #ifndef _do_nothing
# define _do_nothing(__s, __l, __exit, __result) do { _ls_node_t* ast = (_ls_node_t*)(*(__l)); _handle_error_on_obj((__s), SE_RN_WRONG_FUNCTION_REACHED, (char*)MB_FUNC, DON(ast), MB_FUNC_ERR, __exit, __result); } while(0); # define _do_nothing(__s, __l, __exit, __result) \
do { \
_ls_node_t* ast = (_ls_node_t*)(*(__l)); \
_handle_error_on_obj((__s), SE_RN_WRONG_FUNCTION_REACHED, (char*)MB_FUNC, DON(ast), MB_FUNC_ERR, __exit, __result); \
} while(0);
#endif /* _do_nothing */ #endif /* _do_nothing */
/** Core lib */ /** Core lib */
@ -1971,6 +1986,7 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
_pop_scope(s); _pop_scope(s);
result = _public_value_to_internal_object(&arg, var->data); result = _public_value_to_internal_object(&arg, var->data);
var->data->ref = true;
if(result != MB_FUNC_OK) if(result != MB_FUNC_OK)
goto _exit; goto _exit;
} }
@ -2302,9 +2318,15 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
(*obj)->data.instance = ((_object_t*)(glbsyminscope->data))->data.instance; (*obj)->data.instance = ((_object_t*)(glbsyminscope->data))->data.instance;
(*obj)->ref = true; (*obj)->ref = true;
*delsym = true; *delsym = true;
if(running != (*obj)->data.instance->scope &&
context->class_state &&
_IS_FUNC(context->last_symbol, _core_class)) {
_push_scope(s, (*obj)->data.instance->scope);
}
} else { } else {
tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t)); tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t));
_init_instance(s, tmp.instance, sym); _init_class(s, tmp.instance, sym);
_push_scope(s, tmp.instance->scope);
(*obj)->data.instance = tmp.instance; (*obj)->data.instance = tmp.instance;
ul = _ht_set_or_insert(running->var_dict, sym, *obj); ul = _ht_set_or_insert(running->var_dict, sym, *obj);
@ -2492,23 +2514,43 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
goto _exit; goto _exit;
} }
/* _class_t */ /* _class_t */
if(context->last_symbol && _IS_FUNC(context->last_symbol, _core_class)) { if(context->last_symbol) {
glbsyminscope = _search_var_in_scope_chain(s, 0, sym); glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) { if(glbsyminscope && ((_object_t*)glbsyminscope->data)->type == _DT_CLASS) {
tmp.obj = (_object_t*)(glbsyminscope->data); if(_IS_FUNC(context->last_symbol, _core_class))
if(!tmp.obj->ref) { _begin_class(s);
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string); result = _DT_CLASS;
_dispose_object(tmp.obj);
} goto _exit;
tmp.obj->type = _DT_CLASS;
tmp.obj->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
_init_instance(s, tmp.obj->data.instance, sym);
_ht_set_or_insert(running->var_dict, sym, tmp.obj);
} }
if(_IS_FUNC(context->last_symbol, _core_class)) {
if(_IS_FUNC(context->last_symbol, _core_class))
_begin_class(s);
if(!_is_identifier_char(sym[0])) {
result = _DT_NIL;
result = _DT_CLASS; goto _exit;
}
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
tmp.obj = (_object_t*)(glbsyminscope->data);
if(!tmp.obj->ref) {
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string);
_dispose_object(tmp.obj);
}
tmp.obj->type = _DT_CLASS;
tmp.obj->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
_init_class(s, tmp.obj->data.instance, sym);
_init_class(s, tmp.obj->data.instance, sym);
_ht_set_or_insert(running->var_dict, sym, tmp.obj);
}
goto _exit; result = _DT_CLASS;
goto _exit;
} else if(_IS_FUNC(context->last_symbol, _core_endclass)) {
_end_class(s);
_pop_scope(s);
}
} }
/* _routine_t */ /* _routine_t */
if(context->last_symbol) { if(context->last_symbol) {
@ -3108,14 +3150,39 @@ char* _extract_string(_object_t* obj) {
return result; return result;
} }
void _init_instance(mb_interpreter_t* s, _class_t* instance, char* n) { void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
/* Initialize an instance */ /* Initialize an instance */
_running_context_t* running = 0;
mb_assert(s && instance && n); mb_assert(s && instance && n);
running = s->running_context;
memset(instance, 0, sizeof(_class_t)); memset(instance, 0, sizeof(_class_t));
instance->name = n; instance->name = n;
instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t)); instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
memset(instance->scope, 0, sizeof(_running_context_t)); memset(instance->scope, 0, sizeof(_running_context_t));
instance->scope->var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
}
void _begin_class(mb_interpreter_t* s) {
/* Begin parsing a class */
_parsing_context_t* context = 0;
mb_assert(s);
context = s->parsing_context;
context->class_state++;
}
void _end_class(mb_interpreter_t* s) {
/* End parsing a class */
_parsing_context_t* context = 0;
mb_assert(s);
context = s->parsing_context;
context->class_state--;
} }
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) { void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
@ -3279,6 +3346,16 @@ int _dispose_object(_object_t* obj) {
safe_free(obj->data.label); safe_free(obj->data.label);
} }
break;
case _DT_CLASS:
if(!obj->ref) {
safe_free(obj->data.instance->name);
_ht_foreach(obj->data.instance->scope->var_dict, _destroy_object);
_ht_destroy(obj->data.instance->scope->var_dict);
safe_free(obj->data.instance->scope);
safe_free(obj->data.instance);
}
break; break;
case _DT_ROUTINE: case _DT_ROUTINE:
if(!obj->ref) { if(!obj->ref) {
@ -3291,13 +3368,6 @@ int _dispose_object(_object_t* obj) {
safe_free(obj->data.routine); safe_free(obj->data.routine);
} }
break;
case _DT_CLASS:
if(!obj->ref) {
safe_free(obj->data.instance->scope);
safe_free(obj->data.instance);
}
break; break;
case _DT_NIL: /* Fall through */ case _DT_NIL: /* Fall through */
case _DT_ANY: /* Fall through */ case _DT_ANY: /* Fall through */
@ -3599,6 +3669,10 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
case _DT_STRING: case _DT_STRING:
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, 0, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, 0, DON(ast), MB_FUNC_ERR, _exit, result);
break;
case _DT_CLASS:
mb_assert(0 && "Not implemented");
break; break;
case _DT_ROUTINE: case _DT_ROUTINE:
ast = ast->prev; ast = ast->prev;
@ -6161,6 +6235,7 @@ int _core_def(mb_interpreter_t* s, void** l) {
/* DEF statement */ /* DEF statement */
int result = MB_FUNC_OK; int result = MB_FUNC_OK;
_ls_node_t* ast = 0; _ls_node_t* ast = 0;
_running_context_t* running = 0;
_object_t* obj = 0; _object_t* obj = 0;
_var_t* var = 0; _var_t* var = 0;
_ls_node_t* rnode = 0; _ls_node_t* rnode = 0;
@ -6168,6 +6243,8 @@ int _core_def(mb_interpreter_t* s, void** l) {
mb_assert(s && l); mb_assert(s && l);
running = s->running_context;
ast = (_ls_node_t*)(*l); ast = (_ls_node_t*)(*l);
ast = ast->next; ast = ast->next;
@ -6177,6 +6254,9 @@ int _core_def(mb_interpreter_t* s, void** l) {
if(!_IS_ROUTINE(obj)) { if(!_IS_ROUTINE(obj)) {
_handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
} }
if(obj->data.routine->entry) {
_handle_error_on_obj(s, SE_RN_DUPLICATE_ROUTINE, 0, DON(ast), MB_FUNC_ERR, _exit, result);
}
routine = (_routine_t*)(((_object_t*)(ast->data))->data.routine); routine = (_routine_t*)(((_object_t*)(ast->data))->data.routine);
ast = ast->next; ast = ast->next;
obj = (_object_t*)(ast->data); obj = (_object_t*)(ast->data);
@ -6233,17 +6313,32 @@ _exit:
} }
int _core_class(mb_interpreter_t* s, void** l) { int _core_class(mb_interpreter_t* s, void** l) {
/* OBJ statement */ /* CLASS statement */
int result = MB_FUNC_OK; int result = MB_FUNC_OK;
_ls_node_t* ast = 0;
_running_context_t* running = 0;
_do_nothing(s, l, _exit, result); mb_assert(s && l);
running = s->running_context;
ast = (_ls_node_t*)(*l);
ast = ast->next;
_using_jump_set_of_structured(s, ast, _exit, result);
_skip_to(s, &ast, _core_endclass, _DT_NIL);
ast = ast->next;
_exit: _exit:
*l = ast;
return result; return result;
} }
int _core_endclass(mb_interpreter_t* s, void** l) { int _core_endclass(mb_interpreter_t* s, void** l) {
/* ENDOBJ statement */ /* ENDCLASS statement */
int result = MB_FUNC_OK; int result = MB_FUNC_OK;
_do_nothing(s, l, _exit, result); _do_nothing(s, l, _exit, result);
@ -7132,7 +7227,12 @@ int _std_input(mb_interpreter_t* s, void** l) {
ast = (_ls_node_t*)(*l); ast = (_ls_node_t*)(*l);
obj = (_object_t*)(ast->data); obj = (_object_t*)(ast->data);
if(!obj || obj->type != _DT_VAR) { if(!obj || obj->type == _DT_EOS) {
_get_inputer(s)(line, sizeof(line));
goto _exit;
}
if(obj->type != _DT_VAR) {
_handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
} }
if(obj->data.variable->data->type == _DT_INT || obj->data.variable->data->type == _DT_REAL) { if(obj->data.variable->data->type == _DT_INT || obj->data.variable->data->type == _DT_REAL) {

View File

@ -219,6 +219,7 @@ typedef enum mb_error_e {
SE_RN_DONT_SUSPEND_IN_A_ROUTINE, SE_RN_DONT_SUSPEND_IN_A_ROUTINE,
SE_RN_DONT_MIX_INSTRUCTIONAL_AND_STRUCTURED, SE_RN_DONT_MIX_INSTRUCTIONAL_AND_STRUCTURED,
SE_RN_ROUTINE_EXPECTED, SE_RN_ROUTINE_EXPECTED,
SE_RN_DUPLICATE_ROUTINE,
/** Extended abort */ /** Extended abort */
SE_EA_EXTENDED_ABORT, SE_EA_EXTENDED_ABORT,
/** Extra */ /** Extra */

4
makefile Normal file → Executable file
View File

@ -5,7 +5,7 @@ main.o : shell/main.c core/my_basic.h
cc -Os -c shell/main.c cc -Os -c shell/main.c
my_basic.o : core/my_basic.c core/my_basic.h my_basic.o : core/my_basic.c core/my_basic.h
cc -Os -c core/my_basic.c cc -Os -c core/my_basic.c -Wno-multichar -Wno-overflow
clean : clean :
rm edit $(objects) rm -f main.o my_basic.o output/my_basic_bin output/my_basic_bin.exe

Binary file not shown.

Binary file not shown.

View File

@ -36,8 +36,8 @@
IDI_ICON_MAIN ICON "icon.ico" IDI_ICON_MAIN ICON "icon.ico"
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,68,0 FILEVERSION 1,1,69,0
PRODUCTVERSION 1,1,68,0 PRODUCTVERSION 1,1,69,0
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
# ifdef _DEBUG # ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -55,13 +55,13 @@
VALUE "Comments", "MY-BASIC" VALUE "Comments", "MY-BASIC"
VALUE "CompanyName", "Wang Renxin" VALUE "CompanyName", "Wang Renxin"
VALUE "FileDescription", "MY-BASIC Interpreter for Windows" VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
VALUE "FileVersion", "1, 1, 68, 0" VALUE "FileVersion", "1, 1, 69, 0"
VALUE "InternalName", "my_basic" VALUE "InternalName", "my_basic"
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin" VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
VALUE "LegalTrademarks", "MY-BASIC" VALUE "LegalTrademarks", "MY-BASIC"
VALUE "OriginalFilename", "my_basic.exe" VALUE "OriginalFilename", "my_basic.exe"
VALUE "ProductName", "MY-BASIC" VALUE "ProductName", "MY-BASIC"
VALUE "ProductVersion", "1, 1, 68, 0" VALUE "ProductVersion", "1, 1, 69, 0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"