From a91b156de34bd38c6a1c907a4001c955b6495a5f Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sat, 13 Jan 2018 06:44:50 +1000 Subject: [PATCH 01/10] COMMON: bump version --- configure.ac | 4 ++-- debian/changelog | 5 +++++ ide/android/AndroidManifest.xml | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 387f49ee..431ec7d6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,13 +1,13 @@ dnl dnl Configure script for SmallBASIC dnl -dnl Copyright(C) 2001-2016 Chris Warren-Smith. +dnl Copyright(C) 2001-2018 Chris Warren-Smith. dnl dnl This program is distributed under the terms of the GPL v2.0 dnl Download the GNU Public License (GPL) from www.gnu.org dnl -AC_INIT([smallbasic], [0.12.11]) +AC_INIT([smallbasic], [0.12.12]) AC_CONFIG_SRCDIR([configure.ac]) AC_CANONICAL_TARGET diff --git a/debian/changelog b/debian/changelog index 87eba931..ed312fd7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,8 @@ +smallbasic (0.12.12) unstable; urgency=low + * Various see web site + + -- Chris Warren-Smith Sat, 13 Jan 2018 09:45:25 +1000 + smallbasic (0.12.11) unstable; urgency=low * Various see web site diff --git a/ide/android/AndroidManifest.xml b/ide/android/AndroidManifest.xml index 6705af7a..8113f9e6 100644 --- a/ide/android/AndroidManifest.xml +++ b/ide/android/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="27" + android:versionName="0.12.12"> From 2368d8792f0accebcef51d0b49a79535175d1b70 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sat, 13 Jan 2018 09:50:27 +1000 Subject: [PATCH 02/10] COMMON: fix crash on osx --- ChangeLog | 3 +++ src/common/blib.c | 4 ++-- src/common/blib_db.c | 2 +- src/common/fmt.c | 11 ++++++----- src/common/fmt.h | 4 ++-- src/common/pproc.h | 6 +++--- src/common/proc.c | 35 ++++++++++++++++++----------------- src/common/var_map.c | 2 +- src/common/var_map.h | 2 +- src/platform/console/main.c | 4 ++-- 10 files changed, 39 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 892934af..2be1aef8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2018-01-13 (0.12.12) + Fix osx crash + 2017-11-28 (0.12.11) Fix img.save(dat) to build correct indexes Fix ESCm implementation bug diff --git a/src/common/blib.c b/src/common/blib.c index 2c9e2426..5ad33de4 100644 --- a/src/common/blib.c +++ b/src/common/blib.c @@ -513,7 +513,7 @@ void cmd_print(int output) { byte last_op = 0; byte exitf = 0; byte use_format = 0; - int handle = 0; + intptr_t handle = 0; var_t var; // prefix - # (file) @@ -654,7 +654,7 @@ void cmd_input(int input) { byte print_crlf = 1; var_t prompt; var_t *vuser_p = NULL; - int handle = 0; + intptr_t handle = 0; char *inps = NULL; v_init(&prompt); diff --git a/src/common/blib_db.c b/src/common/blib_db.c index 5d9b1e98..449c8a9b 100644 --- a/src/common/blib_db.c +++ b/src/common/blib_db.c @@ -672,7 +672,7 @@ void cmd_floadln() { void cmd_fsaveln() { var_t file_name, *array_p = NULL, *var_p = NULL; int flags = DEV_FILE_OUTPUT; - int handle; + intptr_t handle; if (code_peek() == kwTYPE_SEP) { // "filename" is an already open file number diff --git a/src/common/fmt.c b/src/common/fmt.c index 0c10982e..8a2a81b5 100644 --- a/src/common/fmt.c +++ b/src/common/fmt.c @@ -41,7 +41,7 @@ int fmt_cdig(char *fmt); char *fmt_getnumfmt(char *dest, char *source); char *fmt_getstrfmt(char *dest, char *source); void fmt_addfmt(const char *fmt, int type); -void fmt_printL(int output, int handle); +void fmt_printL(int output, intptr_t handle); typedef struct { char *fmt; // the format or a string @@ -787,7 +787,7 @@ void build_format(const char *fmt_cnst) { /* * print simple strings (parts of format) */ -void fmt_printL(int output, int handle) { +void fmt_printL(int output, intptr_t handle) { if (fmt_count == 0) { return; } else { @@ -808,15 +808,16 @@ void fmt_printL(int output, int handle) { /* * print formated number */ -void fmt_printN(var_num_t x, int output, int handle) { +void fmt_printN(var_num_t x, int output, intptr_t handle) { if (fmt_count == 0) { rt_raise(ERR_FORMAT_INVALID_FORMAT); } else { fmt_printL(output, handle); fmt_node_t *node = &fmt_stack[fmt_cur]; fmt_cur++; - if (fmt_cur >= fmt_count) + if (fmt_cur >= fmt_count) { fmt_cur = 0; + } if (node->type == 1) { char *buf = format_num(node->fmt, x); pv_write(buf, output, handle); @@ -833,7 +834,7 @@ void fmt_printN(var_num_t x, int output, int handle) { /* * print formated string */ -void fmt_printS(const char *str, int output, int handle) { +void fmt_printS(const char *str, int output, intptr_t handle) { if (fmt_count == 0) { rt_raise(ERR_FORMAT_INVALID_FORMAT); } else { diff --git a/src/common/fmt.h b/src/common/fmt.h index c6914b95..6e701f80 100644 --- a/src/common/fmt.h +++ b/src/common/fmt.h @@ -118,7 +118,7 @@ void free_format(void); * @param output is the output-set-of-routines code (see PV_xxx macros) * @param handle is the output handle (depented on output-code) */ -void fmt_printN(var_num_t x, int output, int handle); +void fmt_printN(var_num_t x, int output, intptr_t handle); /** * @ingroup str @@ -131,7 +131,7 @@ void fmt_printN(var_num_t x, int output, int handle); * @param output is the output-set-of-routines code (see PV_xxx macros) * @param handle is the output handle (depented on output-code) */ -void fmt_printS(const char *str, int output, int handle); +void fmt_printS(const char *str, int output, intptr_t handle); #if defined(__cplusplus) } diff --git a/src/common/pproc.h b/src/common/pproc.h index a9a8bfee..a0e6e492 100644 --- a/src/common/pproc.h +++ b/src/common/pproc.h @@ -79,7 +79,7 @@ void set_dataip(uint16_t label_id); * * @note avoid to use it */ -void pv_write(char *str, int method, int handle); +void pv_write(char *str, int method, intptr_t handle); /** * @ingroup exec @@ -88,7 +88,7 @@ void pv_write(char *str, int method, int handle); * * @note avoid to use it */ -void pv_writevar(var_t *var, int method, int handle); +void pv_writevar(var_t *var, int method, intptr_t handle); /** * @ingroup exec @@ -107,7 +107,7 @@ void print_var(var_t *var); * @param var is the variable * @param handle is the file-handle */ -void fprint_var(int handle, var_t *var); +void fprint_var(intptr_t handle, var_t *var); /** * @ingroup exec diff --git a/src/common/proc.c b/src/common/proc.c index 8bf51207..e970e193 100644 --- a/src/common/proc.c +++ b/src/common/proc.c @@ -163,33 +163,34 @@ void exec_usefunc2(var_t *var1, var_t *var2, bcip_t ip) { v_detach(old_y); } +void pv_write_str(char *str, var_t *vp) { + vp->v.p.length += strlen(str); + if (vp->v.p.ptr == NULL) { + vp->v.p.ptr = malloc(vp->v.p.length + 1); + vp->v.p.owner = 1; + strcpy((char *)vp->v.p.ptr, str); + } else { + vp->v.p.ptr = realloc(vp->v.p.ptr, vp->v.p.length + 1); + strcat((char *)vp->v.p.ptr, str); + } +} + /* * Write string to output device */ -void pv_write(char *str, int method, int handle) { - var_t *vp; - +void pv_write(char *str, int method, intptr_t handle) { switch (method) { case PV_FILE: - dev_fwrite(handle, (byte *)str, strlen(str)); + dev_fwrite((int)handle, (byte *)str, strlen(str)); break; case PV_LOG: lwrite(str); break; case PV_STRING: - vp = (var_t*)(intptr_t)handle; - vp->v.p.length += strlen(str); - if (vp->v.p.ptr == NULL) { - vp->v.p.ptr = malloc(vp->v.p.length + 1); - vp->v.p.owner = 1; - strcpy((char *)vp->v.p.ptr, str); - } else { - vp->v.p.ptr = realloc(vp->v.p.ptr, vp->v.p.length + 1); - strcat((char *)vp->v.p.ptr, str); - } + pv_write_str(str, (var_t *)handle); break; case PV_NET: - net_print((socket_t) handle, (const char *)str); + net_print((socket_t)handle, (const char *)str); break; default: dev_print(str); @@ -199,7 +200,7 @@ void pv_write(char *str, int method, int handle) { /* * just prints the value of variable 'var' */ -void pv_writevar(var_t *var, int method, int handle) { +void pv_writevar(var_t *var, int method, intptr_t handle) { char tmpsb[64]; // start with a clean buffer @@ -244,7 +245,7 @@ void print_var(var_t *v) { /* * write a variable to a file */ -void fprint_var(int handle, var_t *v) { +void fprint_var(intptr_t handle, var_t *v) { pv_writevar(v, PV_FILE, handle); } diff --git a/src/common/var_map.c b/src/common/var_map.c index a5372fed..ea7e48d5 100644 --- a/src/common/var_map.c +++ b/src/common/var_map.c @@ -404,7 +404,7 @@ char *map_to_str(const var_p_t var_p) { /** * Print the contents of the structure */ -void map_write(const var_p_t var_p, int method, int handle) { +void map_write(const var_p_t var_p, int method, intptr_t handle) { if (var_p->type == V_MAP || var_p->type == V_ARRAY) { char *buffer = map_to_str(var_p); pv_write(buffer, method, handle); diff --git a/src/common/var_map.h b/src/common/var_map.h index 7a14103f..18aea29e 100644 --- a/src/common/var_map.h +++ b/src/common/var_map.h @@ -35,7 +35,7 @@ void map_get_value(var_p_t base, var_p_t key, var_p_t *result); void map_set(var_p_t dest, const var_p_t src); void map_set_int(var_p_t base, const char *name, var_int_t n); char *map_to_str(const var_p_t var_p); -void map_write(const var_p_t var_p, int method, int handle); +void map_write(const var_p_t var_p, int method, intptr_t handle); void map_parse_str(const char *js, size_t len, var_p_t dest); void map_from_str(var_p_t var_p); void map_from_codearray(var_p_t var_p); diff --git a/src/platform/console/main.c b/src/platform/console/main.c index 2f078f0b..8efd4598 100644 --- a/src/platform/console/main.c +++ b/src/platform/console/main.c @@ -253,10 +253,10 @@ int process_options(int argc, char *argv[]) { return 1; } -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__MACH__) // for analysing excessive malloc calls using kdbg extern void *__libc_malloc(size_t size); -void* malloc (size_t size) { +void *malloc(size_t size) { return __libc_malloc(size); } #endif From 98bc41a42b3def1508a61f83e2787be11f7a47be Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Thu, 18 Jan 2018 19:42:46 +1000 Subject: [PATCH 03/10] SDL: update font handling on osx --- src/platform/sdl/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/platform/sdl/main.cpp b/src/platform/sdl/main.cpp index d1fbe5f9..5fc78fc6 100644 --- a/src/platform/sdl/main.cpp +++ b/src/platform/sdl/main.cpp @@ -106,6 +106,26 @@ bool getFontFiles(const char *familyName, String &fontFile, String &fontFileBold } return true; } +#elif defined(__MACH__) +bool getFontFiles(const char *familyName, String &fontFile, String &fontFileBold) { + fontFile = "Envy Code R.ttf"; + fontFileBold = "Envy Code R Bold.ttf"; + if (access(fontFile.c_str(), 0) != 0) { + fontFile = "SourceCodePro-Regular.ttf"; + fontFileBold = "SourceCodePro-Bold.ttf"; + } + if ((familyName != NULL && strcasecmp(familyName, "andale") == 0) + || access(fontFile.c_str(), 0) != 0) { + fontFile = "/Library/Fonts/Andale Mono.ttf"; + fontFileBold = "/Library/Fonts/Andale Mono.ttf"; + } + if ((familyName != NULL && strcasecmp(familyName, "courier") == 0) + || access(fontFile.c_str(), 0) != 0) { + fontFile = "/Library/Fonts/Courier New.ttf"; + fontFileBold = "/Library/Fonts/Courier New Bold.ttf"; + } + return true; +} #else bool getFont(FcFontSet *fs, const char *familyName, int fontWeight, String &name) { bool result = false; From a524ae53c942dcb8ec0c89a99958ca4390e5ab87 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sun, 21 Jan 2018 15:23:26 +1000 Subject: [PATCH 04/10] COMMON: cleanup array handling --- src/common/blib.c | 180 +++++++++++++++++++++------------------- src/common/blib_db.c | 24 +++--- src/common/blib_func.c | 12 +-- src/common/blib_graph.c | 10 +-- src/common/brun.c | 4 +- src/common/eval.c | 16 ++-- src/common/proc.c | 28 +++---- src/common/var.c | 99 +++++++++++----------- src/common/var.h | 55 +++++++++--- src/common/var_eval.c | 12 +-- src/common/var_map.c | 14 ++-- src/ui/form.cpp | 6 +- src/ui/image.cpp | 20 ++--- src/ui/inputs.cpp | 4 +- 14 files changed, 266 insertions(+), 218 deletions(-) diff --git a/src/common/blib.c b/src/common/blib.c index 5ad33de4..8ed1edf1 100644 --- a/src/common/blib.c +++ b/src/common/blib.c @@ -121,6 +121,62 @@ void cmd_packed_let() { } } +unsigned get_dimensions(int32_t **lbound, int32_t **ubound) { + unsigned count = 0; + if (code_peek() == kwTYPE_LEVEL_BEGIN) { + code_skipnext(); + while (code_peek() != kwTYPE_LEVEL_END && !prog_error) { + if (count == MAXDIM) { + err_matdim(); + break; + } + var_t arg; + v_init(&arg); + eval(&arg); + if (prog_error) { + break; + } + int dim = v_getint(&arg); + v_free(&arg); + + if (count) { + // allocate for extra dimension + *lbound = (int32_t *)realloc(*lbound, (sizeof(int32_t) * (count + 1))); + *ubound = (int32_t *)realloc(*ubound, (sizeof(int32_t) * (count + 1))); + } else { + // allocate for first dimension + *lbound = (int32_t *)malloc(sizeof(int32_t)); + *ubound = (int32_t *)malloc(sizeof(int32_t)); + } + + if (code_peek() == kwTO) { + (*lbound)[count] = dim; + code_skipnext(); + eval(&arg); + (*ubound)[count] = v_getint(&arg); + v_free(&arg); + } else { + (*lbound)[count] = opt_base; + (*ubound)[count] = dim; + } + + count++; + + // skip separator + if (code_peek() == kwTYPE_SEP) { + code_skipnext(); + if (code_getnext() != ',') { + err_missing_comma(); + break; + } + } + } + // skip end separator + code_skipnext(); + } + return count; +} + /** * DIM var([lower TO] uppper [, ...]) */ @@ -131,95 +187,51 @@ void cmd_dim(int preserve) { byte code = code_peek(); if (code == kwTYPE_LINE || code == kwTYPE_EOC) { exitf = 1; - } else { - var_t array; - array.v.a.maxdim = 0; - if (code_peek() == kwTYPE_SEP) { - code_skipnext(); - if (code_getnext() != ',') { - err_missing_comma(); - } + break; + } + if (code_peek() == kwTYPE_SEP) { + code_skipnext(); + if (code_getnext() != ',') { + err_missing_comma(); + return; } + } - var_t *var_p = code_getvarptr_parens(1); - byte zero_length = 1; + var_t *var_p = code_getvarptr_parens(1); + if (prog_error) { + break; + } - if (!prog_error) { - if (code_peek() == kwTYPE_LEVEL_BEGIN) { - code_skipnext(); - while (code_peek() != kwTYPE_LEVEL_END) { - zero_length = 0; - var_t arg; - v_init(&arg); - eval(&arg); - if (prog_error) { - return; - } - if (code_peek() == kwTO) { - array.v.a.lbound[array.v.a.maxdim] = v_getint(&arg); - code_skipnext(); - eval(&arg); - if (prog_error) { - return; - } - array.v.a.ubound[array.v.a.maxdim] = v_getint(&arg); - } else { - array.v.a.lbound[array.v.a.maxdim] = opt_base; - array.v.a.ubound[array.v.a.maxdim] = v_getint(&arg); - } - v_free(&arg); - array.v.a.maxdim++; - - // skip separator - if (code_peek() == kwTYPE_SEP) { - code_skipnext(); - if (code_getnext() != ',') { - err_missing_comma(); - } - } - } - // skip end separator - code_skipnext(); - } else { - zero_length = 1; - } + int32_t *lbound = NULL; + int32_t *ubound = NULL; + unsigned dimensions = get_dimensions(&lbound, &ubound); + if (!prog_error) { + if (!dimensions) { + v_toarray1(var_p, 0); } else { - rt_raise(ERR_SYNTAX); - } - - // - // run... - // - if (!prog_error) { - if (zero_length) { - v_toarray1(var_p, 0); + int size = 1; + for (int i = 0; i < dimensions; i++) { + size = size * (ABS(ubound[i] - lbound[i]) + 1); + } + if (!preserve) { + v_new_array(var_p, size); } else { - int i; - int size = 1; - for (i = 0; i < array.v.a.maxdim; i++) { - size = size * (ABS(array.v.a.ubound[i] - array.v.a.lbound[i]) + 1); - } - if (!preserve) { - v_toarray1(var_p, size); + if (var_p->type == V_ARRAY) { + v_resize_array(var_p, size); } else { - if (var_p->type == V_ARRAY) { - v_resize_array(var_p, size); - } else { - v_toarray1(var_p, size); - } - } - - // dim - var_p->v.a.maxdim = array.v.a.maxdim; - for (i = 0; i < array.v.a.maxdim; i++) { - var_p->v.a.lbound[i] = array.v.a.lbound[i]; - var_p->v.a.ubound[i] = array.v.a.ubound[i]; + v_new_array(var_p, size); } } - } else { - exitf = 1; + // dim + v_maxdim(var_p) = dimensions; + for (int i = 0; i < dimensions; i++) { + v_lbound(var_p, i) = lbound[i]; + v_ubound(var_p, i) = ubound[i]; + } } } + free(lbound); + free(ubound); } while (!exitf && !prog_error); } @@ -328,7 +340,7 @@ void cmd_lins() { if (prog_error) { return; } - idx -= var_p->v.a.lbound[0]; + idx -= v_lbound(var_p, 0); par_getcomma(); if (prog_error) { @@ -412,7 +424,7 @@ void cmd_ldel() { if (prog_error) { return; } - idx -= var_p->v.a.lbound[0]; + idx -= v_lbound(var_p, 0); if ((idx >= size) || (idx < 0)) { err_out_of_range(); return; @@ -2520,7 +2532,7 @@ void cmd_sort() { if (!errf) { if (v_asize(var_p) > 1) { static_qsort_last_use_ip = use_ip; - qsort(var_p->v.a.data, v_asize(var_p), sizeof(var_t), qs_cmp); + qsort(v_data(var_p), v_asize(var_p), sizeof(var_t), qs_cmp); } } // NO RTE anymore... there is no meaning on this because of empty @@ -2585,12 +2597,12 @@ void cmd_search() { } // search if (!errf) { - rv_p->v.i = var_p->v.a.lbound[0] - 1; + rv_p->v.i = v_lbound(var_p, 0) - 1; for (int i = 0; i < v_asize(var_p); i++) { var_t *elem_p = v_elem(var_p, i); int bcmp = sb_qcmp(elem_p, &vkey, use_ip); if (bcmp == 0) { - rv_p->v.i = i + var_p->v.a.lbound[0]; + rv_p->v.i = i + v_lbound(var_p, 0); break; } } diff --git a/src/common/blib_db.c b/src/common/blib_db.c index 449c8a9b..0c0cb81d 100644 --- a/src/common/blib_db.c +++ b/src/common/blib_db.c @@ -149,18 +149,18 @@ void write_encoded_var(int handle, var_t *var) { dev_fwrite(handle, (byte *)var->v.p.ptr, fv.size); break; case V_ARRAY: - fv.size = var->v.a.size; + fv.size = v_asize(var); dev_fwrite(handle, (byte *)&fv, sizeof(struct file_encoded_var)); // write additional data about array - dev_fwrite(handle, &var->v.a.maxdim, 1); - for (int i = 0; i < var->v.a.maxdim; i++) { - dev_fwrite(handle, (byte *)&var->v.a.lbound[i], sizeof(int)); - dev_fwrite(handle, (byte *)&var->v.a.ubound[i], sizeof(int)); + dev_fwrite(handle, &v_maxdim(var), 1); + for (int i = 0; i < v_maxdim(var); i++) { + dev_fwrite(handle, (byte *)&v_lbound(var, i), sizeof(int)); + dev_fwrite(handle, (byte *)&v_ubound(var, i), sizeof(int)); } // write elements - for (int i = 0; i < var->v.a.size; i++) { + for (int i = 0; i < v_asize(var); i++) { var_t *elem = v_elem(var, i); write_encoded_var(handle, elem); } @@ -200,14 +200,14 @@ int read_encoded_var(int handle, var_t *var) { v_new_array(var, fv.size); // read additional data about array - dev_fread(handle, (byte *)&var->v.a.maxdim, 1); - for (int i = 0; i < var->v.a.maxdim; i++) { - dev_fread(handle, (byte *)&var->v.a.lbound[i], sizeof(int)); - dev_fread(handle, (byte *)&var->v.a.ubound[i], sizeof(int)); + dev_fread(handle, (byte *)&v_maxdim(var), 1); + for (int i = 0; i < v_maxdim(var); i++) { + dev_fread(handle, (byte *)&v_lbound(var, i), sizeof(int)); + dev_fread(handle, (byte *)&v_ubound(var, i), sizeof(int)); } // write elements - for (int i = 0; i < var->v.a.size; i++) { + for (int i = 0; i < v_asize(var); i++) { var_t *elem = v_elem(var, i); v_init(elem); read_encoded_var(handle, elem); @@ -711,7 +711,7 @@ void cmd_fsaveln() { if (var_p->type == V_ARRAY) { // parameter is an array - for (int i = 0; i < array_p->v.a.size; i++) { + for (int i = 0; i < v_asize(array_p); i++) { var_p = v_elem(array_p, i); fprint_var(handle, var_p); dev_fwrite(handle, (byte *)"\n", 1); diff --git a/src/common/blib_func.c b/src/common/blib_func.c index 3c155b06..4664f640 100644 --- a/src/common/blib_func.c +++ b/src/common/blib_func.c @@ -1873,10 +1873,10 @@ void cmd_intN(long funcCode, var_t *r) { if (!prog_error) { l--; - if (l >= 0 && l < var_p->v.a.maxdim) { - r->v.i = var_p->v.a.lbound[l]; + if (l >= 0 && l < v_maxdim(var_p)) { + r->v.i = v_lbound(var_p, l); } else { - rt_raise(ERR_BOUND_DIM, var_p->v.a.maxdim, l); + rt_raise(ERR_BOUND_DIM, v_maxdim(var_p), l); } } } else { @@ -1909,10 +1909,10 @@ void cmd_intN(long funcCode, var_t *r) { if (!prog_error) { l--; - if (l >= 0 && l < var_p->v.a.maxdim) { - r->v.i = var_p->v.a.ubound[l]; + if (l >= 0 && l < v_maxdim(var_p)) { + r->v.i = v_ubound(var_p, l); } else { - rt_raise(ERR_BOUND_DIM, var_p->v.a.maxdim); + rt_raise(ERR_BOUND_DIM, v_maxdim(var_p)); } } } else { diff --git a/src/common/blib_graph.c b/src/common/blib_graph.c index f81f46c5..e50fece1 100644 --- a/src/common/blib_graph.c +++ b/src/common/blib_graph.c @@ -1194,7 +1194,7 @@ void cmd_chart() { var_p = par_getvarray(); if (prog_error) return; - count = var_p->v.a.size; + count = v_asize(var_p); // optional labels-flag if (code_peek() == kwTYPE_SEP) { @@ -1274,7 +1274,7 @@ var_t *par_getm3() { if (prog_error) { return NULL; } - if (vp == NULL || vp->type != V_ARRAY || vp->v.a.size != 9) { + if (vp == NULL || vp->type != V_ARRAY || v_asize(vp) != 9) { err_typemismatch(); return NULL; } @@ -1486,7 +1486,7 @@ void cmd_m3apply() { p = par_getvarray(); if (prog_error) return; - count = p->v.a.size; + count = v_asize(p); // copy m to om for (i = 0; i < 3; i++) { @@ -1501,7 +1501,7 @@ void cmd_m3apply() { if (e->type != V_ARRAY) { int o; - count = (p->v.a.size >> 1); + count = (v_asize(p) >> 1); for (i = 0; i < count; i++) { o = i << 1; x = v_getreal(v_elem(p, o)); @@ -1515,7 +1515,7 @@ void cmd_m3apply() { if (e->type != V_ARRAY) err_parsepoly(i, 10); - else if ((e->v.a.size % 2) != 0) + else if ((v_asize(e) % 2) != 0) err_parsepoly(i, 11); if (prog_error) diff --git a/src/common/brun.c b/src/common/brun.c index 4c0cbaa1..c8f1d29c 100644 --- a/src/common/brun.c +++ b/src/common/brun.c @@ -366,9 +366,9 @@ void cmd_chain(void) { code = strdup(var.v.p.ptr); } } else if (var.type == V_ARRAY) { - int el; int len = 0; - for (el = 0; el < var.v.a.size; el++) { + uint32_t size = v_asize(&var); + for (int el = 0; el < size; el++) { var_t *el_p = v_elem(&var, el); if (el_p->type == V_STR) { int str_len = strlen(el_p->v.p.ptr) + 2; diff --git a/src/common/eval.c b/src/common/eval.c index 3dab1f09..1daf8cab 100644 --- a/src/common/eval.c +++ b/src/common/eval.c @@ -44,15 +44,15 @@ var_num_t *mat_toc(var_t *v, int32_t *rows, int32_t *cols) { return NULL; } - if (v->v.a.maxdim > 2) { + if (v_maxdim(v) > 2) { // too many dimensions err_matdim(); return NULL; } - *rows = ABS(v->v.a.lbound[0] - v->v.a.ubound[0]) + 1; + *rows = ABS(v_lbound(v, 0) - v_ubound(v, 0)) + 1; - if (v->v.a.maxdim == 2) { - *cols = ABS(v->v.a.lbound[1] - v->v.a.ubound[1]) + 1; + if (v_maxdim(v) == 2) { + *cols = ABS(v_lbound(v, 1) - v_ubound(v, 1)) + 1; } else { *cols = *rows; *rows = 1; @@ -166,7 +166,7 @@ void mat_op2(var_t *l, var_t *r, int op) { free(m1); free(m2); if (m) { - if (r->v.a.maxdim == 1) { + if (v_maxdim(r) == 1) { mat_tov(l, m, lc, 1, 0); } else { mat_tov(l, m, lr, lc, 1); @@ -273,7 +273,7 @@ int v_wc_match(var_t *vwc, var_t *v) { if (v->type == V_ARRAY) { int i; ri = 1; - for (i = 0; i < v->v.a.size; i++) { + for (i = 0; i < v_asize(v); i++) { var_t *elem_p = v_elem(v, i); if (v_wc_match(vwc, elem_p) == 0) { ri = 0; @@ -371,7 +371,7 @@ static inline void oper_mul(var_t *r, var_t *left) { if (r->type == V_ARRAY || v_is_type(left, V_ARRAY)) { // arrays if (r->type == V_ARRAY && v_is_type(left, V_ARRAY)) { - if (left->v.a.maxdim == r->v.a.maxdim && r->v.a.maxdim == 1) { + if (v_maxdim(left) == v_maxdim(r) && v_maxdim(r) == 1) { if (op == '*') { mat_mul_1d(left, r); } else if (op == '%') { @@ -619,7 +619,7 @@ static inline void oper_cmp(var_t *r, var_t *left) { ri = 0; if (r->type == V_ARRAY) { int i; - for (i = 0; i < r->v.a.size; i++) { + for (i = 0; i < v_asize(r); i++) { var_t *elem_p = v_elem(r, i); if (v_compare(left, elem_p) == 0) { ri = i + 1; diff --git a/src/common/proc.c b/src/common/proc.c index e970e193..e9032ea5 100644 --- a/src/common/proc.c +++ b/src/common/proc.c @@ -560,7 +560,7 @@ pt_t par_getpt() { if (!prog_error) { if (var->type == V_ARRAY) { // array - if (var->v.a.size != 2) { + if (v_asize(var) != 2) { rt_raise(ERR_POLY_POINT); } else { pt.x = v_getreal(v_elem(var, 0)); @@ -612,7 +612,7 @@ ipt_t par_getipt() { if (!prog_error) { if (var->type == V_ARRAY) { // array - if (var->v.a.size != 2) { + if (v_asize(var) != 2) { rt_raise(ERR_POLY_POINT); } else { pt.x = v_getint(v_elem(var, 0)); @@ -664,7 +664,7 @@ int par_getpoly(pt_t **poly_pp) { } // zero-length or non array - if (var->type != V_ARRAY || var->v.a.size == 0) { + if (var->type != V_ARRAY || v_asize(var) == 0) { if (alloc) { v_free(var); v_detach(var); @@ -680,7 +680,7 @@ int par_getpoly(pt_t **poly_pp) { // error check if (style == 1) { - if (el->v.a.size != 2) { + if (v_asize(el) != 2) { err_parsepoly(-1, 1); if (alloc) { v_free(var); @@ -689,9 +689,9 @@ int par_getpoly(pt_t **poly_pp) { return 0; } - count = var->v.a.size; + count = v_asize(var); } else if (style == 0) { - if ((var->v.a.size % 2) != 0) { + if ((v_asize(var) % 2) != 0) { err_parsepoly(-1, 2); if (alloc) { v_free(var); @@ -700,7 +700,7 @@ int par_getpoly(pt_t **poly_pp) { return 0; } - count = var->v.a.size >> 1; + count = v_asize(var) >> 1; } // build array *poly_pp = poly = malloc(sizeof(pt_t) * count); @@ -715,7 +715,7 @@ int par_getpoly(pt_t **poly_pp) { // error check if (el->type != V_ARRAY) { err_parsepoly(i, 3); - } else if (el->v.a.size != 2) { + } else if (v_asize(el) != 2) { err_parsepoly(i, 4); } if (prog_error) { @@ -774,7 +774,7 @@ int par_getipoly(ipt_t **poly_pp) { } // zero-length or non array - if (var->type != V_ARRAY || var->v.a.size == 0) { + if (var->type != V_ARRAY || v_asize(var) == 0) { if (alloc) { v_free(var); v_detach(var); @@ -791,7 +791,7 @@ int par_getipoly(ipt_t **poly_pp) { // error check if (style == 1) { - if (el->v.a.size != 2) { + if (v_asize(el) != 2) { err_parsepoly(-1, 1); if (alloc) { v_free(var); @@ -800,9 +800,9 @@ int par_getipoly(ipt_t **poly_pp) { return 0; } - count = var->v.a.size; + count = v_asize(var); } else if (style == 0) { - if ((var->v.a.size % 2) != 0) { + if ((v_asize(var) % 2) != 0) { err_parsepoly(-1, 2); if (alloc) { v_free(var); @@ -811,7 +811,7 @@ int par_getipoly(ipt_t **poly_pp) { return 0; } - count = var->v.a.size >> 1; + count = v_asize(var) >> 1; } // build array *poly_pp = poly = malloc(sizeof(ipt_t) * count); @@ -826,7 +826,7 @@ int par_getipoly(ipt_t **poly_pp) { // error check if (el->type != V_ARRAY) { err_parsepoly(i, 3); - } else if (el->v.a.size != 2) { + } else if (v_asize(el) != 2) { err_parsepoly(i, 4); } if (prog_error) { diff --git a/src/common/var.c b/src/common/var.c index 2ad3988c..9c6af563 100644 --- a/src/common/var.c +++ b/src/common/var.c @@ -63,9 +63,9 @@ uint32_t v_get_capacity(uint32_t size) { void v_new_array(var_t *var, uint32_t size) { uint32_t capacity = v_get_capacity(size); var->type = V_ARRAY; - var->v.a.size = size; - var->v.a.capacity = capacity; - var->v.a.data = (var_t *)malloc(sizeof(var_t) * capacity); + v_capacity(var) = capacity; + v_asize(var) = size; + v_data(var) = (var_t *)malloc(sizeof(var_t) * capacity); for (uint32_t i = 0; i < capacity; i++) { var_t *e = v_elem(var, i); e->pooled = 0; @@ -74,12 +74,12 @@ void v_new_array(var_t *var, uint32_t size) { } void v_array_free(var_t *var) { - uint32_t v_size = var->v.a.capacity; - if (v_size && var->v.a.data) { + uint32_t v_size = v_capacity(var); + if (v_size && v_data(var)) { for (uint32_t i = 0; i < v_size; i++) { v_free(v_elem(var, i)); } - free(var->v.a.data); + free(v_data(var)); } } @@ -111,7 +111,7 @@ int v_isempty(var_t *var) { case V_STR: return (v_strlen(var) == 0); case V_ARRAY: - return (var->v.a.size == 0); + return (v_asize(var) == 0); case V_PTR: return (var->v.ap.p == 0); case V_MAP: @@ -152,7 +152,7 @@ int v_length(var_t *var) { case V_STR: return v_strlen(var); case V_ARRAY: - return var->v.a.size; + return v_asize(var); case V_PTR: ltostr(var->v.ap.p, tmpsb); return strlen(tmpsb); @@ -169,10 +169,10 @@ int v_length(var_t *var) { */ var_t *v_getelemptr(var_t *v, uint32_t index) { if (v->type == V_ARRAY) { - if (index < v->v.a.size) { + if (index < v_asize(v)) { return v_elem(v, index); } else { - err_vararridx(index, v->v.a.size); + err_vararridx(index, v_asize(v)); return NULL; } } @@ -181,18 +181,30 @@ var_t *v_getelemptr(var_t *v, uint32_t index) { } void v_set_array1_size(var_t *var, uint32_t size) { - var->v.a.size = size; - var->v.a.maxdim = 1; - var->v.a.ubound[0] = var->v.a.lbound[0] + (size - 1); + v_asize(var) = size; + v_maxdim(var) = 1; + v_ubound(var, 0) = v_lbound(var, 0) + (size - 1); } void v_init_array(var_t *var) { - var->v.a.size = 0; - var->v.a.capacity = 0; - var->v.a.data = NULL; - var->v.a.ubound[0] = opt_base; - var->v.a.lbound[0] = opt_base; - var->v.a.maxdim = 1; + v_capacity(var) = 0; + v_asize(var) = 0; + v_data(var) = NULL; + v_ubound(var, 0) = opt_base; + v_lbound(var, 0) = opt_base; + v_maxdim(var) = 1; +} + +void v_copy_array(var_t *dest, const var_t *src) { + memcpy(&dest->v.a, &src->v.a, sizeof(src->v.a)); + v_new_array(dest, v_asize(src)); + // copy each element + uint32_t v_size = v_asize(src); + for (uint32_t i = 0; i < v_size; i++) { + var_t *dest_vp = v_elem(dest, i); + v_init(dest_vp); + v_set(dest_vp, v_elem(src, i)); + } } /* @@ -203,32 +215,32 @@ void v_resize_array(var_t *v, uint32_t size) { err_varisnotarray(); } else if ((int)size < 0) { err_evargerr(); - } else if (size == v->v.a.size) { + } else if (size == v_asize(v)) { // already at target size } else if (size == 0) { v_free(v); v_init_array(v); v->type = V_ARRAY; - } else if (size < v->v.a.size) { + } else if (size < v_asize(v)) { // resize down. free discarded elements uint32_t v_size = v_asize(v); for (uint32_t i = size; i < v_size; i++) { v_free(v_elem(v, i)); } v_set_array1_size(v, size); - } else if (size <= v->v.a.capacity) { + } else if (size <= v_capacity(v)) { // use existing capacity v_set_array1_size(v, size); } else { // insufficient capacity - uint32_t prev_size = v->v.a.size; + uint32_t prev_size = v_asize(v); if (prev_size == 0) { v_new_array(v, size); } else if (prev_size < size) { // resize & copy uint32_t capacity = v_get_capacity(size); - v->v.a.data = (var_t *)realloc(v->v.a.data, sizeof(var_t) * capacity); - v->v.a.capacity = capacity; + v_capacity(v) = capacity; + v_data(v) = (var_t *)realloc(v_data(v), sizeof(var_t) * capacity); for (uint32_t i = prev_size; i < capacity; i++) { var_t *e = v_elem(v, i); e->pooled = 0; @@ -251,10 +263,10 @@ void v_resize_array(var_t *v, uint32_t size) { void v_tomatrix(var_t *v, int r, int c) { v_free(v); v_new_array(v, r * c); - v->v.a.lbound[0] = v->v.a.lbound[1] = opt_base; - v->v.a.ubound[0] = opt_base + (r - 1); - v->v.a.ubound[1] = opt_base + (c - 1); - v->v.a.maxdim = 2; + v_lbound(v, 0) = v_lbound(v, 1) = opt_base; + v_ubound(v, 0) = opt_base + (r - 1); + v_ubound(v, 1) = opt_base + (c - 1); + v_maxdim(v) = 2; } /* @@ -265,9 +277,9 @@ void v_toarray1(var_t *v, uint32_t r) { v->type = V_ARRAY; if (r > 0) { v_new_array(v, r); - v->v.a.maxdim = 1; - v->v.a.lbound[0] = opt_base; - v->v.a.ubound[0] = opt_base + (r - 1); + v_maxdim(v) = 1; + v_lbound(v, 0) = opt_base; + v_ubound(v, 0) = opt_base + (r - 1); } else { v_init_array(v); } @@ -285,7 +297,7 @@ int v_is_nonzero(var_t *v) { case V_STR: return (v->v.p.length != 0); case V_ARRAY: - return (v->v.a.size != 0); + return (v_asize(v) != 0); case V_PTR: return (v->v.ap.p != 0); case V_MAP: @@ -359,14 +371,13 @@ int v_compare(var_t *a, var_t *b) { } if ((a->type == V_ARRAY) && (b->type == V_ARRAY)) { // check size - if (a->v.a.size != b->v.a.size) { - if (a->v.a.size < b->v.a.size) { - return -1; - } + if (v_asize(a) < v_asize(b)) { + return -1; + } else if (v_asize(a) > v_asize(b)) { return 1; } // check every element - for (uint32_t i = 0; i < a->v.a.size; i++) { + for (uint32_t i = 0; i < v_asize(a); i++) { var_t *ea = v_elem(a, i); var_t *eb = v_elem(b, i); int ci = v_compare(ea, eb); @@ -494,16 +505,8 @@ void v_set(var_t *dest, const var_t *src) { } break; case V_ARRAY: - if (src->v.a.size) { - memcpy(&dest->v.a, &src->v.a, sizeof(src->v.a)); - v_new_array(dest, src->v.a.size); - // copy each element - uint32_t v_size = v_asize(src); - for (uint32_t i = 0; i < v_size; i++) { - var_t *dest_vp = v_elem(dest, i); - v_init(dest_vp); - v_set(dest_vp, v_elem(src, i)); - } + if (v_asize(src)) { + v_copy_array(dest, src); } else { v_init_array(dest); } diff --git a/src/common/var.h b/src/common/var.h index b6d50342..7758d1b7 100644 --- a/src/common/var.h +++ b/src/common/var.h @@ -72,6 +72,16 @@ extern "C" { struct var_s; typedef void (*method) (struct var_s *self); +// array +typedef struct { + struct var_s *data; /**< array data pointer */ + uint32_t size; /**< the number of elements */ + uint32_t capacity; /**< the number of slots */ + int32_t ubound[MAXDIM]; /**< upper bound */ + int8_t lbound[MAXDIM]; /**< lower bound */ + uint8_t maxdim; /**< number of dimensions */ +} var_array; + /** * @ingroup var * @typedef var_s @@ -113,14 +123,7 @@ typedef struct var_s { } p; // array - struct { - struct var_s *data; /**< array data pointer */ - uint32_t size; /**< the number of elements */ - uint32_t capacity; /**< the number of slots */ - int32_t lbound[MAXDIM]; /**< lower bound */ - int32_t ubound[MAXDIM]; /**< upper bound */ - byte maxdim; /**< number of dimensions */ - } a; + var_array a; // next item in the free-list struct var_s *pool_next; @@ -625,19 +628,49 @@ void v_input2var(const char *str, var_t *var); * < the number of the elements of the array (x) * @ingroup var */ -#define v_asize(x) ((x)->v.a.size) +#define v_asize(x) ((x)->v.a.size) + +/** + * < the number of array dimensions (x) + * @ingroup var + */ +#define v_maxdim(x) ((x)->v.a.maxdim) + +/** + * < the array lower bound of the given dimension (x) + * @ingroup var + */ +#define v_lbound(x, i) ((x)->v.a.lbound[i]) + +/** + * < the array upper bound of the given dimension (x) + * @ingroup var + */ +#define v_ubound(x, i) ((x)->v.a.ubound[i]) + +/** + * < the array data + * @ingroup var + */ +#define v_data(x) ((x)->v.a.data) + +/** + * < the array capacity + * @ingroup var + */ +#define v_capacity(x) ((x)->v.a.capacity) /** * < returns the integer value of variable v * @ingroup var */ -#define v_getint(v) v_igetval((v)) +#define v_getint(v) v_igetval((v)) /** * < returns the real value of variable v * @ingroup var */ -#define v_getreal(v) v_getval((v)) +#define v_getreal(v) v_getval((v)) /** * @ingroup var diff --git a/src/common/var_eval.c b/src/common/var_eval.c index fb41136b..e5e824be 100644 --- a/src/common/var_eval.c +++ b/src/common/var_eval.c @@ -37,11 +37,11 @@ bcip_t get_array_idx(var_t *array) { bcip_t i; bcip_t idim = v_getint(&var); v_free(&var); - idim = idim - array->v.a.lbound[lev]; + idim = idim - v_lbound(array, lev); m = idim; - for (i = lev + 1; i < array->v.a.maxdim; i++) { - m = m * (ABS(array->v.a.ubound[i] - array->v.a.lbound[i]) + 1); + for (i = lev + 1; i < v_maxdim(array); i++) { + m = m * (ABS(v_ubound(array, i) - v_lbound(array, i)) + 1); } idx += m; @@ -59,7 +59,7 @@ bcip_t get_array_idx(var_t *array) { } while (!prog_error && code_peek() != kwTYPE_LEVEL_END); if (!prog_error) { - if ((int) array->v.a.maxdim != lev) { + if ((int) v_maxdim(array) != lev) { err_missing_sep(); } } @@ -108,7 +108,7 @@ var_t *code_getvarptr_arridx(var_t *basevar_p) { code_skipnext(); bcip_t array_index = get_array_idx(basevar_p); if (!prog_error) { - if ((int) array_index < basevar_p->v.a.size && (int) array_index >= 0) { + if ((int) array_index < v_asize(basevar_p) && (int) array_index >= 0) { var_p = v_elem(basevar_p, array_index); if (code_peek() == kwTYPE_LEVEL_END) { code_skipnext(); @@ -124,7 +124,7 @@ var_t *code_getvarptr_arridx(var_t *basevar_p) { err_arrmis_rp(); } } else { - err_arridx(array_index, basevar_p->v.a.size); + err_arridx(array_index, v_asize(basevar_p)); } } } diff --git a/src/common/var_map.c b/src/common/var_map.c index ea7e48d5..ee73dcab 100644 --- a/src/common/var_map.c +++ b/src/common/var_map.c @@ -237,12 +237,12 @@ var_p_t map_add_var(var_p_t base, const char *name, int value) { * an empty variable that will be returned in a further call */ void map_get_value(var_p_t base, var_p_t var_key, var_p_t *result) { - if (base->type == V_ARRAY && base->v.a.size) { + if (base->type == V_ARRAY && v_asize(base)) { // convert the non-empty array to a map var_t *clone = v_clone(base); hashmap_create(base, 0); - for (int i = 0; i < clone->v.a.size; i++) { + for (int i = 0; i < v_asize(clone); i++) { const var_t *element = v_elem(clone, i); var_p_t key = v_new(); v_setint(key, i); @@ -352,10 +352,10 @@ void array_append_elem(hashmap_cb *cb, var_t *elem) { */ void array_to_str(hashmap_cb *cb, var_t *var) { strcpy(cb->buffer, "["); - if (var->v.a.maxdim == 2) { + if (v_maxdim(var) == 2) { // NxN - int rows = ABS(var->v.a.ubound[0] - var->v.a.lbound[0]) + 1; - int cols = ABS(var->v.a.ubound[1] - var->v.a.lbound[1]) + 1; + int rows = ABS(v_ubound(var, 0) - v_lbound(var, 0)) + 1; + int cols = ABS(v_ubound(var, 1) - v_lbound(var, 1)) + 1; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { @@ -371,10 +371,10 @@ void array_to_str(hashmap_cb *cb, var_t *var) { } } } else { - for (int i = 0; i < var->v.a.size; i++) { + for (int i = 0; i < v_asize(var); i++) { var_t *elem = v_elem(var, i); array_append_elem(cb, elem); - if (i != var->v.a.size - 1) { + if (i != v_asize(var) - 1) { strcat(cb->buffer, ","); } } diff --git a/src/ui/form.cpp b/src/ui/form.cpp index 4e7e0b7f..819036f4 100644 --- a/src/ui/form.cpp +++ b/src/ui/form.cpp @@ -271,7 +271,7 @@ extern "C" void v_create_form(var_p_t var) { if (arg->type == V_MAP) { var_p_t inputs = map_get(arg, FORM_INPUTS); if (inputs != NULL && inputs->type == V_ARRAY) { - for (unsigned i = 0; i < inputs->v.a.size; i++) { + for (unsigned i = 0; i < v_asize(inputs); i++) { var_p_t elem = v_elem(inputs, i); if (elem->type == V_MAP) { hasInputs = true; @@ -286,14 +286,14 @@ extern "C" void v_create_form(var_p_t var) { var_p_t v_focus = map_get(var, FORM_FOCUS); unsigned i_focus = v_focus != NULL ? v_getint(v_focus) : -1; var_p_t inputs = map_get(var, FORM_INPUTS); - for (unsigned i = 0; inputs != NULL && i < inputs->v.a.size; i++) { + for (unsigned i = 0; inputs != NULL && i < v_asize(inputs); i++) { var_p_t elem = v_elem(inputs, i); if (elem->type == V_MAP) { FormInput *widget = create_input(elem); if (widget != NULL) { widget->construct(var, elem, i); out->addInput(widget); - if (i_focus == i || inputs->v.a.size == 1) { + if (i_focus == i || v_asize(inputs) == 1) { widget->setFocus(true); } } diff --git a/src/ui/image.cpp b/src/ui/image.cpp index 867314e2..8c8e07cb 100644 --- a/src/ui/image.cpp +++ b/src/ui/image.cpp @@ -185,9 +185,9 @@ ImageBuffer *load_image(var_t *var) { } } } - } else if (var->type == V_ARRAY && var->v.a.maxdim == 2) { - int w = ABS(var->v.a.lbound[0] - var->v.a.ubound[0]) + 1; - int h = ABS(var->v.a.lbound[1] - var->v.a.ubound[1]) + 1; + } else if (var->type == V_ARRAY && v_maxdim(var) == 2) { + int w = ABS(v_lbound(var, 0) - v_ubound(var, 0)) + 1; + int h = ABS(v_lbound(var, 1) - v_ubound(var, 1)) + 1; int size = w * h * 4; unsigned char *image = (unsigned char *)malloc(size); for (int y = 0; y < h; y++) { @@ -520,26 +520,26 @@ extern "C" void v_create_image(var_p_t var) { strlcpy(file.name, arg.v.p.ptr, sizeof(file.name)); file.type = ft_stream; image = load_image(&file); - } else if (arg.type == V_ARRAY && arg.v.a.size > 0 && !prog_error) { + } else if (arg.type == V_ARRAY && v_asize(&arg) > 0 && !prog_error) { var_p_t elem0 = v_elem(&arg, 0); if (elem0->type == V_STR) { - char **data = new char*[arg.v.a.size]; - for (unsigned i = 0; i < arg.v.a.size; i++) { + char **data = new char*[v_asize(&arg)]; + for (unsigned i = 0; i < v_asize(&arg); i++) { var_p_t elem = v_elem(&arg, i); data[i] = elem->v.p.ptr; } image = load_xpm_image(data); delete [] data; - } else if (arg.v.a.maxdim == 2) { + } else if (v_maxdim(&arg) == 2) { // load from 2d array image = load_image(&arg); } else if (elem0->type == V_INT) { - unsigned char *data = new unsigned char[arg.v.a.size]; - for (unsigned i = 0; i < arg.v.a.size; i++) { + unsigned char *data = new unsigned char[v_asize(&arg)]; + for (unsigned i = 0; i < v_asize(&arg); i++) { var_p_t elem = v_elem(&arg, i); data[i] = (unsigned char)elem->v.i; } - image = load_image(data, arg.v.a.size); + image = load_image(data, v_asize(&arg)); delete [] data; } } else if (arg.type == V_INT && !prog_error) { diff --git a/src/ui/inputs.cpp b/src/ui/inputs.cpp index 538861c5..9248133b 100644 --- a/src/ui/inputs.cpp +++ b/src/ui/inputs.cpp @@ -279,7 +279,7 @@ var_p_t FormInput::getField(var_p_t form) { if (form->type == V_MAP) { var_p_t inputs = map_get(form, FORM_INPUTS); if (inputs != NULL && inputs->type == V_ARRAY) { - for (unsigned i = 0; i < inputs->v.a.size && !result; i++) { + for (unsigned i = 0; i < v_asize(inputs) && !result; i++) { var_p_t elem = v_elem(inputs, i); if (elem->type == V_MAP && (_id == map_get_int(elem, FORM_INPUT_ID, -1))) { result = elem; @@ -828,7 +828,7 @@ void ListModel::create(var_t *v) { // construct from an array of values void ListModel::fromArray(var_t *v) { - for (unsigned i = 0; i < v->v.a.size; i++) { + for (unsigned i = 0; i < v_asize(v); i++) { var_t *el_p = v_elem(v, i); if (el_p->type == V_STR) { _list.add(new strlib::String((const char *)el_p->v.p.ptr)); From 8cf7be7fbd8cb1c3149c113f9fbc5225c1634383 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sun, 28 Jan 2018 09:23:36 +1000 Subject: [PATCH 05/10] COMMON: revert 6d array support --- src/common/blib.c | 47 +++++++++++++------------- src/common/sys.h | 2 +- src/common/var.c | 85 ++++++++++++++++++++++++++++------------------- src/common/var.h | 21 +++++------- 4 files changed, 84 insertions(+), 71 deletions(-) diff --git a/src/common/blib.c b/src/common/blib.c index 8ed1edf1..4f4186af 100644 --- a/src/common/blib.c +++ b/src/common/blib.c @@ -121,8 +121,8 @@ void cmd_packed_let() { } } -unsigned get_dimensions(int32_t **lbound, int32_t **ubound) { - unsigned count = 0; +uint8_t get_dimensions(int32_t **lbound, int32_t **ubound) { + uint8_t count = 0; if (code_peek() == kwTYPE_LEVEL_BEGIN) { code_skipnext(); while (code_peek() != kwTYPE_LEVEL_END && !prog_error) { @@ -193,7 +193,7 @@ void cmd_dim(int preserve) { code_skipnext(); if (code_getnext() != ',') { err_missing_comma(); - return; + break; } } @@ -204,30 +204,31 @@ void cmd_dim(int preserve) { int32_t *lbound = NULL; int32_t *ubound = NULL; - unsigned dimensions = get_dimensions(&lbound, &ubound); + uint8_t dimensions = get_dimensions(&lbound, &ubound); if (!prog_error) { + if (!preserve || var_p->type != V_ARRAY) { + v_free(var_p); + } if (!dimensions) { v_toarray1(var_p, 0); + continue; + } + int size = 1; + for (int i = 0; i < dimensions; i++) { + size = size * (ABS(ubound[i] - lbound[i]) + 1); + } + if (!preserve || var_p->type != V_ARRAY) { + v_new_array(var_p, size); + } else if (v_maxdim(var_p) != dimensions) { + err_matdim(); } else { - int size = 1; - for (int i = 0; i < dimensions; i++) { - size = size * (ABS(ubound[i] - lbound[i]) + 1); - } - if (!preserve) { - v_new_array(var_p, size); - } else { - if (var_p->type == V_ARRAY) { - v_resize_array(var_p, size); - } else { - v_new_array(var_p, size); - } - } - // dim - v_maxdim(var_p) = dimensions; - for (int i = 0; i < dimensions; i++) { - v_lbound(var_p, i) = lbound[i]; - v_ubound(var_p, i) = ubound[i]; - } + // preserve previous array contents + v_resize_array(var_p, size); + } + v_maxdim(var_p) = dimensions; + for (int i = 0; i < dimensions; i++) { + v_lbound(var_p, i) = lbound[i]; + v_ubound(var_p, i) = ubound[i]; } } free(lbound); diff --git a/src/common/sys.h b/src/common/sys.h index d6816f6a..da50ae69 100644 --- a/src/common/sys.h +++ b/src/common/sys.h @@ -80,7 +80,7 @@ typedef long int var_int_t; #define SB_KEYWORD_SIZE 128 #define SB_SOURCELINE_SIZE 65536 // compiler #define SB_TEXTLINE_SIZE 8192 // RTL -#define SB_EXEC_STACK_SIZE 256 // executor's stack size +#define SB_EXEC_STACK_SIZE 512 // executor's stack size #define SB_EVAL_STACK_SIZE 16 // evaluation stack size #define SB_KW_NONE_STR "Nil" diff --git a/src/common/var.c b/src/common/var.c index 9c6af563..bf2fcd9f 100644 --- a/src/common/var.c +++ b/src/common/var.c @@ -60,9 +60,9 @@ uint32_t v_get_capacity(uint32_t size) { return size + (size / 2) + 1; } -void v_new_array(var_t *var, uint32_t size) { +// allocate capacity in the array container +void v_alloc_capacity(var_t *var, uint32_t size) { uint32_t capacity = v_get_capacity(size); - var->type = V_ARRAY; v_capacity(var) = capacity; v_asize(var) = size; v_data(var) = (var_t *)malloc(sizeof(var_t) * capacity); @@ -73,13 +73,55 @@ void v_new_array(var_t *var, uint32_t size) { } } +// create an new empty array +void v_init_array(var_t *var) { + v_capacity(var) = 0; + v_asize(var) = 0; + v_data(var) = NULL; + v_maxdim(var) = 1; + v_ubound(var, 0) = opt_base; + v_lbound(var, 0) = opt_base; +} + +// create an array of the given size +void v_new_array(var_t *var, uint32_t size) { + var->type = V_ARRAY; + v_alloc_capacity(var, size); +} + +void v_set_array1_size(var_t *var, uint32_t size) { + v_asize(var) = size; + v_maxdim(var) = 1; + v_ubound(var, 0) = v_lbound(var, 0) + (size - 1); +} + +void v_copy_array(var_t *dest, const var_t *src) { + dest->type = V_ARRAY; + v_alloc_capacity(dest, v_asize(src)); + + // copy dimensions + v_maxdim(dest) = v_maxdim(src); + for (int i = 0; i < v_maxdim(src); i++) { + v_ubound(dest, i) = v_ubound(src, i); + v_lbound(dest, i) = v_lbound(src, i); + } + + // copy each element + uint32_t v_size = v_asize(src); + for (uint32_t i = 0; i < v_size; i++) { + var_t *dest_vp = v_elem(dest, i); + v_init(dest_vp); + v_set(dest_vp, v_elem(src, i)); + } +} + void v_array_free(var_t *var) { uint32_t v_size = v_capacity(var); if (v_size && v_data(var)) { for (uint32_t i = 0; i < v_size; i++) { v_free(v_elem(var, i)); } - free(v_data(var)); + free(var->v.a.data); } } @@ -180,33 +222,6 @@ var_t *v_getelemptr(var_t *v, uint32_t index) { return NULL; } -void v_set_array1_size(var_t *var, uint32_t size) { - v_asize(var) = size; - v_maxdim(var) = 1; - v_ubound(var, 0) = v_lbound(var, 0) + (size - 1); -} - -void v_init_array(var_t *var) { - v_capacity(var) = 0; - v_asize(var) = 0; - v_data(var) = NULL; - v_ubound(var, 0) = opt_base; - v_lbound(var, 0) = opt_base; - v_maxdim(var) = 1; -} - -void v_copy_array(var_t *dest, const var_t *src) { - memcpy(&dest->v.a, &src->v.a, sizeof(src->v.a)); - v_new_array(dest, v_asize(src)); - // copy each element - uint32_t v_size = v_asize(src); - for (uint32_t i = 0; i < v_size; i++) { - var_t *dest_vp = v_elem(dest, i); - v_init(dest_vp); - v_set(dest_vp, v_elem(src, i)); - } -} - /* * resize an existing array */ @@ -235,7 +250,7 @@ void v_resize_array(var_t *v, uint32_t size) { // insufficient capacity uint32_t prev_size = v_asize(v); if (prev_size == 0) { - v_new_array(v, size); + v_alloc_capacity(v, size); } else if (prev_size < size) { // resize & copy uint32_t capacity = v_get_capacity(size); @@ -263,10 +278,10 @@ void v_resize_array(var_t *v, uint32_t size) { void v_tomatrix(var_t *v, int r, int c) { v_free(v); v_new_array(v, r * c); + v_maxdim(v) = 2; v_lbound(v, 0) = v_lbound(v, 1) = opt_base; v_ubound(v, 0) = opt_base + (r - 1); v_ubound(v, 1) = opt_base + (c - 1); - v_maxdim(v) = 2; } /* @@ -606,6 +621,7 @@ void v_inc(var_t *a, var_t *b) { } /* + * returns the sign of a variable */ int v_sign(var_t *x) { if (x->type == V_INT) { @@ -771,14 +787,13 @@ void v_input2var(const char *str, var_t *var) { // no data v_setstr(var, str); } else { - char *np, *sb; char buf[INT_STR_LEN]; int type; var_int_t lv; var_num_t dv; - sb = strdup(str); - np = get_numexpr(sb, buf, &type, &lv, &dv); + char *sb = strdup(str); + char *np = get_numexpr(sb, buf, &type, &lv, &dv); if (type == 1 && *np == '\0') { v_setint(var, lv); diff --git a/src/common/var.h b/src/common/var.h index 7758d1b7..f5aa35fd 100644 --- a/src/common/var.h +++ b/src/common/var.h @@ -63,7 +63,7 @@ * @ingroup var * @def MAXDIM Maxium number of array-dimensions */ -#define MAXDIM 2 +#define MAXDIM 6 #if defined(__cplusplus) extern "C" { @@ -72,16 +72,6 @@ extern "C" { struct var_s; typedef void (*method) (struct var_s *self); -// array -typedef struct { - struct var_s *data; /**< array data pointer */ - uint32_t size; /**< the number of elements */ - uint32_t capacity; /**< the number of slots */ - int32_t ubound[MAXDIM]; /**< upper bound */ - int8_t lbound[MAXDIM]; /**< lower bound */ - uint8_t maxdim; /**< number of dimensions */ -} var_array; - /** * @ingroup var * @typedef var_s @@ -123,7 +113,14 @@ typedef struct var_s { } p; // array - var_array a; + struct { + struct var_s *data; /**< array data pointer */ + uint32_t size; /**< the number of elements */ + uint32_t capacity; /**< the number of slots */ + int32_t ubound[MAXDIM]; /**< upper bound */ + int8_t lbound[MAXDIM]; /**< lower bound */ + uint8_t maxdim; /**< number of dimensions */ + } a; // next item in the free-list struct var_s *pool_next; From 453e70b57e2ef0bf91d139ec4d58386bb2658b9a Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sun, 28 Jan 2018 09:57:08 +1000 Subject: [PATCH 06/10] COMMON: revert 6d array support --- samples/distro-examples/tests/array.bas | 7 +++++++ src/common/blib_func.c | 12 +++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/samples/distro-examples/tests/array.bas b/samples/distro-examples/tests/array.bas index 9966f5bb..b835e0e9 100644 --- a/samples/distro-examples/tests/array.bas +++ b/samples/distro-examples/tests/array.bas @@ -294,3 +294,10 @@ camera = { if (camera.x != 512) then throw "invalid x" if (camera.height != 78) then throw "invalid height" if (camera.distance != 800) then throw "invalid distance" + +rem - 6d array +dim a6d(0 to 5, 0 to 5, 0 to 5, 0 to 5, 0 to 5, 4 to 5) +a6d(0,1,2,3,4,5)=99 +if (a6d(0,1,2,3,4,5) <> 99) then + throw "a6d error 1" +endif diff --git a/src/common/blib_func.c b/src/common/blib_func.c index 4664f640..1bbb714a 100644 --- a/src/common/blib_func.c +++ b/src/common/blib_func.c @@ -1857,8 +1857,7 @@ void cmd_intN(long funcCode, var_t *r) { // if (code_peek() == kwTYPE_VAR) { var_p = code_getvarptr(); - if (var_p->type == V_ARRAY) { - + if (!prog_error && var_p->type == V_ARRAY) { l = 1; if (code_peek() == kwTYPE_SEP) { par_getcomma(); @@ -1892,9 +1891,8 @@ void cmd_intN(long funcCode, var_t *r) { // int <- UBOUND(array [, dim]) // if (code_peek() == kwTYPE_VAR) { - code_skipnext(); - var_p = tvar[code_getaddr()]; - if (var_p->type == V_ARRAY) { + var_p = code_getvarptr(); + if (!prog_error && var_p->type == V_ARRAY) { l = 1; if (code_peek() == kwTYPE_SEP) { par_getcomma(); @@ -2556,7 +2554,7 @@ void cmd_genfunc(long funcCode, var_t *r) { ofs = prog_ip; if (code_isvar()) { var_t *basevar_p = code_getvarptr(); - if (basevar_p->type == V_ARRAY) { + if (!prog_error && basevar_p->type == V_ARRAY) { count = v_asize(basevar_p); for (int i = 0; i < count; i++) { var_t *elem_p = v_getelemptr(basevar_p, i); @@ -2626,7 +2624,7 @@ void cmd_genfunc(long funcCode, var_t *r) { ofs = prog_ip; if (code_isvar()) { var_t *basevar_p = code_getvarptr(); - if (basevar_p->type == V_ARRAY) { + if (!prog_error && basevar_p->type == V_ARRAY) { count = v_asize(basevar_p); for (int i = 0; i < count; i++) { var_t *elem_p = v_getelemptr(basevar_p, i); From e4237f4f7649d63bbafb4683c626e37dcd9af955 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sun, 28 Jan 2018 14:03:17 +1000 Subject: [PATCH 07/10] LIB: update lodepng --- src/lib/lodepng.c | 25 +++++++++++++++++++------ src/lib/lodepng.h | 11 +++++++++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/lib/lodepng.c b/src/lib/lodepng.c index 37b0562b..69989103 100644 --- a/src/lib/lodepng.c +++ b/src/lib/lodepng.c @@ -1,7 +1,7 @@ /* -LodePNG version 20170917 +LodePNG version 20180114 -Copyright (c) 2005-2017 Lode Vandevenne +Copyright (c) 2005-2018 Lode Vandevenne This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -39,7 +39,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ #endif /*_MSC_VER */ -const char* LODEPNG_VERSION_STRING = "20170917"; +const char* LODEPNG_VERSION_STRING = "20180114"; /* This source file is built up in the following large parts. The code sections @@ -4565,12 +4565,20 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* data; /*the data in the chunk*/ /*error: size of the in buffer too small to contain next chunk*/ - if((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30); + if((size_t)((chunk - in) + 12) > insize || chunk < in) + { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 30); + } /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ chunkLength = lodepng_chunk_length(chunk); /*error: chunk length larger than the max PNG chunk size*/ - if(chunkLength > 2147483647) CERROR_BREAK(state->error, 63); + if(chunkLength > 2147483647) + { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 63); + } if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) { @@ -4657,7 +4665,10 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ - if(!lodepng_chunk_ancillary(chunk)) CERROR_BREAK(state->error, 69); + if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) + { + CERROR_BREAK(state->error, 69); + } unknown = 1; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS @@ -4822,6 +4833,8 @@ void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) settings->remember_unknown_chunks = 0; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ settings->ignore_crc = 0; + settings->ignore_critical = 0; + settings->ignore_end = 0; lodepng_decompress_settings_init(&settings->zlibsettings); } diff --git a/src/lib/lodepng.h b/src/lib/lodepng.h index d633bfae..cf6667c8 100644 --- a/src/lib/lodepng.h +++ b/src/lib/lodepng.h @@ -1,7 +1,7 @@ /* -LodePNG version 20170917 +LodePNG version 20180114 -Copyright (c) 2005-2017 Lode Vandevenne +Copyright (c) 2005-2018 Lode Vandevenne This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -255,6 +255,7 @@ const char* lodepng_error_text(unsigned code); typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; struct LodePNGDecompressSettings { + /* Check LodePNGDecoderSettings for more ignorable errors */ unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ /*use custom zlib decoder instead of built in one (default: null)*/ @@ -520,7 +521,10 @@ typedef struct LodePNGDecoderSettings { LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ + /* Check LodePNGDecompressSettings for more ignorable errors */ unsigned ignore_crc; /*ignore CRC checksums*/ + unsigned ignore_critical; /*ignore unknown critical chunks*/ + unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ @@ -1567,6 +1571,8 @@ For decoding: state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums state.decoder.zlibsettings.custom_...: use custom inflate function state.decoder.ignore_crc: ignore CRC checksums +state.decoder.ignore_critical: ignore unknown critical chunks +state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors state.decoder.color_convert: convert internal PNG color to chosen one state.decoder.read_text_chunks: whether to read in text metadata chunks state.decoder.remember_unknown_chunks: whether to read in unknown chunks @@ -1608,6 +1614,7 @@ yyyymmdd. Some changes aren't backwards compatible. Those are indicated with a (!) symbol. +*) 14 jan 2018: allow optionally ignoring a few more recoverable errors *) 17 sep 2017: fix memory leak for some encoder input error cases *) 27 nov 2016: grey+alpha auto color model detection bugfix *) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). From 24ea81cad6101878dce9a5f25a2d6e901998b812 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Mon, 29 Jan 2018 21:26:41 +1000 Subject: [PATCH 08/10] COMMON: revert 6d array support --- samples/distro-examples/tests/array.bas | 15 ++++++++++++++- src/common/blib.c | 2 +- src/common/sberr.c | 4 ++++ src/common/sberr.h | 1 + src/common/var.c | 12 ++++++++---- src/languages/messages.en.h | 1 + 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/samples/distro-examples/tests/array.bas b/samples/distro-examples/tests/array.bas index b835e0e9..4dfa05ea 100644 --- a/samples/distro-examples/tests/array.bas +++ b/samples/distro-examples/tests/array.bas @@ -295,9 +295,22 @@ if (camera.x != 512) then throw "invalid x" if (camera.height != 78) then throw "invalid height" if (camera.distance != 800) then throw "invalid distance" -rem - 6d array +rem --- 6d arrays dim a6d(0 to 5, 0 to 5, 0 to 5, 0 to 5, 0 to 5, 4 to 5) a6d(0,1,2,3,4,5)=99 if (a6d(0,1,2,3,4,5) <> 99) then throw "a6d error 1" endif +dim m(1 to 11, 2 to 12, 3 to 13, 4 to 14, 5 to 15, 6 to 16) +for i = 1 to 6 + if (lbound(m,i) != i) then + throw "lbound error" + endif + if (ubound(m,i) != 10+i) then + throw "ubound error" + endif +next i +m[1,2,3,4,5,6]=999 +if (999 <> m[1,2,3,4,5,6]) then + throw "e" +endif \ No newline at end of file diff --git a/src/common/blib.c b/src/common/blib.c index 4f4186af..dac3e4a4 100644 --- a/src/common/blib.c +++ b/src/common/blib.c @@ -213,7 +213,7 @@ void cmd_dim(int preserve) { v_toarray1(var_p, 0); continue; } - int size = 1; + uint32_t size = 1; for (int i = 0; i < dimensions; i++) { size = size * (ABS(ubound[i] - lbound[i]) + 1); } diff --git a/src/common/sberr.c b/src/common/sberr.c index 69ebe997..6a78a2b0 100644 --- a/src/common/sberr.c +++ b/src/common/sberr.c @@ -318,6 +318,10 @@ void err_form_input() { err_throw(ERR_FORM_INPUT); } +void err_memory() { + rt_raise(ERR_MEMORY); +} + /** * the DONE message */ diff --git a/src/common/sberr.h b/src/common/sberr.h index 7318e7f6..e2d6759c 100644 --- a/src/common/sberr.h +++ b/src/common/sberr.h @@ -78,6 +78,7 @@ void err_ref_var(); void err_ref_circ_var(); void err_array(); void err_form_input(); +void err_memory(); void err_throw(const char *fmt, ...); int err_handle_error(const char *err, var_p_t var); void inf_done(void); diff --git a/src/common/var.c b/src/common/var.c index bf2fcd9f..70626d5c 100644 --- a/src/common/var.c +++ b/src/common/var.c @@ -66,10 +66,14 @@ void v_alloc_capacity(var_t *var, uint32_t size) { v_capacity(var) = capacity; v_asize(var) = size; v_data(var) = (var_t *)malloc(sizeof(var_t) * capacity); - for (uint32_t i = 0; i < capacity; i++) { - var_t *e = v_elem(var, i); - e->pooled = 0; - v_init(e); + if (!v_data(var)) { + err_memory(); + } else { + for (uint32_t i = 0; i < capacity; i++) { + var_t *e = v_elem(var, i); + e->pooled = 0; + v_init(e); + } } } diff --git a/src/languages/messages.en.h b/src/languages/messages.en.h index 9bba1c41..93643f5b 100644 --- a/src/languages/messages.en.h +++ b/src/languages/messages.en.h @@ -219,3 +219,4 @@ #define ERR_PARAM_NUM "Incorrect number of parameters: %d. Expected %d." #define ERR_PACK_TOO_MANY "Too many values to unpack" #define ERR_PACK_TOO_FEW "Need more than %d values to unpack" +#define ERR_MEMORY "Out of memory error" From 9039603f2900b406e2bac55fa1d4e4248221f399 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sat, 3 Feb 2018 10:29:42 +1000 Subject: [PATCH 09/10] CONSOLE: fix win32 console build --- src/platform/console/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/console/main.c b/src/platform/console/main.c index 8efd4598..9e1f0e34 100644 --- a/src/platform/console/main.c +++ b/src/platform/console/main.c @@ -253,7 +253,7 @@ int process_options(int argc, char *argv[]) { return 1; } -#if defined(__GNUC__) && !defined(__MACH__) +#if defined(__GNUC__) && !defined(__MACH__) && !defined(_Win32) // for analysing excessive malloc calls using kdbg extern void *__libc_malloc(size_t size); void *malloc(size_t size) { From 664cdb78c1ba8eeca7e6611f164cd3ea6be7b560 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sat, 3 Feb 2018 13:28:43 +1000 Subject: [PATCH 10/10] COMMON: moved decompiler to command line --- ChangeLog | 4 ++ src/common/Makefile.am | 1 - src/common/brun.c | 63 +++------------------- src/common/smbas.h | 9 ---- src/platform/android/jni/common/Android.mk | 1 - src/platform/console/Makefile.am | 3 +- src/{common => platform/console}/decomp.c | 4 +- src/platform/console/main.c | 63 +++++++++++++++++++++- 8 files changed, 76 insertions(+), 72 deletions(-) rename src/{common => platform/console}/decomp.c (99%) diff --git a/ChangeLog b/ChangeLog index 2be1aef8..16a33a26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2018-02-03 (0.12.12) + COMMON: restore 6d array handling + COMMON: increase default stack size + 2018-01-13 (0.12.12) Fix osx crash diff --git a/src/common/Makefile.am b/src/common/Makefile.am index c45dafb1..8c016bb2 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -53,7 +53,6 @@ libsb_common_a_SOURCES = \ blib_sound.c \ brun.c \ ceval.c \ - decomp.c \ device.c device.h \ screen.c \ system.c \ diff --git a/src/common/brun.c b/src/common/brun.c index c8f1d29c..7572f63a 100644 --- a/src/common/brun.c +++ b/src/common/brun.c @@ -31,7 +31,6 @@ int exec_close_task(); void sys_before_comp(); static char fileName[OS_FILENAME_SIZE + 1]; -static int exec_tid; static stknode_t err_node; #define EVT_CHECK_EVERY 50 @@ -1528,47 +1527,7 @@ int sbasic_recursive_exec(int tid) { } /** - * dump-taskinfo - */ -void sbasic_dump_taskinfo(FILE * output) { - int i; - int prev_tid = 0; - - fprintf(output, "\n* task list:\n"); - for (i = 0; i < count_tasks(); i++) { - prev_tid = activate_task(i); - fprintf(output, " id %d, child of %d, file %s, status %d\n", ctask->tid, ctask->parent, ctask->file, - ctask->status); - } - activate_task(prev_tid); -} - -/** - * dump-bytecode - */ -void sbasic_dump_bytecode(int tid, FILE *output) { - int i; - int prev_tid; - - prev_tid = activate_task(tid); - - for (i = 0; i < count_tasks(); i++) { - activate_task(i); - if (ctask->parent == tid) { - // do the same for the childs - sbasic_dump_bytecode(ctask->tid, output); - } - } - - activate_task(tid); - fprintf(output, "\n* task: %d/%d (%s)\n", ctask->tid, count_tasks(), prog_file); - // run the code - dump_bytecode(output); - activate_task(prev_tid); -} - -/** - * TODO add comment + * compile the given file into bytecode */ int sbasic_compile(const char *file) { int comp_rq = 0; // compilation required = 0 @@ -1626,18 +1585,21 @@ int sbasic_compile(const char *file) { /** * initialize executor and run a binary */ -void sbasic_exec_prepare(const char *filename) { +int sbasic_exec_prepare(const char *filename) { + int taskId; + v_init_pool(); // load source if (opt_nosave) { - exec_tid = brun_create_task(filename, ctask->bytecode, 0); + taskId = brun_create_task(filename, ctask->bytecode, 0); } else { - exec_tid = brun_create_task(filename, 0, 0); + taskId = brun_create_task(filename, 0, 0); } // reset system cmd_play_reset(); graph_reset(); + return taskId; } /* @@ -1694,9 +1656,6 @@ int sbasic_exec(const char *file) { opt_pref_height = 0; opt_show_page = 0; - if (opt_decomp) { - opt_nosave = 1; - } // setup global values gsb_last_line = gsb_last_error = 0; strlcpy(gsb_last_file, file, sizeof(gsb_last_file)); @@ -1708,12 +1667,6 @@ int sbasic_exec(const char *file) { // cannot run a unit exec_rq = 0; gsb_last_error = 1; - } else if (opt_decomp && success) { - sbasic_exec_prepare(file); // load everything - sbasic_dump_taskinfo(stdout); - sbasic_dump_bytecode(exec_tid, stdout); - exec_close(exec_tid); // clean up executor's garbages - exec_rq = 0; } else if (!success) { // there was some errors; do not continue exec_rq = 0; gsb_last_error = 1; @@ -1721,7 +1674,7 @@ int sbasic_exec(const char *file) { if (exec_rq) { // we will run it // load everything - sbasic_exec_prepare(file); + int exec_tid = sbasic_exec_prepare(file); dev_init(opt_graphics, 0); // initialize output device for graphics srand(clock()); // randomize diff --git a/src/common/smbas.h b/src/common/smbas.h index 61cf23a0..5cdc5cd2 100644 --- a/src/common/smbas.h +++ b/src/common/smbas.h @@ -101,7 +101,6 @@ typedef struct { EXTERN byte opt_graphics; /**< command-line option: start in graphics mode */ EXTERN byte opt_quiet; /**< command-line option: quiet */ -EXTERN byte opt_decomp; /**< decompile */ EXTERN char opt_command[OPT_CMD_SZ]; /**< command-line parameters (COMMAND$) */ EXTERN int opt_base; /**< OPTION BASE x */ EXTERN byte opt_loadmod; /**< load all modules */ @@ -242,14 +241,6 @@ void brun_stop(void); */ int brun_status(void); -/** - * decompiler, - * dumps the code in the current task - * - * @param output the output stream (FILE*) - */ -void dump_bytecode(FILE *output); - /** * returns the last-modified time of the file * diff --git a/src/platform/android/jni/common/Android.mk b/src/platform/android/jni/common/Android.mk index 78daccab..987a9b1b 100644 --- a/src/platform/android/jni/common/Android.mk +++ b/src/platform/android/jni/common/Android.mk @@ -29,7 +29,6 @@ LOCAL_SRC_FILES := \ $(COMMON)/blib_sound.c \ $(COMMON)/brun.c \ $(COMMON)/ceval.c \ - $(COMMON)/decomp.c \ $(COMMON)/device.c \ $(COMMON)/screen.c \ $(COMMON)/system.c \ diff --git a/src/platform/console/Makefile.am b/src/platform/console/Makefile.am index 910d69bb..9aeed90a 100644 --- a/src/platform/console/Makefile.am +++ b/src/platform/console/Makefile.am @@ -9,8 +9,9 @@ AM_CPPFLAGS = -I$(top_builddir)/src -I. @PACKAGE_CFLAGS@ bin_PROGRAMS = sbasic -sbasic_SOURCES = \ +sbasic_SOURCES = \ ../console/main.c \ + ../console/decomp.c \ ../console/dev_null.c sbasic_LDADD = -L$(top_srcdir)/src/common -lsb_common @PACKAGE_LIBS@ diff --git a/src/common/decomp.c b/src/platform/console/decomp.c similarity index 99% rename from src/common/decomp.c rename to src/platform/console/decomp.c index 00449034..ab45abd5 100644 --- a/src/common/decomp.c +++ b/src/platform/console/decomp.c @@ -10,11 +10,9 @@ #include "common/sbapp.h" /** - * * decompiler - * */ -void dump_bytecode(FILE * output) { +void dump_bytecode(FILE *output) { int i, c, b, d, h, l, j; long lng; int len, new_ip; diff --git a/src/platform/console/main.c b/src/platform/console/main.c index 9e1f0e34..39993f12 100644 --- a/src/platform/console/main.c +++ b/src/platform/console/main.c @@ -13,6 +13,13 @@ // global filename (its needed for CTRL+C signal - delete temporary) char g_file[OS_PATHNAME_SIZE + 1]; +// decompile handling +int decomp; +void dump_bytecode(FILE *output); +int sbasic_compile(const char *file); +int sbasic_exec_prepare(const char *file); +int exec_close(int tid); + /* * remove temporary files * @@ -131,6 +138,7 @@ int setup_file(const char *program) { int process_options(int argc, char *argv[]) { int opt_ihavename = 0; int opt_nomore = 0; + decomp = 0; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { @@ -152,7 +160,8 @@ int process_options(int argc, char *argv[]) { case 's': // decompile - opt_decomp++; + decomp = 1; + opt_nosave = 1; break; case 'c': @@ -261,6 +270,52 @@ void *malloc(size_t size) { } #endif +void print_taskinfo(FILE *output) { + int prev_tid = 0; + + fprintf(output, "\n* task list:\n"); + for (int i = 0; i < count_tasks(); i++) { + prev_tid = activate_task(i); + fprintf(output, " id %d, child of %d, file %s, status %d\n", + ctask->tid, ctask->parent, ctask->file, ctask->status); + } + activate_task(prev_tid); +} + +void print_bytecode(int tid, FILE *output) { + int prev_tid = activate_task(tid); + fprintf(stderr, "%d %d %d\n", prev_tid, tid, count_tasks()); + + for (int i = 0; i < count_tasks(); i++) { + activate_task(i); + if (ctask->parent == tid) { + // do the same for the childs + print_bytecode(ctask->tid, output); + exit(1); + } + } + + activate_task(tid); + fprintf(output, "\n* task: %d/%d (%s)\n", ctask->tid, count_tasks(), prog_file); + dump_bytecode(output); + activate_task(prev_tid); +} + +void decompile() { + init_tasks(); + unit_mgr_init(); + sblmgr_init(0, NULL); + if (sbasic_compile(g_file)) { + int exec_tid = sbasic_exec_prepare(g_file); + print_taskinfo(stdout); + print_bytecode(exec_tid, stdout); + exec_close(exec_tid); + } + unit_mgr_close(); + sblmgr_close(); + destroy_tasks(); +} + /* * program entry point */ @@ -282,7 +337,11 @@ int main(int argc, char *argv[]) { char prev_cwd[OS_PATHNAME_SIZE + 1]; prev_cwd[0] = 0; getcwd(prev_cwd, sizeof(prev_cwd) - 1); - sbasic_main(g_file); + if (decomp) { + decompile(); + } else { + sbasic_main(g_file); + } chdir(prev_cwd); } else { show_brief_help();