Changed _strupr macro to mb_strupr function; Added an mb_strdup function; Fixed an intermediate value disposing more than once bug.
This commit is contained in:
parent
090fd0b900
commit
d5245ceb71
9
HISTORY
9
HISTORY
@ -1,3 +1,8 @@
|
|||||||
|
Mar. 25 2015
|
||||||
|
Changed _strupr macro to mb_strupr function
|
||||||
|
Added an mb_strdup function
|
||||||
|
Fixed an intermediate value disposing more than once bug
|
||||||
|
|
||||||
Dec. 17 2014
|
Dec. 17 2014
|
||||||
Fixed a calculation crash bug
|
Fixed a calculation crash bug
|
||||||
Fixed a memory leak with intermediate value
|
Fixed a memory leak with intermediate value
|
||||||
@ -9,8 +14,8 @@ Dec. 9 2014
|
|||||||
Improved compatibility with BCB
|
Improved compatibility with BCB
|
||||||
|
|
||||||
May. 25 2014
|
May. 25 2014
|
||||||
Added a mb_set_inputer function which allows the user to specify an INPUT reader, thanks to Michael P. Welch for suggestion
|
Added an mb_set_inputer function which allows the user to specify an INPUT reader, thanks to Michael P. Welch for suggestion
|
||||||
Added a mb_remove_reserved_func function which allows the user to disable/remove a reserved statement
|
Added an mb_remove_reserved_func function which allows the user to disable/remove a reserved statement
|
||||||
|
|
||||||
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
|
||||||
|
2
LICENSE
Normal file → Executable file
2
LICENSE
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
The MIT License
|
The MIT License
|
||||||
|
|
||||||
Copyright (c) 2011 - 2014 W. Renxin
|
Copyright (c) 2011 - 2015 W. Renxin
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
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
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
2
README.md
Normal file → Executable file
2
README.md
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
|
|
||||||
Copyright (C) 2011 - 2014 W. Renxin
|
Copyright (C) 2011 - 2015 W. Renxin
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 6000 lines of source code. Its grammar is similar to structured BASIC in early era, but without line number. 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 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 6000 lines of source code. Its grammar is similar to structured BASIC in early era, but without line number. 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 project easily, scripting driven can make your projects more powerful, elegant and neat.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
**
|
**
|
||||||
** For the latest info, see https://github.com/paladin-t/my_basic/
|
** For the latest info, see https://github.com/paladin-t/my_basic/
|
||||||
**
|
**
|
||||||
** Copyright (C) 2011 - 2014 W. Renxin
|
** Copyright (C) 2011 - 2015 W. Renxin
|
||||||
**
|
**
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy of
|
** 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
|
** this software and associated documentation files (the "Software"), to deal in
|
||||||
@ -78,7 +78,7 @@ extern "C" {
|
|||||||
/** Macros */
|
/** Macros */
|
||||||
#define _VER_MAJOR 1
|
#define _VER_MAJOR 1
|
||||||
#define _VER_MINOR 0
|
#define _VER_MINOR 0
|
||||||
#define _VER_REVISION 45
|
#define _VER_REVISION 46
|
||||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||||
|
|
||||||
/* Uncomment this line to treat warnings as error */
|
/* Uncomment this line to treat warnings as error */
|
||||||
@ -110,21 +110,6 @@ extern "C" {
|
|||||||
# define toupper(__c) ((islower(__c)) ? ((__c) - 'a' + 'A') : (__c))
|
# define toupper(__c) ((islower(__c)) ? ((__c) - 'a' + 'A') : (__c))
|
||||||
#endif /* toupper */
|
#endif /* toupper */
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
# ifndef _strupr
|
|
||||||
static char* _strupr(char* __s) {
|
|
||||||
char* t = __s;
|
|
||||||
|
|
||||||
while(*__s) {
|
|
||||||
*__s = toupper(*__s);
|
|
||||||
++__s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
# endif /* _strupr */
|
|
||||||
#endif /* _MSC_VER */
|
|
||||||
|
|
||||||
#define DON(__o) ((__o) ? ((_object_t*)((__o)->data)) : 0)
|
#define DON(__o) ((__o) ? ((_object_t*)((__o)->data)) : 0)
|
||||||
|
|
||||||
/* Hash table size */
|
/* Hash table size */
|
||||||
@ -545,6 +530,32 @@ static void _ls_clear(_ls_node_t* list);
|
|||||||
static void _ls_destroy(_ls_node_t* list);
|
static void _ls_destroy(_ls_node_t* list);
|
||||||
static int _ls_free_extra(void* data, void* extra);
|
static int _ls_free_extra(void* data, void* extra);
|
||||||
|
|
||||||
|
#define _LS_FOREACH(L, O, P, E) \
|
||||||
|
do { \
|
||||||
|
_ls_node_t* __lst = L; \
|
||||||
|
int __opresult = _OP_RESULT_NORMAL; \
|
||||||
|
_ls_node_t* __tmp = 0; \
|
||||||
|
mb_assert(L && O); \
|
||||||
|
__lst = __lst->next; \
|
||||||
|
while(__lst) { \
|
||||||
|
if(P != 0) { \
|
||||||
|
P(__lst->data, __lst->extra, E); \
|
||||||
|
} \
|
||||||
|
__opresult = O(__lst->data, __lst->extra); \
|
||||||
|
__tmp = __lst; \
|
||||||
|
__lst = __lst->next; \
|
||||||
|
if(_OP_RESULT_NORMAL == __opresult) { \
|
||||||
|
} else if(_OP_RESULT_DEL_NODE == __opresult) { \
|
||||||
|
__tmp->prev->next = __lst; \
|
||||||
|
if(__lst) { \
|
||||||
|
__lst->prev = __tmp->prev; \
|
||||||
|
} \
|
||||||
|
safe_free(__tmp); \
|
||||||
|
} else { \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
/** Dictionary */
|
/** Dictionary */
|
||||||
static unsigned int _ht_hash_string(void* ht, void* d);
|
static unsigned int _ht_hash_string(void* ht, void* d);
|
||||||
static unsigned int _ht_hash_int(void* ht, void* d);
|
static unsigned int _ht_hash_int(void* ht, void* d);
|
||||||
@ -583,6 +594,8 @@ static void* mb_malloc(size_t s);
|
|||||||
static void* mb_realloc(void** p, size_t s);
|
static void* mb_realloc(void** p, size_t s);
|
||||||
static void mb_free(void* p);
|
static void mb_free(void* p);
|
||||||
|
|
||||||
|
static char* mb_strupr(char* s);
|
||||||
|
|
||||||
#define safe_free(__p) do { if(__p) { mb_free(__p); __p = 0; } else { mb_assert(0 && "Memory already released"); } } while(0)
|
#define safe_free(__p) do { if(__p) { mb_free(__p); __p = 0; } else { mb_assert(0 && "Memory already released"); } } while(0)
|
||||||
|
|
||||||
/** Expression processing */
|
/** Expression processing */
|
||||||
@ -668,6 +681,7 @@ static int _remove_source_object(void* data, void* extra);
|
|||||||
static int _compare_numbers(const _object_t* first, const _object_t* second);
|
static int _compare_numbers(const _object_t* first, const _object_t* second);
|
||||||
static int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn);
|
static int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn);
|
||||||
static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl);
|
static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl);
|
||||||
|
static void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s);
|
||||||
|
|
||||||
static int _execute_statement(mb_interpreter_t* s, _ls_node_t** l);
|
static int _execute_statement(mb_interpreter_t* s, _ls_node_t** l);
|
||||||
static int _skip_to(mb_interpreter_t* s, _ls_node_t** l, mb_func_t f, _data_e t);
|
static int _skip_to(mb_interpreter_t* s, _ls_node_t** l, mb_func_t f, _data_e t);
|
||||||
@ -1531,6 +1545,17 @@ void mb_free(void* p) {
|
|||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* mb_strupr(char* s) {
|
||||||
|
char* t = s;
|
||||||
|
|
||||||
|
while(*s) {
|
||||||
|
*s = toupper(*s);
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/** Expression processing */
|
/** Expression processing */
|
||||||
bool_t _is_operator(mb_func_t op) {
|
bool_t _is_operator(mb_func_t op) {
|
||||||
/* Determine whether a function is an operator */
|
/* Determine whether a function is an operator */
|
||||||
@ -1939,11 +1964,13 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(guard_val != c && _ls_try_remove(garbage, c, _ls_cmp_data, NULL)) {
|
if(guard_val != c && _ls_try_remove(garbage, c, _ls_cmp_data, NULL)) {
|
||||||
|
_try_clear_intermediate_value(c, 0, s);
|
||||||
|
|
||||||
_destroy_object(c, 0);
|
_destroy_object(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
_ls_foreach(garbage, _destroy_object);
|
_LS_FOREACH(garbage, _destroy_object, _try_clear_intermediate_value, s);
|
||||||
_ls_destroy(garbage);
|
_ls_destroy(garbage);
|
||||||
_ls_foreach(optr, _destroy_object_non_syntax);
|
_ls_foreach(optr, _destroy_object_non_syntax);
|
||||||
_ls_foreach(opnd, _destroy_object_non_syntax);
|
_ls_foreach(opnd, _destroy_object_non_syntax);
|
||||||
@ -2983,6 +3010,24 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s) {
|
||||||
|
/* Try clear the intermediate value when destroying an object */
|
||||||
|
_object_t* obj = 0;
|
||||||
|
_running_context_t* running = 0;
|
||||||
|
|
||||||
|
mb_assert(s);
|
||||||
|
|
||||||
|
if(data == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
obj = (_object_t*)data;
|
||||||
|
running = (_running_context_t*)(s->running_context);
|
||||||
|
|
||||||
|
if(obj->type == _DT_STRING && running->intermediate_value.type == MB_DT_STRING && obj->data.string == running->intermediate_value.value.string) {
|
||||||
|
running->intermediate_value.type = MB_DT_NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
||||||
/* Execute the ast, core execution function */
|
/* Execute the ast, core execution function */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
@ -3130,7 +3175,7 @@ int _register_func(mb_interpreter_t* s, const char* n, mb_func_t f, bool_t local
|
|||||||
size_t _sl = strlen(n);
|
size_t _sl = strlen(n);
|
||||||
name = (char*)mb_malloc(_sl + 1);
|
name = (char*)mb_malloc(_sl + 1);
|
||||||
memcpy(name, n, _sl + 1);
|
memcpy(name, n, _sl + 1);
|
||||||
_strupr(name);
|
mb_strupr(name);
|
||||||
result += _ht_set_or_insert(scope, (void*)name, (void*)(intptr_t)f);
|
result += _ht_set_or_insert(scope, (void*)name, (void*)(intptr_t)f);
|
||||||
} else {
|
} else {
|
||||||
_set_current_error(s, SE_CM_FUNC_EXISTS);
|
_set_current_error(s, SE_CM_FUNC_EXISTS);
|
||||||
@ -3158,7 +3203,7 @@ int _remove_func(mb_interpreter_t* s, const char* n, bool_t local) {
|
|||||||
size_t _sl = strlen(n);
|
size_t _sl = strlen(n);
|
||||||
name = (char*)mb_malloc(_sl + 1);
|
name = (char*)mb_malloc(_sl + 1);
|
||||||
memcpy(name, n, _sl + 1);
|
memcpy(name, n, _sl + 1);
|
||||||
_strupr(name);
|
mb_strupr(name);
|
||||||
result += _ht_remove(scope, (void*)name, _ls_cmp_extra_string);
|
result += _ht_remove(scope, (void*)name, _ls_cmp_extra_string);
|
||||||
safe_free(name);
|
safe_free(name);
|
||||||
} else {
|
} else {
|
||||||
@ -4025,6 +4070,18 @@ int mb_gets(char* buf, int s) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* mb_strdup(char* val, unsigned size) {
|
||||||
|
/* Duplicate a string for internal use */
|
||||||
|
char* result = 0;
|
||||||
|
|
||||||
|
if(val != 0) {
|
||||||
|
result = (char*)mb_malloc(size);
|
||||||
|
memcpy(result, val, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================================================} */
|
/* ========================================================} */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
**
|
**
|
||||||
** For the latest info, see https://github.com/paladin-t/my_basic/
|
** For the latest info, see https://github.com/paladin-t/my_basic/
|
||||||
**
|
**
|
||||||
** Copyright (C) 2011 - 2014 W. Renxin
|
** Copyright (C) 2011 - 2015 W. Renxin
|
||||||
**
|
**
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy of
|
** 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
|
** this software and associated documentation files (the "Software"), to deal in
|
||||||
@ -252,6 +252,8 @@ MBAPI int mb_set_inputer(mb_interpreter_t* s, mb_input_func_t p);
|
|||||||
|
|
||||||
MBAPI int mb_gets(char* buf, int s);
|
MBAPI int mb_gets(char* buf, int s);
|
||||||
|
|
||||||
|
MBAPI char* mb_strdup(char* val, unsigned size);
|
||||||
|
|
||||||
#ifdef MB_COMPACT_MODE
|
#ifdef MB_COMPACT_MODE
|
||||||
# pragma pack()
|
# pragma pack()
|
||||||
#endif /* MB_COMPACT_MODE */
|
#endif /* MB_COMPACT_MODE */
|
||||||
|
Binary file not shown.
BIN
output/my_basic_mac
Normal file → Executable file
BIN
output/my_basic_mac
Normal file → Executable file
Binary file not shown.
0
resource/icon.ico
Normal file → Executable file
0
resource/icon.ico
Normal file → Executable file
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
0
resource/my_basic.aps
Normal file → Executable file
0
resource/my_basic.aps
Normal file → Executable file
@ -81,13 +81,13 @@ BEGIN
|
|||||||
VALUE "Comments", "MY-BASIC"
|
VALUE "Comments", "MY-BASIC"
|
||||||
VALUE "CompanyName", "W. Renxin"
|
VALUE "CompanyName", "W. Renxin"
|
||||||
VALUE "FileDescription", "MY-BASIC interpreter"
|
VALUE "FileDescription", "MY-BASIC interpreter"
|
||||||
VALUE "FileVersion", "1, 0, 0, 45"
|
VALUE "FileVersion", "1, 0, 0, 46"
|
||||||
VALUE "InternalName", "my_basic"
|
VALUE "InternalName", "my_basic"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2014 W. Renxin"
|
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 W. 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, 0, 0, 45"
|
VALUE "ProductVersion", "1, 0, 0, 46"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
0
resource/resource.h
Normal file → Executable file
0
resource/resource.h
Normal file → Executable file
2
sample/sample01.bas
Normal file → Executable file
2
sample/sample01.bas
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
' This script is an example of MY-BASIC
|
' This script is an example of MY-BASIC
|
||||||
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 W. Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
s$ = "hello "
|
s$ = "hello "
|
||||||
|
2
sample/sample02.bas
Normal file → Executable file
2
sample/sample02.bas
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
' This script is an example of MY-BASIC
|
' This script is an example of MY-BASIC
|
||||||
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 W. Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
e = 50
|
e = 50
|
||||||
|
2
sample/sample03.bas
Normal file → Executable file
2
sample/sample03.bas
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
' This script is an example of MY-BASIC
|
' This script is an example of MY-BASIC
|
||||||
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 W. Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
PRINT "Input: "
|
PRINT "Input: "
|
||||||
|
2
sample/sample04.bas
Normal file → Executable file
2
sample/sample04.bas
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
' This script is an example of MY-BASIC
|
' This script is an example of MY-BASIC
|
||||||
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 W. Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
BEGIN:
|
BEGIN:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
**
|
**
|
||||||
** For the latest info, see https://github.com/paladin-t/my_basic/
|
** For the latest info, see https://github.com/paladin-t/my_basic/
|
||||||
**
|
**
|
||||||
** Copyright (C) 2011 - 2014 W. Renxin
|
** Copyright (C) 2011 - 2015 W. Renxin
|
||||||
**
|
**
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy of
|
** 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
|
** this software and associated documentation files (the "Software"), to deal in
|
||||||
@ -331,7 +331,7 @@ static void _kill_program(const char* path) {
|
|||||||
|
|
||||||
static void _show_tip(void) {
|
static void _show_tip(void) {
|
||||||
printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string());
|
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 - 2015 W. Renxin. All Rights Reserved.\n");
|
||||||
printf("For more information, see https://github.com/paladin-t/my_basic/.\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");
|
printf("Input HELP and hint enter to view help information.\n");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user