diff --git a/HISTORY b/HISTORY index 4041269..e826af0 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,7 @@ +Feb. 3 2017 +Added a replacement real number formatting function +Added a replacement function of strtod on the wiki page, thanks to Paul Johnson for providing the code + Jan. 19 2017 Fixed a crash bug with unmatched ENDIF statement, thanks to yukini3 for pointing it out diff --git a/README.md b/README.md index e3d2ad2..bd0c502 100755 --- a/README.md +++ b/README.md @@ -174,6 +174,7 @@ The [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf) includes most o * [Customize a memory allocator](https://github.com/paladin-t/my_basic/wiki/Customize-a-memory-allocator) * [Redirect PRINT and INPUT](https://github.com/paladin-t/my_basic/wiki/Redirect-PRINT-and-INPUT) * [Redefine int_t and real_t](https://github.com/paladin-t/my_basic/wiki/Redefine-int_t-and-real_t) + * [Convert between string and real](https://github.com/paladin-t/my_basic/wiki/Convert-between-string-and-real) * [Customize an importer](https://github.com/paladin-t/my_basic/wiki/Customize-an-importer) * [More scripting APIs](https://github.com/paladin-t/my_basic/wiki/More-scripting-APIs) * [String matching module](https://github.com/paladin-t/my_basic/wiki/String-matching-module) diff --git a/core/my_basic.c b/core/my_basic.c index 45aa9c4..1875609 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -35,6 +35,9 @@ # ifndef MB_DISABLE_LOAD_FILE # define MB_DISABLE_LOAD_FILE # endif /* MB_DISABLE_LOAD_FILE */ +# ifndef MB_MANUAL_REAL_FORMATTING +# define MB_MANUAL_REAL_FORMATTING +# endif /* MB_MANUAL_REAL_FORMATTING */ #endif /* ARDUINO && !MB_CP_ARDUINO */ #ifdef MB_CP_VC # include @@ -1427,6 +1430,9 @@ static bool_t _try_get_value(_object_t* obj, mb_value_u* val, _data_e expected); static bool_t _is_number(void* obj); static bool_t _is_string(void* obj); static char* _extract_string(_object_t* obj); +#ifdef MB_MANUAL_REAL_FORMATTING +static void _real_to_str(real_t r, char* str, size_t size, size_t afterpoint); +#endif /* MB_MANUAL_REAL_FORMATTING */ #ifdef MB_ENABLE_COLLECTION_LIB # define _IS_LIST(__o) ((__o) && ((_object_t*)(__o))->type == _DT_LIST) @@ -5841,6 +5847,40 @@ static char* _extract_string(_object_t* obj) { return result; } +#ifdef MB_MANUAL_REAL_FORMATTING +/* Convert a real number to string */ +static void _real_to_str(real_t r, char* str, size_t size, size_t afterpoint) { + size_t pos = 0; + size_t len = 0; + char curr[4]; + int val = (int)r; + char dot = 0; + + itoa(val, str, 10); + if(r < 0) { + r *= -1; + val *= -1; + } + pos = len = strlen(str); + while(pos < size - 1) { + r = r - (real_t)val; + if(r == 0.0) + break; + if(!dot) { + dot = 1; + str[pos++] = '.'; + } + r *= 10; + val = (int)r; + itoa(val, curr, 10); + str[pos++] = *curr; + if(--afterpoint == 0) + break; + } + str[pos] = '\0'; +} +#endif /* MB_MANUAL_REAL_FORMATTING */ + #ifdef _HAS_REF_OBJ_LOCK /* Lock a referenced object */ static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { @@ -15765,9 +15805,13 @@ static int _std_str(mb_interpreter_t* s, void** l) { case MB_DT_REAL: lbuf = 1 /* - */ + (DBL_MAX_10_EXP + 1) /* 308 + 1 digits */ + 1 /* . */ + 6 /* precision */ + 1 /* \0 */; _RESIZE_CHAR_BUF(buf, lbuf); +#ifdef MB_MANUAL_REAL_FORMATTING + _real_to_str(arg.value.float_point, _CHAR_BUF_PTR(buf), lbuf, 5); +#else /* MB_MANUAL_REAL_FORMATTING */ if((size_t)sprintf(_CHAR_BUF_PTR(buf), MB_REAL_FMT, arg.value.float_point) >= lbuf) { mb_assert(0 && "Buffer overflow."); } +#endif /* MB_MANUAL_REAL_FORMATTING */ break; #ifdef MB_ENABLE_CLASS @@ -16216,7 +16260,17 @@ _print: } else if(val_ptr->type == _DT_INT) { _get_printer(s)(MB_INT_FMT, val_ptr->data.integer); } else if(val_ptr->type == _DT_REAL) { +#ifdef MB_MANUAL_REAL_FORMATTING + _dynamic_buffer_t buf; + size_t lbuf = 32; + _INIT_BUF(buf); + _RESIZE_CHAR_BUF(buf, lbuf); + _real_to_str(val_ptr->data.float_point, _CHAR_BUF_PTR(buf), lbuf, 5); + _get_printer(s)("%s", _CHAR_BUF_PTR(buf)); + _DISPOSE_BUF(buf); +#else /* MB_MANUAL_REAL_FORMATTING */ _get_printer(s)(MB_REAL_FMT, val_ptr->data.float_point); +#endif /* MB_MANUAL_REAL_FORMATTING */ } else if(val_ptr->type == _DT_STRING) { _print_string(s, val_ptr); if(!val_ptr->ref && val_ptr->data.string && !pathed_str) { diff --git a/output/my_basic.exe b/output/my_basic.exe index f10dea5..410d7c6 100755 Binary files a/output/my_basic.exe and b/output/my_basic.exe differ