Fixed a double precision float parsing bug on all 32bit systems, thanks to Pito for pointing it out; Fixed a exponential number parsing bug, thanks to Pito for pointing it out; Fixed a crash bug when a script begins with a meaningless negtive number.

This commit is contained in:
tony 2015-04-10 22:04:41 +08:00
parent eb5cd615ce
commit e872d26513
7 changed files with 784 additions and 734 deletions

View File

@ -1,3 +1,9 @@
Apr. 10 2015
Improved compatibility with PellesC
Fixed a double precision float parsing bug on all 32bit systems, thanks to Pito for pointing it out
Fixed a exponential number parsing bug, thanks to Pito for pointing it out
Fixed a crash bug when a script begins with a meaningless negtive number
Mar. 25 2015 Mar. 25 2015
Changed _strupr macro to mb_strupr function Changed _strupr macro to mb_strupr function
Added an mb_strdup function Added an mb_strdup function

View File

@ -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 46 #define _VER_REVISION 47
#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 */
@ -258,6 +258,8 @@ typedef struct _label_t {
_ls_node_t* node; _ls_node_t* node;
} _label_t; } _label_t;
typedef unsigned char _raw_t[sizeof(union { int_t i; real_t r; void* p; })];
typedef struct _object_t { typedef struct _object_t {
_data_e type; _data_e type;
union { union {
@ -270,6 +272,7 @@ typedef struct _object_t {
_array_t* array; _array_t* array;
_label_t* label; _label_t* label;
char separator; char separator;
_raw_t raw;
} data; } data;
bool_t ref; bool_t ref;
int source_pos; int source_pos;
@ -594,6 +597,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 size_t mb_memtest(void*p, size_t s);
static char* mb_strupr(char* s); 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)
@ -656,7 +661,7 @@ static int _append_char_to_symbol(mb_interpreter_t* s, char c);
static int _cut_symbol(mb_interpreter_t* s, int pos, unsigned short row, unsigned short col); static int _cut_symbol(mb_interpreter_t* s, int pos, unsigned short row, unsigned short col);
static int _append_symbol(mb_interpreter_t* s, char* sym, bool_t* delsym, int pos, unsigned short row, unsigned short col); static int _append_symbol(mb_interpreter_t* s, char* sym, bool_t* delsym, int pos, unsigned short row, unsigned short col);
static int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** obj, _ls_node_t*** asgn, bool_t* delsym); static int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** obj, _ls_node_t*** asgn, bool_t* delsym);
static _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value); static _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value);
static int _parse_char(mb_interpreter_t* s, char c, int pos, unsigned short row, unsigned short col); static int _parse_char(mb_interpreter_t* s, char c, int pos, unsigned short row, unsigned short col);
static void _set_error_pos(mb_interpreter_t* s, int pos, unsigned short row, unsigned short col); static void _set_error_pos(mb_interpreter_t* s, int pos, unsigned short row, unsigned short col);
@ -722,6 +727,8 @@ MBAPI int mb_dispose_value(mb_interpreter_t* s, mb_value_t val);
# endif /* _MSC_VER < 1300 */ # endif /* _MSC_VER < 1300 */
#elif defined __BORLANDC__ #elif defined __BORLANDC__
# define _do_nothing do { printf("Unaccessable function: %s\n", __FUNC__); } while(0) # define _do_nothing do { printf("Unaccessable function: %s\n", __FUNC__); } while(0)
#elif defined __POCC__
# define _do_nothing do { printf("Unaccessable function: %s\n", __func__); } while(0)
#else /* _MSC_VER */ #else /* _MSC_VER */
# define _do_nothing do { printf("Unaccessable function: %s\n", __FUNCTION__); } while(0) # define _do_nothing do { printf("Unaccessable function: %s\n", __FUNCTION__); } while(0)
#endif /* _MSC_VER */ #endif /* _MSC_VER */
@ -1545,6 +1552,16 @@ void mb_free(void* p) {
free(p); free(p);
} }
size_t mb_memtest(void*p, size_t s) {
size_t result = 0;
size_t i = 0;
for(i = 0; i < s; i++) {
result += ((unsigned char*)p)[i];
}
return result;
}
char* mb_strupr(char* s) { char* mb_strupr(char* s) {
char* t = s; char* t = s;
@ -2165,8 +2182,8 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
/* Create a syntax symbol */ /* Create a syntax symbol */
int result = MB_FUNC_OK; int result = MB_FUNC_OK;
_data_e type; _data_e type;
union { _func_t* func; _array_t* array; _var_t* var; _label_t* label; real_t float_point; int_t integer; void* any; } tmp; union { _func_t* func; _array_t* array; _var_t* var; _label_t* label; real_t float_point; int_t integer; _raw_t any; } tmp;
void* value = 0; _raw_t value;
unsigned int ul = 0; unsigned int ul = 0;
_parsing_context_t* context = 0; _parsing_context_t* context = 0;
_ls_node_t* glbsyminscope = 0; _ls_node_t* glbsyminscope = 0;
@ -2174,6 +2191,8 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
mb_assert(s && sym && obj); mb_assert(s && sym && obj);
memset(value, 0, sizeof(_raw_t));
context = (_parsing_context_t*)s->parsing_context; context = (_parsing_context_t*)s->parsing_context;
*obj = (_object_t*)mb_malloc(sizeof(_object_t)); *obj = (_object_t*)mb_malloc(sizeof(_object_t));
@ -2185,13 +2204,13 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
(*obj)->type = type; (*obj)->type = type;
switch(type) { switch(type) {
case _DT_INT: case _DT_INT:
tmp.any = value; memcpy(tmp.any, value, sizeof(_raw_t));
(*obj)->data.integer = tmp.integer; (*obj)->data.integer = tmp.integer;
safe_free(sym); safe_free(sym);
break; break;
case _DT_REAL: case _DT_REAL:
tmp.any = value; memcpy(tmp.any, value, sizeof(_raw_t));
(*obj)->data.float_point = tmp.float_point; (*obj)->data.float_point = tmp.float_point;
safe_free(sym); safe_free(sym);
@ -2209,7 +2228,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
tmp.func = (_func_t*)mb_malloc(sizeof(_func_t)); tmp.func = (_func_t*)mb_malloc(sizeof(_func_t));
memset(tmp.func, 0, sizeof(_func_t)); memset(tmp.func, 0, sizeof(_func_t));
tmp.func->name = sym; tmp.func->name = sym;
tmp.func->pointer = (mb_func_t)(intptr_t)value; memcpy(&tmp.func->pointer, value, sizeof(tmp.func->pointer));
(*obj)->data.func = tmp.func; (*obj)->data.func = tmp.func;
break; break;
@ -2223,7 +2242,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
tmp.array = (_array_t*)mb_malloc(sizeof(_array_t)); tmp.array = (_array_t*)mb_malloc(sizeof(_array_t));
memset(tmp.array, 0, sizeof(_array_t)); memset(tmp.array, 0, sizeof(_array_t));
tmp.array->name = sym; tmp.array->name = sym;
tmp.array->type = (_data_e)(int)(long)(intptr_t)value; memcpy(&tmp.array->type, value, sizeof(tmp.array->type));
(*obj)->data.array = tmp.array; (*obj)->data.array = tmp.array;
ul = _ht_set_or_insert((_ht_node_t*)s->global_var_dict, sym, *obj); ul = _ht_set_or_insert((_ht_node_t*)s->global_var_dict, sym, *obj);
@ -2266,8 +2285,8 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
break; break;
case _DT_LABEL: case _DT_LABEL:
if(context->current_char == ':') { if(context->current_char == ':') {
if(value) { if(mb_memtest(value, sizeof(_raw_t))) {
(*obj)->data.label = value; memcpy(&((*obj)->data.label), value, sizeof((*obj)->data.label));
(*obj)->ref = true; (*obj)->ref = true;
*delsym = true; *delsym = true;
} else { } else {
@ -2309,15 +2328,17 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
return result; return result;
} }
_data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) { _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
/* Get the type of a syntax symbol */ /* Get the type of a syntax symbol */
_data_e result = _DT_NIL; _data_e result = _DT_NIL;
union { real_t float_point; int_t integer; _object_t* obj; void* any; } tmp; union { real_t float_point; int_t integer; _object_t* obj; _raw_t any; } tmp;
char* conv_suc = 0; char* conv_suc = 0;
_parsing_context_t* context = 0; _parsing_context_t* context = 0;
_ls_node_t* lclsyminscope = 0; _ls_node_t* lclsyminscope = 0;
_ls_node_t* glbsyminscope = 0; _ls_node_t* glbsyminscope = 0;
size_t _sl = 0; size_t _sl = 0;
_data_e en = _DT_ANY;
intptr_t ptr = 0;
mb_assert(s && sym); mb_assert(s && sym);
_sl = strlen(sym); _sl = strlen(sym);
@ -2328,7 +2349,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
/* int_t */ /* int_t */
tmp.integer = (int_t)strtol(sym, &conv_suc, 0); tmp.integer = (int_t)strtol(sym, &conv_suc, 0);
if(*conv_suc == '\0') { if(*conv_suc == '\0') {
*value = tmp.any; memcpy(*value, tmp.any, sizeof(_raw_t));
result = _DT_INT; result = _DT_INT;
@ -2337,7 +2358,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
/* real_t */ /* real_t */
tmp.float_point = (real_t)strtod(sym, &conv_suc); tmp.float_point = (real_t)strtod(sym, &conv_suc);
if(*conv_suc == '\0') { if(*conv_suc == '\0') {
*value = tmp.any; memcpy(*value, tmp.any, sizeof(_raw_t));
result = _DT_REAL; result = _DT_REAL;
@ -2353,7 +2374,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
glbsyminscope = _ht_find((_ht_node_t*)s->global_var_dict, sym); glbsyminscope = _ht_find((_ht_node_t*)s->global_var_dict, sym);
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_ARRAY) { if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_ARRAY) {
tmp.obj = (_object_t*)(glbsyminscope->data); tmp.obj = (_object_t*)(glbsyminscope->data);
*value = (void*)(intptr_t)(tmp.obj->data.array->type); memcpy(*value, &(tmp.obj->data.array->type), sizeof(tmp.obj->data.array->type));
result = _DT_ARRAY; result = _DT_ARRAY;
@ -2361,7 +2382,8 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
} }
if(context->last_symbol && context->last_symbol->type == _DT_FUNC) { if(context->last_symbol && context->last_symbol->type == _DT_FUNC) {
if(strcmp("DIM", context->last_symbol->data.func->name) == 0) { if(strcmp("DIM", context->last_symbol->data.func->name) == 0) {
*value = (void*)(intptr_t)(sym[_sl - 1] == '$' ? _DT_STRING : _DT_REAL); en = (sym[_sl - 1] == '$' ? _DT_STRING : _DT_REAL);
memcpy(*value, &en, sizeof(en));
result = _DT_ARRAY; result = _DT_ARRAY;
@ -2369,10 +2391,12 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
} }
} }
/* _func_t */ /* _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_SEP)) { (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) { if(strcmp("-", sym) == 0) {
*value = (void*)(intptr_t)(_core_neg); ptr = (intptr_t)_core_neg;
memcpy(*value, &ptr, sizeof(intptr_t));
result = _DT_FUNC; result = _DT_FUNC;
@ -2382,7 +2406,8 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
lclsyminscope = _ht_find((_ht_node_t*)s->local_func_dict, sym); lclsyminscope = _ht_find((_ht_node_t*)s->local_func_dict, sym);
glbsyminscope = _ht_find((_ht_node_t*)s->global_func_dict, sym); glbsyminscope = _ht_find((_ht_node_t*)s->global_func_dict, sym);
if(lclsyminscope || glbsyminscope) { if(lclsyminscope || glbsyminscope) {
*value = lclsyminscope ? lclsyminscope->data : glbsyminscope->data; ptr = lclsyminscope ? (intptr_t)lclsyminscope->data : (intptr_t)glbsyminscope->data;
memcpy(*value, &ptr, sizeof(intptr_t));
result = _DT_FUNC; result = _DT_FUNC;
@ -2404,7 +2429,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
glbsyminscope = _ht_find((_ht_node_t*)s->global_var_dict, sym); glbsyminscope = _ht_find((_ht_node_t*)s->global_var_dict, sym);
if(glbsyminscope) { if(glbsyminscope) {
if(((_object_t*)glbsyminscope->data)->type != _DT_LABEL) { if(((_object_t*)glbsyminscope->data)->type != _DT_LABEL) {
*value = glbsyminscope->data; memcpy(*value, &glbsyminscope->data, sizeof(glbsyminscope->data));
result = _DT_VAR; result = _DT_VAR;
@ -2416,7 +2441,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, void** value) {
if(!context->last_symbol || context->last_symbol->type == _DT_EOS) { if(!context->last_symbol || context->last_symbol->type == _DT_EOS) {
glbsyminscope = _ht_find((_ht_node_t*)s->global_var_dict, sym); glbsyminscope = _ht_find((_ht_node_t*)s->global_var_dict, sym);
if(glbsyminscope) { if(glbsyminscope) {
*value = glbsyminscope->data; memcpy(*value, &glbsyminscope->data, sizeof(glbsyminscope->data));
} }
result = _DT_LABEL; result = _DT_LABEL;
@ -2442,11 +2467,13 @@ int _parse_char(mb_interpreter_t* s, char c, int pos, unsigned short row, unsign
/* Parse a char */ /* Parse a char */
int result = MB_FUNC_OK; int result = MB_FUNC_OK;
_parsing_context_t* context = 0; _parsing_context_t* context = 0;
char last_char = '\0';
mb_assert(s && s->parsing_context); mb_assert(s && s->parsing_context);
context = (_parsing_context_t*)(s->parsing_context); context = (_parsing_context_t*)(s->parsing_context);
last_char = context->current_char;
context->current_char = c; context->current_char = c;
if(context->parsing_state == _PS_NORMAL) { if(context->parsing_state == _PS_NORMAL) {
@ -2478,9 +2505,13 @@ int _parse_char(mb_interpreter_t* s, char c, int pos, unsigned short row, unsign
if(_is_identifier_char(c)) { if(_is_identifier_char(c)) {
result += _append_char_to_symbol(s, c); result += _append_char_to_symbol(s, c);
} else if(_is_operator_char(c)) { } else if(_is_operator_char(c)) {
context->symbol_state = _SS_OPERATOR; if((last_char == 'e' || last_char == 'E') && c == '-') {
result += _cut_symbol(s, pos, row, col); result += _append_char_to_symbol(s, c);
result += _append_char_to_symbol(s, c); } else {
context->symbol_state = _SS_OPERATOR;
result += _cut_symbol(s, pos, row, col);
result += _append_char_to_symbol(s, c);
}
} else { } else {
_handle_error(s, SE_PS_INVALID_CHAR, pos, row, col, MB_FUNC_ERR, _exit, result); _handle_error(s, SE_PS_INVALID_CHAR, pos, row, col, MB_FUNC_ERR, _exit, result);
} }
@ -4217,9 +4248,13 @@ int _core_neg(mb_interpreter_t* s, void** l) {
running = (_running_context_t*)(s->running_context); running = (_running_context_t*)(s->running_context);
inep = (int*)_ls_back(running->in_neg_expr)->data; if(!_ls_empty(running->in_neg_expr)) {
inep = (int*)_ls_back(running->in_neg_expr)->data;
}
(*inep)++; if(inep) {
(*inep)++;
}
mb_check(mb_attempt_func_begin(s, l)); mb_check(mb_attempt_func_begin(s, l));
@ -4227,7 +4262,9 @@ int _core_neg(mb_interpreter_t* s, void** l) {
mb_check(mb_attempt_func_end(s, l)); mb_check(mb_attempt_func_end(s, l));
(*inep)--; if(inep) {
(*inep)--;
}
switch(arg.type) { switch(arg.type) {
case MB_DT_INT: case MB_DT_INT:

View File

@ -1,265 +1,267 @@
/* /*
** This source file is part of MY-BASIC ** This source file is part of MY-BASIC
** **
** 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 - 2015 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
** the Software without restriction, including without limitation the rights to ** the Software without restriction, including without limitation the rights to
** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
** the Software, and to permit persons to whom the Software is furnished to do so, ** the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions: ** subject to the following conditions:
** **
** The above copyright notice and this permission notice shall be included in all ** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software. ** copies or substantial portions of the Software.
** **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#ifndef __MY_BASIC_H__ #ifndef __MY_BASIC_H__
#define __MY_BASIC_H__ #define __MY_BASIC_H__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
#ifndef MBAPI #ifndef MBAPI
# define MBAPI # define MBAPI
#endif /* MBAPI */ #endif /* MBAPI */
#ifndef MB_COMPACT_MODE #ifndef MB_COMPACT_MODE
# define MB_COMPACT_MODE # define MB_COMPACT_MODE
#endif /* MB_COMPACT_MODE */ #endif /* MB_COMPACT_MODE */
#ifdef MB_COMPACT_MODE #ifdef MB_COMPACT_MODE
# pragma pack(1) # pragma pack(1)
#endif /* MB_COMPACT_MODE */ #endif /* MB_COMPACT_MODE */
#ifndef true #ifndef true
# define true (!0) # define true (!0)
#endif #endif
#ifndef false #ifndef false
# define false (0) # define false (0)
#endif #endif
#ifndef bool_t #ifndef bool_t
# define bool_t int # define bool_t int
#endif #endif
#ifndef byte_t #ifndef byte_t
# define byte_t unsigned char # define byte_t unsigned char
#endif #endif
#ifndef int_t #ifndef int_t
# define int_t int # define int_t int
#endif #endif
#ifndef real_t #ifndef real_t
# define real_t float # define real_t float
#endif #endif
#ifndef _MSC_VER #ifndef _MSC_VER
# ifndef _strcmpi # ifndef _strcmpi
# ifdef __BORLANDC__ # ifdef __BORLANDC__
# define _strcmpi stricmp # define _strcmpi stricmp
# else /* __BORLANDC__*/ # elif defined __POCC__
# define _strcmpi strcasecmp # define _strcmpi _stricmp
# endif /* __BORLANDC__ */ # else /* __BORLANDC__*/
# endif /* _strcmpi */ # define _strcmpi strcasecmp
#endif /* _MSC_VER */ # endif /* __BORLANDC__ */
# endif /* _strcmpi */
#ifndef mb_assert #endif /* _MSC_VER */
# define mb_assert(__a) do { ((void)(__a)); assert(__a); } while(0)
#endif /* mb_assert */ #ifndef mb_assert
# define mb_assert(__a) do { ((void)(__a)); assert(__a); } while(0)
#ifndef mb_static_assert #endif /* mb_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) #ifndef mb_static_assert
# define _compile_time_assert2(x, l) _compile_time_assert3(x, l) # define _static_assert_impl(cond, msg) typedef char static_assertion_##msg[(!!(cond)) * 2 - 1]
# define mb_static_assert(x) _compile_time_assert2(x, __LINE__) # define _compile_time_assert3(x, l) _static_assert_impl(x, static_assertion_at_line_##l)
#endif /* mb_static_assert */ # define _compile_time_assert2(x, l) _compile_time_assert3(x, l)
# define mb_static_assert(x) _compile_time_assert2(x, __LINE__)
#ifndef mb_unrefvar #endif /* mb_static_assert */
# define mb_unrefvar(__v) ((void)(__v))
#endif /* mb_unrefvar */ #ifndef mb_unrefvar
# define mb_unrefvar(__v) ((void)(__v))
#ifndef MB_CODES #endif /* mb_unrefvar */
# define MB_CODES
# define MB_FUNC_OK 0 #ifndef MB_CODES
# define MB_FUNC_BYE 1001 # define MB_CODES
# define MB_FUNC_WARNING 1002 # define MB_FUNC_OK 0
# define MB_FUNC_ERR 1003 # define MB_FUNC_BYE 1001
# define MB_FUNC_END 1004 # define MB_FUNC_WARNING 1002
# define MB_FUNC_SUSPEND 1005 # define MB_FUNC_ERR 1003
# define MB_PARSING_ERR 3001 # define MB_FUNC_END 1004
# define MB_LOOP_BREAK 5001 # define MB_FUNC_SUSPEND 1005
# define MB_LOOP_CONTINUE 5002 # define MB_PARSING_ERR 3001
# define MB_SUB_RETURN 5101 # define MB_LOOP_BREAK 5001
# define MB_EXTENDED_ABORT 9001 # define MB_LOOP_CONTINUE 5002
#endif /* MB_CODES */ # define MB_SUB_RETURN 5101
# define MB_EXTENDED_ABORT 9001
#ifndef mb_check #endif /* MB_CODES */
# define mb_check(__r) { int __hr = __r; if(__hr != MB_FUNC_OK) { return __hr; } }
#endif /* mb_check */ #ifndef mb_check
# define mb_check(__r) { int __hr = __r; if(__hr != MB_FUNC_OK) { return __hr; } }
#ifndef mb_reg_fun #endif /* mb_check */
# define mb_reg_fun(__s, __f) mb_register_func(__s, #__f, __f)
#endif /* mb_reg_fun */ #ifndef mb_reg_fun
#ifndef mb_rem_fun # define mb_reg_fun(__s, __f) mb_register_func(__s, #__f, __f)
# define mb_rem_fun(__s, __f) mb_remove_func(__s, #__f) #endif /* mb_reg_fun */
#endif /* mb_rem_fun */ #ifndef mb_rem_fun
#ifndef mb_rem_res_fun # define mb_rem_fun(__s, __f) mb_remove_func(__s, #__f)
# define mb_rem_res_fun(__s, __f) mb_remove_reserved_func(__s, #__f) #endif /* mb_rem_fun */
#endif /* mb_rem_res_fun */ #ifndef mb_rem_res_fun
# define mb_rem_res_fun(__s, __f) mb_remove_reserved_func(__s, #__f)
struct mb_interpreter_t; #endif /* mb_rem_res_fun */
typedef enum mb_error_e { struct mb_interpreter_t;
SE_NO_ERR = 0,
/** Common */ typedef enum mb_error_e {
SE_CM_MB_OPEN_FAILED, SE_NO_ERR = 0,
SE_CM_FUNC_EXISTS, /** Common */
SE_CM_FUNC_NOT_EXISTS, SE_CM_MB_OPEN_FAILED,
/** Parsing */ SE_CM_FUNC_EXISTS,
SE_PS_FILE_OPEN_FAILED, SE_CM_FUNC_NOT_EXISTS,
SE_PS_SYMBOL_TOO_LONG, /** Parsing */
SE_PS_INVALID_CHAR, SE_PS_FILE_OPEN_FAILED,
/** Running */ SE_PS_SYMBOL_TOO_LONG,
SE_RN_NOT_SUPPORTED, SE_PS_INVALID_CHAR,
SE_RN_EMPTY_PROGRAM, /** Running */
SE_RN_SYNTAX, SE_RN_NOT_SUPPORTED,
SE_RN_INVALID_DATA_TYPE, SE_RN_EMPTY_PROGRAM,
SE_RN_TYPE_NOT_MATCH, SE_RN_SYNTAX,
SE_RN_ILLEGAL_BOUND, SE_RN_INVALID_DATA_TYPE,
SE_RN_DIMENSION_TOO_MUCH, SE_RN_TYPE_NOT_MATCH,
SE_RN_OPERATION_FAILED, SE_RN_ILLEGAL_BOUND,
SE_RN_DIMENSION_OUT_OF_BOUND, SE_RN_DIMENSION_TOO_MUCH,
SE_RN_ARRAY_OUT_OF_BOUND, SE_RN_OPERATION_FAILED,
SE_RN_LABEL_NOT_EXISTS, SE_RN_DIMENSION_OUT_OF_BOUND,
SE_RN_NO_RETURN_POINT, SE_RN_ARRAY_OUT_OF_BOUND,
SE_RN_COLON_EXPECTED, SE_RN_LABEL_NOT_EXISTS,
SE_RN_COMMA_OR_SEMICOLON_EXPECTED, SE_RN_NO_RETURN_POINT,
SE_RN_ARRAY_IDENTIFIER_EXPECTED, SE_RN_COLON_EXPECTED,
SE_RN_OPEN_BRACKET_EXPECTED, SE_RN_COMMA_OR_SEMICOLON_EXPECTED,
SE_RN_CLOSE_BRACKET_EXPECTED, SE_RN_ARRAY_IDENTIFIER_EXPECTED,
SE_RN_ARRAY_SUBSCRIPT_EXPECTED, SE_RN_OPEN_BRACKET_EXPECTED,
SE_RN_STRUCTURE_NOT_COMPLETED, SE_RN_CLOSE_BRACKET_EXPECTED,
SE_RN_FUNCTION_EXPECTED, SE_RN_ARRAY_SUBSCRIPT_EXPECTED,
SE_RN_STRING_EXPECTED, SE_RN_STRUCTURE_NOT_COMPLETED,
SE_RN_VAR_OR_ARRAY_EXPECTED, SE_RN_FUNCTION_EXPECTED,
SE_RN_ASSIGN_OPERATOR_EXPECTED, SE_RN_STRING_EXPECTED,
SE_RN_INTEGER_EXPECTED, SE_RN_VAR_OR_ARRAY_EXPECTED,
SE_RN_ELSE_EXPECTED, SE_RN_ASSIGN_OPERATOR_EXPECTED,
SE_RN_TO_EXPECTED, SE_RN_INTEGER_EXPECTED,
SE_RN_NEXT_EXPECTED, SE_RN_ELSE_EXPECTED,
SE_RN_UNTIL_EXPECTED, SE_RN_TO_EXPECTED,
SE_RN_LOOP_VAR_EXPECTED, SE_RN_NEXT_EXPECTED,
SE_RN_JUMP_LABEL_EXPECTED, SE_RN_UNTIL_EXPECTED,
SE_RN_VARIABLE_EXPECTED, SE_RN_LOOP_VAR_EXPECTED,
SE_RN_INVALID_ID_USAGE, SE_RN_JUMP_LABEL_EXPECTED,
SE_RN_OPERATOR_EXPECTED, SE_RN_VARIABLE_EXPECTED,
SE_RN_CALCULATION_ERROR, SE_RN_INVALID_ID_USAGE,
SE_RN_DIVIDE_BY_ZERO, SE_RN_OPERATOR_EXPECTED,
SE_RN_MOD_BY_ZERO, SE_RN_CALCULATION_ERROR,
SE_RN_INVALID_EXPRESSION, SE_RN_DIVIDE_BY_ZERO,
SE_RN_OUT_OF_MEMORY, SE_RN_MOD_BY_ZERO,
/** Extended abort */ SE_RN_INVALID_EXPRESSION,
SE_EA_EXTENDED_ABORT, SE_RN_OUT_OF_MEMORY,
/** Extra */ /** Extended abort */
SE_COUNT SE_EA_EXTENDED_ABORT,
} mb_error_e; /** Extra */
SE_COUNT
typedef enum mb_data_e { } mb_error_e;
MB_DT_NIL = -1,
MB_DT_INT = 0, typedef enum mb_data_e {
MB_DT_REAL, MB_DT_NIL = -1,
MB_DT_STRING MB_DT_INT = 0,
} mb_data_e; MB_DT_REAL,
MB_DT_STRING
typedef union mb_value_u { } mb_data_e;
int_t integer;
real_t float_point; typedef union mb_value_u {
char* string; int_t integer;
} mb_value_u; real_t float_point;
char* string;
typedef struct mb_value_t { } mb_value_u;
mb_data_e type;
mb_value_u value; typedef struct mb_value_t {
} mb_value_t; mb_data_e type;
mb_value_u value;
typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, int, unsigned short, unsigned short, int); } mb_value_t;
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
typedef int (* mb_print_func_t)(const char*, ...); typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, int, unsigned short, unsigned short, int);
typedef int (* mb_input_func_t)(char*, int); typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
typedef int (* mb_print_func_t)(const char*, ...);
typedef struct mb_interpreter_t { typedef int (* mb_input_func_t)(char*, int);
void* local_func_dict;
void* global_func_dict; typedef struct mb_interpreter_t {
void* global_var_dict; void* local_func_dict;
void* ast; void* global_func_dict;
void* parsing_context; void* global_var_dict;
void* running_context; void* ast;
mb_error_e last_error; void* parsing_context;
int last_error_pos; void* running_context;
unsigned short last_error_row; mb_error_e last_error;
unsigned short last_error_col; int last_error_pos;
mb_error_handler_t error_handler; unsigned short last_error_row;
mb_print_func_t printer; unsigned short last_error_col;
mb_input_func_t inputer; mb_error_handler_t error_handler;
void* userdata; mb_print_func_t printer;
} mb_interpreter_t; mb_input_func_t inputer;
void* userdata;
MBAPI unsigned int mb_ver(void); } mb_interpreter_t;
MBAPI const char* mb_ver_string(void);
MBAPI unsigned int mb_ver(void);
MBAPI int mb_init(void); MBAPI const char* mb_ver_string(void);
MBAPI int mb_dispose(void);
MBAPI int mb_open(mb_interpreter_t** s); MBAPI int mb_init(void);
MBAPI int mb_close(mb_interpreter_t** s); MBAPI int mb_dispose(void);
MBAPI int mb_reset(mb_interpreter_t** s, bool_t clrf); MBAPI int mb_open(mb_interpreter_t** s);
MBAPI int mb_close(mb_interpreter_t** s);
MBAPI int mb_register_func(mb_interpreter_t* s, const char* n, mb_func_t f); MBAPI int mb_reset(mb_interpreter_t** s, bool_t clrf);
MBAPI int mb_remove_func(mb_interpreter_t* s, const char* n);
MBAPI int mb_remove_reserved_func(mb_interpreter_t* s, const char* n); MBAPI int mb_register_func(mb_interpreter_t* s, const char* n, mb_func_t f);
MBAPI int mb_remove_func(mb_interpreter_t* s, const char* n);
MBAPI int mb_attempt_func_begin(mb_interpreter_t* s, void** l); MBAPI int mb_remove_reserved_func(mb_interpreter_t* s, const char* n);
MBAPI int mb_attempt_func_end(mb_interpreter_t* s, void** l);
MBAPI int mb_attempt_open_bracket(mb_interpreter_t* s, void** l); MBAPI int mb_attempt_func_begin(mb_interpreter_t* s, void** l);
MBAPI int mb_attempt_close_bracket(mb_interpreter_t* s, void** l); MBAPI int mb_attempt_func_end(mb_interpreter_t* s, void** l);
MBAPI int mb_pop_int(mb_interpreter_t* s, void** l, int_t* val); MBAPI int mb_attempt_open_bracket(mb_interpreter_t* s, void** l);
MBAPI int mb_pop_real(mb_interpreter_t* s, void** l, real_t* val); MBAPI int mb_attempt_close_bracket(mb_interpreter_t* s, void** l);
MBAPI int mb_pop_string(mb_interpreter_t* s, void** l, char** val); MBAPI int mb_pop_int(mb_interpreter_t* s, void** l, int_t* val);
MBAPI int mb_pop_value(mb_interpreter_t* s, void** l, mb_value_t* val); MBAPI int mb_pop_real(mb_interpreter_t* s, void** l, real_t* val);
MBAPI int mb_push_int(mb_interpreter_t* s, void** l, int_t val); MBAPI int mb_pop_string(mb_interpreter_t* s, void** l, char** val);
MBAPI int mb_push_real(mb_interpreter_t* s, void** l, real_t val); MBAPI int mb_pop_value(mb_interpreter_t* s, void** l, mb_value_t* val);
MBAPI int mb_push_string(mb_interpreter_t* s, void** l, char* val); MBAPI int mb_push_int(mb_interpreter_t* s, void** l, int_t val);
MBAPI int mb_push_value(mb_interpreter_t* s, void** l, mb_value_t val); MBAPI int mb_push_real(mb_interpreter_t* s, void** l, real_t val);
MBAPI int mb_push_string(mb_interpreter_t* s, void** l, char* val);
MBAPI int mb_load_string(mb_interpreter_t* s, const char* l); MBAPI int mb_push_value(mb_interpreter_t* s, void** l, mb_value_t val);
MBAPI int mb_load_file(mb_interpreter_t* s, const char* f);
MBAPI int mb_run(mb_interpreter_t* s); MBAPI int mb_load_string(mb_interpreter_t* s, const char* l);
MBAPI int mb_suspend(mb_interpreter_t* s, void** l); MBAPI int mb_load_file(mb_interpreter_t* s, const char* f);
MBAPI int mb_run(mb_interpreter_t* s);
MBAPI mb_error_e mb_get_last_error(mb_interpreter_t* s); MBAPI int mb_suspend(mb_interpreter_t* s, void** l);
MBAPI const char* mb_get_error_desc(mb_error_e err);
MBAPI int mb_set_error_handler(mb_interpreter_t* s, mb_error_handler_t h); MBAPI mb_error_e mb_get_last_error(mb_interpreter_t* s);
MBAPI int mb_set_printer(mb_interpreter_t* s, mb_print_func_t p); MBAPI const char* mb_get_error_desc(mb_error_e err);
MBAPI int mb_set_inputer(mb_interpreter_t* s, mb_input_func_t p); MBAPI int mb_set_error_handler(mb_interpreter_t* s, mb_error_handler_t h);
MBAPI int mb_set_printer(mb_interpreter_t* s, mb_print_func_t p);
MBAPI int mb_gets(char* buf, int s); MBAPI int mb_set_inputer(mb_interpreter_t* s, mb_input_func_t p);
MBAPI char* mb_strdup(char* val, unsigned size); MBAPI int mb_gets(char* buf, int s);
#ifdef MB_COMPACT_MODE MBAPI char* mb_strdup(char* val, unsigned size);
# pragma pack()
#endif /* MB_COMPACT_MODE */ #ifdef MB_COMPACT_MODE
# pragma pack()
#ifdef __cplusplus #endif /* MB_COMPACT_MODE */
}
#endif /* __cplusplus */ #ifdef __cplusplus
}
#endif /* __MY_BASIC_H__ */ #endif /* __cplusplus */
#endif /* __MY_BASIC_H__ */

Binary file not shown.

Binary file not shown.

View 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, 46" VALUE "FileVersion", "1, 0, 0, 47"
VALUE "InternalName", "my_basic" VALUE "InternalName", "my_basic"
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 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, 46" VALUE "ProductVersion", "1, 0, 0, 47"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -1,439 +1,444 @@
/* /*
** This source file is part of MY-BASIC ** This source file is part of MY-BASIC
** **
** 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 - 2015 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
** the Software without restriction, including without limitation the rights to ** the Software without restriction, including without limitation the rights to
** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
** the Software, and to permit persons to whom the Software is furnished to do so, ** the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions: ** subject to the following conditions:
** **
** The above copyright notice and this permission notice shall be included in all ** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software. ** copies or substantial portions of the Software.
** **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
# ifndef _CRT_SECURE_NO_WARNINGS # ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS
# endif /* _CRT_SECURE_NO_WARNINGS */ # endif /* _CRT_SECURE_NO_WARNINGS */
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#include "../core/my_basic.h" #include "../core/my_basic.h"
#ifdef _MSC_VER #ifdef _MSC_VER
# include <crtdbg.h> # include <crtdbg.h>
# include <conio.h> # include <conio.h>
#elif !defined __BORLANDC__ #elif !defined __BORLANDC__
# include <unistd.h> # include <unistd.h>
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(disable : 4127) # pragma warning(disable : 4127)
# pragma warning(disable : 4996) # pragma warning(disable : 4996)
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#ifdef __BORLANDC__ #ifdef __BORLANDC__
# pragma warn -8004 # pragma warn -8004
# pragma warn -8008 # pragma warn -8008
# pragma warn -8066 # pragma warn -8066
#endif /* __BORLANDC__ */ #endif /* __BORLANDC__ */
#define _MAX_LINE_LENGTH 256 #ifdef __POCC__
#define _str_eq(__str1, __str2) (_strcmpi(__str1, __str2) == 0) # define unlink _unlink
# define strdup _strdup
#define _LINE_INC_STEP 16 #endif /* __POCC__ */
#define _NO_END(s) (MB_FUNC_OK == s || MB_FUNC_SUSPEND == s || MB_FUNC_WARNING == s || MB_FUNC_ERR == s || MB_FUNC_END == s) #define _MAX_LINE_LENGTH 256
#define _str_eq(__str1, __str2) (_strcmpi(__str1, __str2) == 0)
typedef struct _code_line_t {
char** lines; #define _LINE_INC_STEP 16
int count;
int size; #define _NO_END(s) (MB_FUNC_OK == s || MB_FUNC_SUSPEND == s || MB_FUNC_WARNING == s || MB_FUNC_ERR == s || MB_FUNC_END == s)
} _code_line_t;
typedef struct _code_line_t {
static mb_interpreter_t* bas = 0; char** lines;
int count;
static _code_line_t* c = 0; int size;
} _code_line_t;
static _code_line_t* _create_code(void) {
_code_line_t* result = (_code_line_t*)malloc(sizeof(_code_line_t)); static mb_interpreter_t* bas = 0;
result->count = 0;
result->size = _LINE_INC_STEP; static _code_line_t* c = 0;
result->lines = (char**)malloc(sizeof(char*) * result->size);
static _code_line_t* _create_code(void) {
return result; _code_line_t* result = (_code_line_t*)malloc(sizeof(_code_line_t));
} result->count = 0;
result->size = _LINE_INC_STEP;
static void _destroy_code(_code_line_t* code) { result->lines = (char**)malloc(sizeof(char*) * result->size);
int i = 0;
mb_assert(code); return result;
for(i = 0; i < code->count; ++i) { }
free(code->lines[i]);
} static void _destroy_code(_code_line_t* code) {
free(code->lines); int i = 0;
free(code); mb_assert(code);
} for(i = 0; i < code->count; ++i) {
free(code->lines[i]);
static void _clear_code(_code_line_t* code) { }
int i = 0; free(code->lines);
mb_assert(code); free(code);
for(i = 0; i < code->count; ++i) { }
free(code->lines[i]);
} static void _clear_code(_code_line_t* code) {
code->count = 0; int i = 0;
} mb_assert(code);
for(i = 0; i < code->count; ++i) {
static void _append_line(_code_line_t* code, char* txt) { free(code->lines[i]);
mb_assert(code && txt); }
if(code->count + 1 == code->size) { code->count = 0;
code->size += _LINE_INC_STEP; }
code->lines = (char**)realloc(code->lines, sizeof(char*) * code->size);
} static void _append_line(_code_line_t* code, char* txt) {
code->lines[code->count++] = strdup(txt); mb_assert(code && txt);
} if(code->count + 1 == code->size) {
code->size += _LINE_INC_STEP;
static char* _get_code(_code_line_t* code) { code->lines = (char**)realloc(code->lines, sizeof(char*) * code->size);
char* result = 0; }
int i = 0; code->lines[code->count++] = strdup(txt);
mb_assert(code); }
result = (char*)malloc((_MAX_LINE_LENGTH + 2) * code->count + 1);
result[0] = '\0'; static char* _get_code(_code_line_t* code) {
for(i = 0; i < code->count; ++i) { char* result = 0;
result = strcat(result, code->lines[i]); int i = 0;
if(i != code->count - 1) { mb_assert(code);
result = strcat(result, "\r\n"); result = (char*)malloc((_MAX_LINE_LENGTH + 2) * code->count + 1);
} result[0] = '\0';
} for(i = 0; i < code->count; ++i) {
result = strcat(result, code->lines[i]);
return result; if(i != code->count - 1) {
} result = strcat(result, "\r\n");
}
static void _set_code(_code_line_t* code, char* txt) { }
char* cursor = 0;
char _c = '\0'; return result;
mb_assert(code); }
if(!txt) {
return; static void _set_code(_code_line_t* code, char* txt) {
} char* cursor = 0;
_clear_code(code); char _c = '\0';
cursor = txt; mb_assert(code);
do { if(!txt) {
_c = *cursor; return;
if(_c == '\r' || _c == '\n' || _c == '\0') { }
cursor[0] = '\0'; _clear_code(code);
if(_c == '\r' && *(cursor + 1) == '\n') { cursor = txt;
++cursor; do {
} _c = *cursor;
_append_line(code, txt); if(_c == '\r' || _c == '\n' || _c == '\0') {
txt = cursor + 1; cursor[0] = '\0';
} if(_c == '\r' && *(cursor + 1) == '\n') {
++cursor; ++cursor;
} while(_c); }
} _append_line(code, txt);
txt = cursor + 1;
static char* _load_file(const char* path) { }
FILE* fp = 0; ++cursor;
char* result = 0; } while(_c);
long curpos = 0; }
long l = 0;
mb_assert(path); static char* _load_file(const char* path) {
fp = fopen(path, "rb"); FILE* fp = 0;
if(fp) { char* result = 0;
curpos = ftell(fp); long curpos = 0;
fseek(fp, 0L, SEEK_END); long l = 0;
l = ftell(fp); mb_assert(path);
fseek(fp, curpos, SEEK_SET); fp = fopen(path, "rb");
result = (char*)malloc((size_t)(l + 1)); if(fp) {
mb_assert(result); curpos = ftell(fp);
fread(result, 1, l, fp); fseek(fp, 0L, SEEK_END);
fclose(fp); l = ftell(fp);
result[l] = '\0'; fseek(fp, curpos, SEEK_SET);
} result = (char*)malloc((size_t)(l + 1));
mb_assert(result);
return result; fread(result, 1, l, fp);
} fclose(fp);
result[l] = '\0';
static int _save_file(const char* path, const char* txt) { }
FILE* fp = 0;
mb_assert(path && txt); return result;
fp = fopen(path, "wb"); }
if(fp) {
fwrite(txt, sizeof(char), strlen(txt), fp); static int _save_file(const char* path, const char* txt) {
fclose(fp); FILE* fp = 0;
mb_assert(path && txt);
return 1; fp = fopen(path, "wb");
} if(fp) {
fwrite(txt, sizeof(char), strlen(txt), fp);
return 0; fclose(fp);
}
return 1;
static int beep(mb_interpreter_t* s, void** l) { }
int result = MB_FUNC_OK;
return 0;
mb_assert(s && l); }
mb_check(mb_attempt_func_begin(s, l)); static int beep(mb_interpreter_t* s, void** l) {
mb_check(mb_attempt_func_end(s, l)); int result = MB_FUNC_OK;
putchar('\a'); mb_assert(s && l);
return result; mb_check(mb_attempt_func_begin(s, l));
} mb_check(mb_attempt_func_end(s, l));
static void _on_error(mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) { putchar('\a');
mb_unrefvar(s);
if(SE_NO_ERR != e) { return result;
printf("Error:\n [POS] %d, [ROW] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", p, row, col, e, m, abort_code); }
}
} static void _on_error(mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
mb_unrefvar(s);
static void _on_startup(void) { if(SE_NO_ERR != e) {
c = _create_code(); printf("Error:\n [POS] %d, [ROW] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", p, row, col, e, m, abort_code);
}
mb_init(); }
mb_open(&bas); static void _on_startup(void) {
mb_set_error_handler(bas, _on_error); c = _create_code();
mb_reg_fun(bas, beep); mb_init();
}
mb_open(&bas);
static void _on_exit(void) { mb_set_error_handler(bas, _on_error);
mb_close(&bas);
mb_reg_fun(bas, beep);
mb_dispose(); }
_destroy_code(c); static void _on_exit(void) {
c = 0; mb_close(&bas);
#if defined _MSC_VER && !defined _WIN64 mb_dispose();
if(0 != _CrtDumpMemoryLeaks()) { _asm { int 3 } }
#endif /* _MSC_VER && !_WIN64 */ _destroy_code(c);
} c = 0;
static void _clear_screen(void) { #if defined _MSC_VER && !defined _WIN64
#ifdef _MSC_VER if(0 != _CrtDumpMemoryLeaks()) { _asm { int 3 } }
system("cls"); #endif /* _MSC_VER && !_WIN64 */
#else /* _MSC_VER */ }
system("clear");
#endif /* _MSC_VER */ static void _clear_screen(void) {
} #ifdef _MSC_VER
system("cls");
static int _new_program(void) { #else /* _MSC_VER */
_clear_code(c); system("clear");
#endif /* _MSC_VER */
return mb_reset(&bas, false); }
}
static int _new_program(void) {
static void _list_program(const char* sn, const char* cn) { _clear_code(c);
long lsn = 0;
long lcn = 0; return mb_reset(&bas, false);
mb_assert(sn && cn); }
lsn = atoi(sn);
lcn = atoi(cn); static void _list_program(const char* sn, const char* cn) {
if(lsn == 0 && lcn == 0) { long lsn = 0;
char* txt = _get_code(c); long lcn = 0;
printf("%s\n", txt); mb_assert(sn && cn);
free(txt); lsn = atoi(sn);
} else { lcn = atoi(cn);
long i = 0; if(lsn == 0 && lcn == 0) {
long e = 0; char* txt = _get_code(c);
if(lsn < 1 || lsn > c->count) { printf("%s\n", txt);
printf("Line number %ld out of bound.\n", lsn); free(txt);
} else {
return; long i = 0;
} long e = 0;
if(lcn < 0) { if(lsn < 1 || lsn > c->count) {
printf("Invalid line count %ld.\n", lcn); printf("Line number %ld out of bound.\n", lsn);
return; return;
} }
--lsn; if(lcn < 0) {
e = lcn ? lsn + lcn : c->count; printf("Invalid line count %ld.\n", lcn);
for(i = lsn; i < e; ++i) {
if(i >= c->count) { return;
break; }
} --lsn;
printf("%s\n", c->lines[i]); e = lcn ? lsn + lcn : c->count;
} for(i = lsn; i < e; ++i) {
} if(i >= c->count) {
} break;
}
static void _edit_program(const char* no) { printf("%s\n", c->lines[i]);
char line[_MAX_LINE_LENGTH]; }
long lno = 0; }
mb_assert(no); }
lno = atoi(no);
if(lno < 1 || lno > c->count) { static void _edit_program(const char* no) {
printf("Line number %ld out of bound.\n", lno); char line[_MAX_LINE_LENGTH];
long lno = 0;
return; mb_assert(no);
} lno = atoi(no);
--lno; if(lno < 1 || lno > c->count) {
memset(line, 0, _MAX_LINE_LENGTH); printf("Line number %ld out of bound.\n", lno);
printf("%ld]", lno + 1);
mb_gets(line, _MAX_LINE_LENGTH); return;
c->lines[lno] = (char*)realloc(c->lines[lno], strlen(line) + 1); }
strcpy(c->lines[lno], line); --lno;
} memset(line, 0, _MAX_LINE_LENGTH);
printf("%ld]", lno + 1);
static void _load_program(const char* path) { mb_gets(line, _MAX_LINE_LENGTH);
char* txt = _load_file(path); c->lines[lno] = (char*)realloc(c->lines[lno], strlen(line) + 1);
if(txt) { strcpy(c->lines[lno], line);
_new_program(); }
_set_code(c, txt);
free(txt); static void _load_program(const char* path) {
if(c->count == 1) { char* txt = _load_file(path);
printf("Load done. %d line loaded.\n", c->count); if(txt) {
} else { _new_program();
printf("Load done. %d lines loaded.\n", c->count); _set_code(c, txt);
} free(txt);
} else { if(c->count == 1) {
printf("Cannot load file \"%s\"\n", path); printf("Load done. %d line loaded.\n", c->count);
} } else {
} printf("Load done. %d lines loaded.\n", c->count);
}
static void _save_program(const char* path) { } else {
char* txt = _get_code(c); printf("Cannot load file \"%s\"\n", path);
if(!_save_file(path, txt)) { }
printf("Cannot save file \"%s\"\n", path); }
} else {
if(c->count == 1) { static void _save_program(const char* path) {
printf("Save done. %d line saved.\n", c->count); char* txt = _get_code(c);
} else { if(!_save_file(path, txt)) {
printf("Save done. %d lines saved.\n", c->count); printf("Cannot save file \"%s\"\n", path);
} } else {
} if(c->count == 1) {
free(txt); printf("Save done. %d line saved.\n", c->count);
} } else {
printf("Save done. %d lines saved.\n", c->count);
static void _kill_program(const char* path) { }
if(!unlink(path)) { }
printf("Delete file \"%s\" successfully.\n", path); free(txt);
} else { }
printf("Delete file \"%s\" failed.\n", path);
} static void _kill_program(const char* path) {
} if(!unlink(path)) {
printf("Delete file \"%s\" successfully.\n", path);
static void _show_tip(void) { } else {
printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string()); printf("Delete file \"%s\" failed.\n", path);
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("Input HELP and hint enter to view help information.\n");
} static void _show_tip(void) {
printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string());
static void _show_help(void) { printf("Copyright (C) 2011 - 2015 W. Renxin. All Rights Reserved.\n");
printf("Commands:\n"); printf("For more information, see https://github.com/paladin-t/my_basic/.\n");
printf(" CLS - Clear screen\n"); printf("Input HELP and hint enter to view help information.\n");
printf(" NEW - Clear current program\n"); }
printf(" RUN - Run current program\n");
printf(" BYE - Quit interpreter\n"); static void _show_help(void) {
printf(" LIST - List current program\n"); printf("Commands:\n");
printf(" Usage: LIST [l [n]], l is start line number, n is line count\n"); printf(" CLS - Clear screen\n");
printf(" EDIT - Edit a line in current program\n"); printf(" NEW - Clear current program\n");
printf(" Usage: EDIT n, n is line number\n"); printf(" RUN - Run current program\n");
printf(" LOAD - Load a file as current program\n"); printf(" BYE - Quit interpreter\n");
printf(" Usage: LOAD *.*\n"); printf(" LIST - List current program\n");
printf(" SAVE - Save current program to a file\n"); printf(" Usage: LIST [l [n]], l is start line number, n is line count\n");
printf(" Usage: SAVE *.*\n"); printf(" EDIT - Edit a line in current program\n");
printf(" KILL - Delete a file\n"); printf(" Usage: EDIT n, n is line number\n");
printf(" Usage: KILL *.*\n"); printf(" LOAD - Load a file as current program\n");
} printf(" Usage: LOAD *.*\n");
printf(" SAVE - Save current program to a file\n");
static int _do_line(void) { printf(" Usage: SAVE *.*\n");
int result = MB_FUNC_OK; printf(" KILL - Delete a file\n");
char line[_MAX_LINE_LENGTH]; printf(" Usage: KILL *.*\n");
char dup[_MAX_LINE_LENGTH]; }
mb_assert(bas); static int _do_line(void) {
int result = MB_FUNC_OK;
memset(line, 0, _MAX_LINE_LENGTH); char line[_MAX_LINE_LENGTH];
printf("]"); char dup[_MAX_LINE_LENGTH];
mb_gets(line, _MAX_LINE_LENGTH);
mb_assert(bas);
memcpy(dup, line, _MAX_LINE_LENGTH);
strtok(line, " "); memset(line, 0, _MAX_LINE_LENGTH);
printf("]");
if(_str_eq(line, "")) { mb_gets(line, _MAX_LINE_LENGTH);
/* Do nothing */
} else if(_str_eq(line, "HELP")) { memcpy(dup, line, _MAX_LINE_LENGTH);
_show_help(); strtok(line, " ");
} else if(_str_eq(line, "CLS")) {
_clear_screen(); if(_str_eq(line, "")) {
} else if(_str_eq(line, "NEW")) { /* Do nothing */
result = _new_program(); } else if(_str_eq(line, "HELP")) {
} else if(_str_eq(line, "RUN")) { _show_help();
char* txt = _get_code(c); } else if(_str_eq(line, "CLS")) {
result = mb_reset(&bas, false); _clear_screen();
result = mb_load_string(bas, txt); } else if(_str_eq(line, "NEW")) {
free(txt); result = _new_program();
result = mb_run(bas); } else if(_str_eq(line, "RUN")) {
printf("\n"); char* txt = _get_code(c);
} else if(_str_eq(line, "BYE")) { result = mb_reset(&bas, false);
result = MB_FUNC_BYE; result = mb_load_string(bas, txt);
} else if(_str_eq(line, "LIST")) { free(txt);
char* sn = line + strlen(line) + 1; result = mb_run(bas);
char* cn = 0; printf("\n");
strtok(sn, " "); } else if(_str_eq(line, "BYE")) {
cn = sn + strlen(sn) + 1; result = MB_FUNC_BYE;
_list_program(sn, cn); } else if(_str_eq(line, "LIST")) {
} else if(_str_eq(line, "EDIT")) { char* sn = line + strlen(line) + 1;
char* no = line + strlen(line) + 1; char* cn = 0;
_edit_program(no); strtok(sn, " ");
} else if(_str_eq(line, "LOAD")) { cn = sn + strlen(sn) + 1;
char* path = line + strlen(line) + 1; _list_program(sn, cn);
_load_program(path); } else if(_str_eq(line, "EDIT")) {
} else if(_str_eq(line, "SAVE")) { char* no = line + strlen(line) + 1;
char* path = line + strlen(line) + 1; _edit_program(no);
_save_program(path); } else if(_str_eq(line, "LOAD")) {
} else if(_str_eq(line, "KILL")) { char* path = line + strlen(line) + 1;
char* path = line + strlen(line) + 1; _load_program(path);
_kill_program(path); } else if(_str_eq(line, "SAVE")) {
} else { char* path = line + strlen(line) + 1;
_append_line(c, dup); _save_program(path);
} } else if(_str_eq(line, "KILL")) {
char* path = line + strlen(line) + 1;
return result; _kill_program(path);
} } else {
_append_line(c, dup);
int main(int argc, char* argv[]) { }
int status = 0;
return result;
#if defined _MSC_VER && !defined _WIN64 }
_CrtSetBreakAlloc(0);
#endif /* _MSC_VER && !_WIN64 */ int main(int argc, char* argv[]) {
int status = 0;
atexit(_on_exit);
#if defined _MSC_VER && !defined _WIN64
_on_startup(); _CrtSetBreakAlloc(0);
#endif /* _MSC_VER && !_WIN64 */
if(argc == 1) {
_show_tip(); atexit(_on_exit);
do {
status = _do_line(); _on_startup();
} while(_NO_END(status));
} else if(argc == 2) { if(argc == 1) {
if(mb_load_file(bas, argv[1]) == MB_FUNC_OK) { _show_tip();
mb_run(bas); do {
} status = _do_line();
} else { } while(_NO_END(status));
printf("Unknown arguments\n"); } else if(argc == 2) {
_show_tip(); if(mb_load_file(bas, argv[1]) == MB_FUNC_OK) {
} mb_run(bas);
}
return 0; } else {
} printf("Unknown arguments\n");
_show_tip();
}
return 0;
}