+implemented tail recursion optimization in sub routine; +added array length gain in len function; *fixed a crash bug when returning nothing in a sub routine; *polished document.

This commit is contained in:
tony 2015-09-21 23:51:55 +08:00
parent a956338ec0
commit b6ab676ad7
7 changed files with 216 additions and 168 deletions

View File

@ -1,3 +1,9 @@
Sep. 21 2015
Implemented tail recursion optimization in sub routine
Added array length gain in LEN function
Fixed a crash bug when returning nothing in a sub routine
Polished document
Sep. 20 2015
Added array manipulation ability to script, it's able to assign an array to a variable or use it as a scripting interface argument
Added recursive sub routine support
@ -10,7 +16,7 @@ Added directly expression evaluation shell command
Sep. 17 2015
Allowed string in a boolean expression
Added support for sub routine in PRINT
Fixed a repeated disposing bug when suing sub routine
Fixed a repeated disposing bug when using sub routine
Sep. 16 2015
Added Nil type handling, including assignment, boolean operation, serialization, etc.

Binary file not shown.

View File

@ -79,8 +79,12 @@ extern "C" {
/** Macros */
#define _VER_MAJOR 1
#define _VER_MINOR 1
#define _VER_REVISION 72
#define _VER_REVISION 73
#define _VER_SUFFIX
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
#define _STRINGIZE(A) _MAKE_STRINGIZE(A)
#define _MAKE_STRINGIZE(A) #A
#define _MB_VERSION_STRING _STRINGIZE(_VER_MAJOR._VER_MINOR._VER_REVISION _VER_SUFFIX)
/* Uncomment the line below to treat warning as error */
/*#define _WARING_AS_ERROR*/
@ -407,6 +411,7 @@ typedef struct mb_interpreter_t {
_parsing_context_t* parsing_context;
_running_context_t* running_context;
unsigned char jump_set;
_routine_t* last_routine;
_ls_node_t* sub_stack;
_ls_node_t* temp_values;
_ls_node_t* suspent_point;
@ -985,11 +990,11 @@ static int _std_log(mb_interpreter_t* s, void** l);
static int _std_asc(mb_interpreter_t* s, void** l);
static int _std_chr(mb_interpreter_t* s, void** l);
static int _std_left(mb_interpreter_t* s, void** l);
static int _std_len(mb_interpreter_t* s, void** l);
static int _std_mid(mb_interpreter_t* s, void** l);
static int _std_right(mb_interpreter_t* s, void** l);
static int _std_str(mb_interpreter_t* s, void** l);
static int _std_val(mb_interpreter_t* s, void** l);
static int _std_len(mb_interpreter_t* s, void** l);
static int _std_print(mb_interpreter_t* s, void** l);
static int _std_input(mb_interpreter_t* s, void** l);
@ -1075,12 +1080,13 @@ static const _func_t _std_libs[] = {
{ "ASC", _std_asc },
{ "CHR", _std_chr },
{ "LEFT", _std_left },
{ "LEN", _std_len },
{ "MID", _std_mid },
{ "RIGHT", _std_right },
{ "STR", _std_str },
{ "VAL", _std_val },
{ "LEN", _std_len },
{ "PRINT", _std_print },
{ "INPUT", _std_input }
};
@ -1839,6 +1845,8 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
memset(c, 0, sizeof(_object_t));
_ls_pushback(garbage, c);
result = _public_value_to_internal_object(&running->intermediate_value, c);
if(c->type == _DT_STRING)
c->ref = true;
if(result != MB_FUNC_OK)
goto _exit;
if(f) {
@ -2018,9 +2026,27 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
_var_t* var = 0;
_ls_node_t* rnode = 0;
_running_context_t* running = 0;
_routine_t* lastr = 0;
mb_assert(s && l && r);
if(s->last_routine && (s->last_routine->name == r->name || !strcmp(s->last_routine->name, r->name))) {
ast = (_ls_node_t*)(*l);
_skip_to(s, &ast, 0, _DT_EOS);
if(ast && ((_object_t*)(ast->data))->type == _DT_EOS)
ast = ast->next;
if(_IS_FUNC((_object_t*)(ast->data), _core_enddef)) { /* Tail recursion optimization */
*l = r->entry;
if(*l)
*l = (*l)->next;
goto _tail;
}
}
lastr = s->last_routine;
s->last_routine = r;
running = s->running_context;
mb_check(mb_attempt_open_bracket(s, (void**)l));
@ -2094,6 +2120,9 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
s->running_context->intermediate_value = running->intermediate_value;
_exit:
s->last_routine = lastr;
_tail:
return result;
}
@ -3846,6 +3875,8 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
ast = (_ls_node_t*)_ls_popback(sub_stack);
} else if(obj && obj->type == _DT_FUNC && (_is_operator(obj->data.func->pointer) || _is_flow(obj->data.func->pointer))) {
ast = ast->next;
} else if(obj && obj->type == _DT_FUNC) {
/* Do nothing */
} else if(obj && obj->type != _DT_FUNC) {
ast = ast->next;
} else {
@ -4162,11 +4193,7 @@ unsigned int mb_ver(void) {
const char* mb_ver_string(void) {
/* Get the version text of this MY-BASIC system */
static char buf[32] = { '\0' };
if(!buf[0])
sprintf(buf, "%d.%d.%04d", _VER_MAJOR, _VER_MINOR, _VER_REVISION);
return buf;
return _MB_VERSION_STRING;
}
int mb_init(void) {
@ -4353,6 +4380,7 @@ int mb_reset(struct mb_interpreter_t** s, bool_t clrf/* = false*/) {
mb_assert(s);
(*s)->jump_set = _JMP_NIL;
(*s)->last_routine = 0;
(*s)->no_eat_comma_mark = 0;
(*s)->last_error = SE_NO_ERR;
(*s)->last_error_func = 0;
@ -6344,12 +6372,14 @@ int _core_return(mb_interpreter_t* s, void** l) {
if(running->prev) {
ast = (_ls_node_t*)(*l);
ast = ast->next;
mb_check(mb_pop_value(s, (void**)(&ast), &arg));
mb_check(mb_push_value(s, (void**)(&ast), arg));
if(mb_has_arg(s, (void**)(&ast))) {
mb_check(mb_pop_value(s, (void**)(&ast), &arg));
mb_check(mb_push_value(s, (void**)(&ast), arg));
if(arg.type == MB_DT_STRING) {
_ls_foreach(s->temp_values, _destroy_object_capsule_only);
_ls_clear(s->temp_values);
if(arg.type == MB_DT_STRING) {
_ls_foreach(s->temp_values, _destroy_object_capsule_only);
_ls_clear(s->temp_values);
}
}
}
ast = (_ls_node_t*)_ls_popback(sub_stack);
@ -7027,43 +7057,6 @@ _exit:
return result;
}
int _std_len(mb_interpreter_t* s, void** l) {
/* Get the length of a string */
int result = MB_FUNC_OK;
_ls_node_t* ast = 0;
mb_value_t arg;
_array_t* arr = 0;
mb_assert(s && l);
ast = (_ls_node_t*)(*l);
mb_check(mb_attempt_open_bracket(s, l));
mb_check(mb_pop_value(s, l, &arg));
mb_check(mb_attempt_close_bracket(s, l));
switch(arg.type) {
case MB_DT_STRING:
mb_check(mb_push_int(s, l, (int_t)strlen(arg.value.string)));
break;
case MB_DT_ARRAY:
arr = (_array_t*)arg.value.array;
mb_check(mb_push_int(s, l, (int_t)arr->count));
break;
default:
_handle_error_on_obj(s, SE_RN_NOT_SUPPORTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
break;
}
_exit:
return result;
}
int _std_mid(mb_interpreter_t* s, void** l) {
/* Get a number of characters from a given position of a string */
int result = MB_FUNC_OK;
@ -7194,6 +7187,43 @@ _exit:
return result;
}
int _std_len(mb_interpreter_t* s, void** l) {
/* Get the length of a string or an array */
int result = MB_FUNC_OK;
_ls_node_t* ast = 0;
mb_value_t arg;
_array_t* arr = 0;
mb_assert(s && l);
ast = (_ls_node_t*)(*l);
mb_check(mb_attempt_open_bracket(s, l));
mb_check(mb_pop_value(s, l, &arg));
mb_check(mb_attempt_close_bracket(s, l));
switch(arg.type) {
case MB_DT_STRING:
mb_check(mb_push_int(s, l, (int_t)strlen(arg.value.string)));
break;
case MB_DT_ARRAY:
arr = (_array_t*)arg.value.array;
mb_check(mb_push_int(s, l, (int_t)arr->count));
break;
default:
_handle_error_on_obj(s, SE_RN_NOT_SUPPORTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
break;
}
_exit:
return result;
}
int _std_print(mb_interpreter_t* s, void** l) {
/* PRINT statement */
int result = MB_FUNC_OK;

Binary file not shown.

Binary file not shown.

View File

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

View File

@ -1,27 +1,27 @@
/*
** This source file is part of MY-BASIC
**
** For the latest info, see https://github.com/paladin-t/my_basic/
**
** Copyright (C) 2011 - 2015 Wang Renxin
**
** Permission is hereby granted, free of charge, to any person obtaining a copy of
** this software and associated documentation files (the "Software"), to deal in
** the Software without restriction, including without limitation the rights to
** 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,
** subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** 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
** 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.
*/
** This source file is part of MY-BASIC
**
** For the latest info, see https://github.com/paladin-t/my_basic/
**
** Copyright (C) 2011 - 2015 Wang Renxin
**
** Permission is hereby granted, free of charge, to any person obtaining a copy of
** this software and associated documentation files (the "Software"), to deal in
** the Software without restriction, including without limitation the rights to
** 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,
** subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** 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
** 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.
*/
#ifdef _MSC_VER
# ifndef _CRT_SECURE_NO_WARNINGS
@ -40,6 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef _MSC_VER
# pragma warning(disable : 4127)
@ -59,9 +60,9 @@
#endif /* __POCC__ */
/*
** {========================================================
** Common declarations
*/
** {========================================================
** Common declarations
*/
#ifdef _MSC_VER
# define _BIN_FILE_NAME "my_basic"
@ -85,9 +86,20 @@ static struct mb_interpreter_t* bas = 0;
/* ========================================================} */
/*
** {========================================================
** Memory manipulation
*/
** {========================================================
** Common
*/
#ifndef _printf
# define _printf printf
#endif /* _printf */
/* ========================================================} */
/*
** {========================================================
** Memory manipulation
*/
#ifdef _USE_MEM_POOL
@ -251,9 +263,9 @@ static void _push_mem(char* p) {
/* ========================================================} */
/*
** {========================================================
** Code manipulation
*/
** {========================================================
** Code manipulation
*/
typedef struct _code_line_t {
char** lines;
@ -397,9 +409,9 @@ static int _save_file(const char* path, const char* txt) {
/* ========================================================} */
/*
** {========================================================
** Interactive commands
*/
** {========================================================
** Interactive commands
*/
static void _clear_screen(void) {
#ifdef _MSC_VER
@ -426,18 +438,18 @@ static void _list_program(const char* sn, const char* cn) {
if(lsn == 0 && lcn == 0) {
long i = 0;
for(i = 0; i < c->count; ++i) {
printf("%ld]%s", i + 1, c->lines[i]);
_printf("%ld]%s", i + 1, c->lines[i]);
}
} else {
long i = 0;
long e = 0;
if(lsn < 1 || lsn > c->count) {
printf("Line number %ld out of bound.\n", lsn);
_printf("Line number %ld out of bound.\n", lsn);
return;
}
if(lcn < 0) {
printf("Invalid line count %ld.\n", lcn);
_printf("Invalid line count %ld.\n", lcn);
return;
}
@ -447,7 +459,7 @@ static void _list_program(const char* sn, const char* cn) {
if(i >= c->count)
break;
printf("%ld]%s\n", i + 1, c->lines[i]);
_printf("%ld]%s\n", i + 1, c->lines[i]);
}
}
}
@ -461,13 +473,13 @@ static void _edit_program(const char* no) {
lno = atoi(no);
if(lno < 1 || lno > c->count) {
printf("Line number %ld out of bound.\n", lno);
_printf("Line number %ld out of bound.\n", lno);
return;
}
--lno;
memset(line, 0, _MAX_LINE_LENGTH);
printf("%ld]", lno + 1);
_printf("%ld]", lno + 1);
mb_gets(line, _MAX_LINE_LENGTH);
l = (int)strlen(line);
c->lines[lno] = (char*)realloc(c->lines[lno], l + 2);
@ -485,13 +497,13 @@ static void _insert_program(const char* no) {
lno = atoi(no);
if(lno < 1 || lno > c->count) {
printf("Line number %ld out of bound.\n", lno);
_printf("Line number %ld out of bound.\n", lno);
return;
}
--lno;
memset(line, 0, _MAX_LINE_LENGTH);
printf("%ld]", lno + 1);
_printf("%ld]", lno + 1);
mb_gets(line, _MAX_LINE_LENGTH);
if(c->count + 1 == c->size) {
c->size += _LINE_INC_STEP;
@ -512,7 +524,7 @@ static void _alter_program(const char* no) {
lno = atoi(no);
if(lno < 1 || lno > c->count) {
printf("Line number %ld out of bound.\n", lno);
_printf("Line number %ld out of bound.\n", lno);
return;
}
@ -530,24 +542,24 @@ static void _load_program(const char* path) {
_set_code(c, txt);
free(txt);
if(c->count == 1) {
printf("Load done. %d line loaded.\n", c->count);
_printf("Load done. %d line loaded.\n", c->count);
} else {
printf("Load done. %d lines loaded.\n", c->count);
_printf("Load done. %d lines loaded.\n", c->count);
}
} else {
printf("Cannot load file \"%s\".\n", path);
_printf("Cannot load file \"%s\".\n", path);
}
}
static void _save_program(const char* path) {
char* txt = _get_code(c);
if(!_save_file(path, txt)) {
printf("Cannot save file \"%s\".\n", path);
_printf("Cannot save file \"%s\".\n", path);
} else {
if(c->count == 1) {
printf("Save done. %d line saved.\n", c->count);
_printf("Save done. %d line saved.\n", c->count);
} else {
printf("Save done. %d lines saved.\n", c->count);
_printf("Save done. %d lines saved.\n", c->count);
}
}
free(txt);
@ -555,41 +567,41 @@ static void _save_program(const char* path) {
static void _kill_program(const char* path) {
if(!unlink(path)) {
printf("Delete file \"%s\" successfully.\n", path);
_printf("Delete file \"%s\" successfully.\n", path);
} else {
printf("Delete file \"%s\" failed.\n", path);
_printf("Delete file \"%s\" failed.\n", path);
}
}
static void _show_tip(void) {
printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string());
printf("Copyright (C) 2011 - 2015 Wang 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");
_printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string());
_printf("Copyright (C) 2011 - 2015 Wang 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_help(void) {
printf("Parameters:\n");
printf(" %s - Start interactive mode without arguments.\n", _BIN_FILE_NAME);
printf(" %s *.* - Load and run a file.\n", _BIN_FILE_NAME);
printf(" %s -e \"expr\" - Evaluate an expression directly.\n", _BIN_FILE_NAME);
printf("Interactive commands:\n");
printf(" CLS - Clear screen\n");
printf(" NEW - Clear current program\n");
printf(" RUN - Run current program\n");
printf(" BYE - Quit interpreter\n");
printf(" LIST - List current program\n");
printf(" Usage: LIST [l [n]], l is start line number, n is line count\n");
printf(" EDIT - Edit (modify/insert/remove) a line in current program\n");
printf(" Usage: EDIT n, n is line number\n");
printf(" EDIT -I n, insert a line before a given line, n is line number\n");
printf(" EDIT -R n, remove a line, n is line number\n");
printf(" LOAD - Load a file as current program\n");
printf(" Usage: LOAD *.*\n");
printf(" SAVE - Save current program to a file\n");
printf(" Usage: SAVE *.*\n");
printf(" KILL - Delete a file\n");
printf(" Usage: KILL *.*\n");
_printf("Parameters:\n");
_printf(" %s - Start interactive mode without arguments.\n", _BIN_FILE_NAME);
_printf(" %s *.* - Load and run a file.\n", _BIN_FILE_NAME);
_printf(" %s -e \"expr\" - Evaluate an expression directly.\n", _BIN_FILE_NAME);
_printf("Interactive commands:\n");
_printf(" CLS - Clear screen\n");
_printf(" NEW - Clear current program\n");
_printf(" RUN - Run current program\n");
_printf(" BYE - Quit interpreter\n");
_printf(" LIST - List current program\n");
_printf(" Usage: LIST [l [n]], l is start line number, n is line count\n");
_printf(" EDIT - Edit (modify/insert/remove) a line in current program\n");
_printf(" Usage: EDIT n, n is line number\n");
_printf(" EDIT -I n, insert a line before a given line, n is line number\n");
_printf(" EDIT -R n, remove a line, n is line number\n");
_printf(" LOAD - Load a file as current program\n");
_printf(" Usage: LOAD *.*\n");
_printf(" SAVE - Save current program to a file\n");
_printf(" Usage: SAVE *.*\n");
_printf(" KILL - Delete a file\n");
_printf(" Usage: KILL *.*\n");
}
static int _do_line(void) {
@ -600,7 +612,7 @@ static int _do_line(void) {
mb_assert(bas);
memset(line, 0, _MAX_LINE_LENGTH);
printf("]");
_printf("]");
mb_gets(line, _MAX_LINE_LENGTH);
memcpy(dup, line, _MAX_LINE_LENGTH);
@ -621,7 +633,7 @@ static int _do_line(void) {
for(i = 0; i < c->count; ++i)
mb_load_string(bas, c->lines[i]);
result = mb_run(bas);
printf("\n");
_printf("\n");
} else if(_str_eq(line, "BYE")) {
result = MB_FUNC_BYE;
} else if(_str_eq(line, "LIST")) {
@ -660,23 +672,23 @@ static int _do_line(void) {
/* ========================================================} */
/*
** {========================================================
** Parameter processing
*/
** {========================================================
** Parameter processing
*/
#define _CHECK_ARG(__c, __i, __e) \
do { \
if(__c <= __i + 1) { \
printf(__e); \
return; \
} \
} while(0)
do { \
if(__c <= __i + 1) { \
_printf(__e); \
return; \
} \
} while(0)
static void _run_file(char* path) {
if(mb_load_file(bas, path) == MB_FUNC_OK) {
mb_run(bas);
} else {
printf("Invalid file or error code.\n");
_printf("Invalid file or error code.\n");
}
}
@ -690,7 +702,7 @@ static void _evaluate_expression(char* p) {
const char* const print = "PRINT ";
if(!p) {
printf("Invalid expression.\n");
_printf("Invalid expression.\n");
return;
}
@ -713,7 +725,7 @@ static void _evaluate_expression(char* p) {
if(mb_load_string(bas, p) == MB_FUNC_OK) {
mb_run(bas);
} else {
printf("Invalid expression.\n");
_printf("Invalid expression.\n");
}
if(a) {
free(e);
@ -732,7 +744,7 @@ static void _process_parameters(int argc, char* argv[]) {
_CHECK_ARG(argc, i, "-e: Expression expected.\n");
p = argv[++i];
} else {
printf("Unknown argument: %s.\n", argv[i]);
_printf("Unknown argument: %s.\n", argv[i]);
}
} else {
p = argv[i];
@ -742,21 +754,21 @@ static void _process_parameters(int argc, char* argv[]) {
}
switch(m) {
case '\0':
_run_file(p);
break;
case 'e':
_evaluate_expression(p);
break;
case '\0':
_run_file(p);
break;
case 'e':
_evaluate_expression(p);
break;
}
}
/* ========================================================} */
/*
** {========================================================
** Scripting interfaces
*/
** {========================================================
** Scripting interfaces
*/
static int beep(struct mb_interpreter_t* s, void** l) {
int result = MB_FUNC_OK;
@ -774,9 +786,9 @@ static int beep(struct mb_interpreter_t* s, void** l) {
/* ========================================================} */
/*
** {========================================================
** Callbacks and handlers
*/
** {========================================================
** Callbacks and handlers
*/
static void _on_stepped(struct mb_interpreter_t* s, int p, unsigned short row, unsigned short col) {
mb_unrefvar(s);
@ -790,16 +802,16 @@ static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, char* f
mb_unrefvar(f);
mb_unrefvar(p);
if(SE_NO_ERR != e) {
printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d.\n", row, col, e, m, abort_code);
_printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d.\n", row, col, e, m, abort_code);
}
}
/* ========================================================} */
/*
** {========================================================
** Initialization and disposing
*/
** {========================================================
** Initialization and disposing
*/
static void _on_startup(void) {
#ifdef _USE_MEM_POOL
@ -839,9 +851,9 @@ static void _on_exit(void) {
/* ========================================================} */
/*
** {========================================================
** Entry
*/
** {========================================================
** Entry
*/
int main(int argc, char* argv[]) {
int status = 0;
@ -862,10 +874,10 @@ int main(int argc, char* argv[]) {
} else if(argc >= 2) {
_process_parameters(argc, argv);
} else {
printf("Unknown arguments.\n");
_printf("Unknown arguments.\n");
_show_tip();
}
return 0;
}