From 56e44bb0a247f3817d86175e4573c9f665a0e8db Mon Sep 17 00:00:00 2001 From: chrisws Date: Sat, 8 Apr 2023 17:43:37 +0930 Subject: [PATCH 1/7] ANDROID: Fix regression with bundle build and plugin handling. --- src/platform/android/app/build.gradle | 10 +++++++++- .../java/net/sourceforge/smallbasic/MainActivity.java | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/platform/android/app/build.gradle b/src/platform/android/app/build.gradle index b3626390..b11f872e 100644 --- a/src/platform/android/app/build.gradle +++ b/src/platform/android/app/build.gradle @@ -9,7 +9,7 @@ android { applicationId 'net.sourceforge.smallbasic' minSdkVersion 16 targetSdkVersion 33 - versionCode 57 + versionCode 59 versionName '12.26' resConfigs 'en' } @@ -42,12 +42,20 @@ android { signingConfig signingConfigs.release } } + externalNativeBuild { ndkBuild { path '../jni/Android.mk' } } + namespace 'net.sourceforge.smallbasic' + + packagingOptions { + jniLibs { + useLegacyPackaging = true + } + } } dependencies { diff --git a/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/MainActivity.java b/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/MainActivity.java index 161648ac..f97e907d 100644 --- a/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/MainActivity.java +++ b/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/MainActivity.java @@ -319,8 +319,10 @@ public String getModulePath() { result = result.substring(0, lastSlash); } } else { + Log.i(TAG, "class loader is not BaseDexClassLoader"); result = ""; } + Log.i(TAG, "modulePath = " + result); return result; } From 774569428c4f0d8f192a21ebbb03aa57e434ce25 Mon Sep 17 00:00:00 2001 From: chrisws Date: Fri, 12 May 2023 18:25:38 +0930 Subject: [PATCH 2/7] CONSOLE: fix image save to array --- src/platform/console/image.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/console/image.cpp b/src/platform/console/image.cpp index 67c172a1..527a539d 100644 --- a/src/platform/console/image.cpp +++ b/src/platform/console/image.cpp @@ -405,6 +405,7 @@ void cmd_image_save(var_s *self, var_s *) { v_setint(v_elem(array, pos), px); } } + error = 0; break; default: v_init(&var); From c046bdf0684ccbb69f4d1aa22df44042eee2e2b4 Mon Sep 17 00:00:00 2001 From: chrisws Date: Fri, 12 May 2023 19:32:48 +0930 Subject: [PATCH 3/7] ANDROID: Fix download error when duplicate scratch.bas files --- ChangeLog | 4 ++++ configure.ac | 2 +- src/platform/android/Makefile.am | 3 ++- src/platform/android/app/build.gradle | 4 ++-- .../android/app/src/main/assets/main.bas | 2 +- .../net/sourceforge/smallbasic/WebServer.java | 18 ++++++++++++++++++ src/platform/android/build.gradle | 2 +- src/platform/android/gradle.properties | 3 +++ src/platform/android/webui/package.json | 12 ++++++------ 9 files changed, 38 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9ac1e3d..1a3e7f4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2023-05-12 (12.27) + CONSOLE: Fix image save + ANDROID: Fix download error when there are duplicate scratch.bas files + 2023-03-26 (12.26) ANDROID: Fix setenv error #187 ANDROID: update web UI dependencies diff --git a/configure.ac b/configure.ac index 38be9f8f..12bdc625 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ 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], [12.26]) +AC_INIT([smallbasic], [12.27]) AC_CONFIG_SRCDIR([configure.ac]) AC_CANONICAL_TARGET diff --git a/src/platform/android/Makefile.am b/src/platform/android/Makefile.am index b8d2c4a9..d37204d3 100644 --- a/src/platform/android/Makefile.am +++ b/src/platform/android/Makefile.am @@ -31,10 +31,11 @@ ndk-build-release: (cd jni && ${NDK}/ndk-build NDK_DEBUG=0) release: - (./gradlew clean assemble) + (./gradlew clean :app:bundle) library: (./gradlew clean assemble) (mkdir -p dist) (cp -R app/build/intermediates/stripped_native_libs/release/out/lib/ dist) (cp app/build/intermediates/dex/release/minifyReleaseWithR8/classes.dex dist) + diff --git a/src/platform/android/app/build.gradle b/src/platform/android/app/build.gradle index b11f872e..04d1a985 100644 --- a/src/platform/android/app/build.gradle +++ b/src/platform/android/app/build.gradle @@ -11,7 +11,7 @@ android { targetSdkVersion 33 versionCode 59 versionName '12.26' - resConfigs 'en' + resConfigs 'en' } signingConfigs { @@ -59,6 +59,6 @@ android { } dependencies { - implementation 'androidx.core:core:1.9.0' + implementation 'androidx.core:core:1.10.0' testImplementation 'junit:junit:4.13.2' } diff --git a/src/platform/android/app/src/main/assets/main.bas b/src/platform/android/app/src/main/assets/main.bas index d2250d07..605655f2 100644 --- a/src/platform/android/app/src/main/assets/main.bas +++ b/src/platform/android/app/src/main/assets/main.bas @@ -120,7 +120,7 @@ sub do_about() color colText print "Version "; sbver print - print "Copyright (c) 2002-2022 Chris Warren-Smith" + print "Copyright (c) 2002-2023 Chris Warren-Smith" print "Copyright (c) 1999-2006 Nicholas Christopoulos" + chr(10) local bn_home diff --git a/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/WebServer.java b/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/WebServer.java index 156dfc0f..e70e5dca 100644 --- a/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/WebServer.java +++ b/src/platform/android/app/src/main/java/net/sourceforge/smallbasic/WebServer.java @@ -17,9 +17,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.TimeZone; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -424,8 +426,24 @@ private Response handleDownload(Map> data) throws IOE // download multiple as zip ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); + Set fileNameSet = new HashSet<>(); for (String fileName : fileNames) { Response response = getFile(remoteHost, fileName, false); + // de-duplicate the fileName entry to avoid a duplicate entry/zip exception + int index = 1; + String originalName = fileName; + while (fileNameSet.contains(fileName)) { + int dot = originalName.lastIndexOf('.'); + if (dot != -1) { + String extension = originalName.substring(dot + 1); + String name = originalName.substring(0, dot); + fileName = String.format(Locale.ENGLISH, "%s (%d).%s", name, index, extension); + } else { + fileName = String.format(Locale.ENGLISH, "%s (%d)", originalName, index); + } + index++; + } + fileNameSet.add(fileName); ZipEntry entry = new ZipEntry(fileName); zipOutputStream.putNextEntry(entry); response.toStream(zipOutputStream); diff --git a/src/platform/android/build.gradle b/src/platform/android/build.gradle index 297bd6d6..7672e233 100644 --- a/src/platform/android/build.gradle +++ b/src/platform/android/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.0.1' } } diff --git a/src/platform/android/gradle.properties b/src/platform/android/gradle.properties index 9e6fce10..f6720ae0 100644 --- a/src/platform/android/gradle.properties +++ b/src/platform/android/gradle.properties @@ -9,7 +9,10 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. +android.defaults.buildfeatures.buildconfig=true android.enableJetifier=true +android.nonFinalResIds=false +android.nonTransitiveRClass=false android.useAndroidX=true org.gradle.jvmargs=-Xmx1536m diff --git a/src/platform/android/webui/package.json b/src/platform/android/webui/package.json index a87291a2..bc807ebb 100644 --- a/src/platform/android/webui/package.json +++ b/src/platform/android/webui/package.json @@ -4,12 +4,12 @@ "private": true, "proxy": "http://localhost:8080", "dependencies": { - "@emotion/react": "^11.10.6", - "@emotion/styled": "^11.10.6", - "@mui/icons-material": "^5.11.11", - "@mui/material": "^5.11.14", - "@mui/x-data-grid": "^6.0.2", - "npm-check-updates": "^16.8.0", + "@emotion/react": "^11.11.0", + "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.11.16", + "@mui/material": "^5.13.0", + "@mui/x-data-grid": "^6.3.1", + "npm-check-updates": "^16.10.12", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1" From 3e875307e5ff9ccdf74e7504dc997ea57b8d2bdd Mon Sep 17 00:00:00 2001 From: chrisws Date: Fri, 2 Jun 2023 20:47:52 +0930 Subject: [PATCH 4/7] PLUGINS: mechanism for cleaning up resources when out of scope --- src/common/hashmap.c | 2 ++ src/common/plugins.c | 15 +++++++++++++++ src/common/plugins.h | 5 +++++ src/common/var.c | 2 ++ src/common/var_map.c | 6 ++++++ src/include/module.h | 10 ++++++++++ src/include/var.h | 2 ++ src/lib/lodepng | 2 +- src/lib/miniaudio | 2 +- src/lib/stb | 2 +- 10 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/common/hashmap.c b/src/common/hashmap.c index 75c63f2f..863eaf67 100644 --- a/src/common/hashmap.c +++ b/src/common/hashmap.c @@ -126,6 +126,8 @@ void hashmap_create(var_p_t map, int size) { map->type = V_MAP; map->v.m.count = 0; map->v.m.id = -1; + map->v.m.lib_id = -1; + map->v.m.cls_id = -1; if (size == 0) { map->v.m.size = MAP_SIZE; } else { diff --git a/src/common/plugins.c b/src/common/plugins.c index 0cb7a44f..5dfddbdc 100644 --- a/src/common/plugins.c +++ b/src/common/plugins.c @@ -39,6 +39,7 @@ typedef int (*sblib_exec_fn)(int, int, slib_par_t *, var_t *); typedef int (*sblib_getname_fn) (int, char *); typedef int (*sblib_count_fn) (void); typedef int (*sblib_init_fn) (const char *); +typedef int (*sblib_free_fn)(int, int); typedef void (*sblib_close_fn) (void); typedef struct { @@ -47,6 +48,7 @@ typedef struct { void *_handle; sblib_exec_fn _sblib_proc_exec; sblib_exec_fn _sblib_func_exec; + sblib_free_fn _sblib_free; ext_func_node_t *_func_list; ext_proc_node_t *_proc_list; uint32_t _id; @@ -304,6 +306,7 @@ static void slib_import_routines(slib_t *lib, int comp) { lib->_sblib_func_exec = slib_getoptptr(lib, "sblib_func_exec"); lib->_sblib_proc_exec = slib_getoptptr(lib, "sblib_proc_exec"); + lib->_sblib_free = slib_getoptptr(lib, "sblib_free"); sblib_count_fn fcount = slib_getoptptr(lib, "sblib_proc_count"); sblib_getname_fn fgetname = slib_getoptptr(lib, "sblib_proc_getname"); @@ -471,6 +474,10 @@ static int slib_exec(slib_t *lib, var_t *ret, int index, int proc) { free(ptable); } + if (success && v_is_type(ret, V_MAP)) { + ret->v.m.lib_id = lib->_id; + } + return success; } @@ -598,6 +605,13 @@ int plugin_funcexec(int lib_id, int index, var_t *ret) { return result; } +void plugin_free(int lib_id, int cls_id, int id) { + slib_t *lib = get_lib(lib_id); + if (lib && lib->_sblib_free) { + lib->_sblib_free(cls_id, id); + } +} + void plugin_close() { for (int i = 0; i < MAX_SLIBS; i++) { if (plugins[i]) { @@ -626,5 +640,6 @@ int plugin_get_kid(int lib_id, const char *keyword) { return -1; } void *plugin_get_func(const char *name) { return 0; } int plugin_procexec(int lib_id, int index) { return -1; } int plugin_funcexec(int lib_id, int index, var_t *ret) { return -1; } +void plugin_free(int lib_id, int cls_id, int id) {} void plugin_close() {} #endif diff --git a/src/common/plugins.h b/src/common/plugins.h index 0496f5cf..a4dd16bd 100644 --- a/src/common/plugins.h +++ b/src/common/plugins.h @@ -55,6 +55,11 @@ int plugin_procexec(int lib_id, int index); // int plugin_funcexec(int lib_id, int index, var_t *ret); +// +// cleanup any resources held against the map data +// +void plugin_free(int lib_id, int cls_id, int id); + // // closes the plugin system // diff --git a/src/common/var.c b/src/common/var.c index 17929539..64f9e679 100644 --- a/src/common/var.c +++ b/src/common/var.c @@ -565,6 +565,8 @@ void v_move(var_t *dest, const var_t *src) { dest->v.m.count = src->v.m.count; dest->v.m.size = src->v.m.size; dest->v.m.id = src->v.m.id; + dest->v.m.lib_id = src->v.m.lib_id; + dest->v.m.cls_id = src->v.m.cls_id; break; case V_REF: dest->v.ref = src->v.ref; diff --git a/src/common/var_map.c b/src/common/var_map.c index 37bb263b..240b2b04 100644 --- a/src/common/var_map.c +++ b/src/common/var_map.c @@ -11,6 +11,7 @@ #include "common/sys.h" #include "common/pproc.h" #include "common/hashmap.h" +#include "common/plugins.h" #include "include/var_map.h" #define BUFFER_GROW_SIZE 64 @@ -170,6 +171,9 @@ var_p_t map_elem_key(const var_p_t var_p, int index) { */ void map_free(var_p_t var_p) { if (var_p->type == V_MAP) { + if (var_p->v.m.lib_id != -1 && var_p->v.m.cls_id != -1 && var_p->v.m.id != -1) { + plugin_free(var_p->v.m.lib_id, var_p->v.m.cls_id, var_p->v.m.id); + } hashmap_destroy(var_p); v_init(var_p); } @@ -291,6 +295,8 @@ void map_set(var_p_t dest, const var_p_t src) { hashmap_foreach(src, map_set_cb, &cb); dest->v.m.count = src->v.m.count; dest->v.m.id = src->v.m.id; + dest->v.m.lib_id = src->v.m.lib_id; + dest->v.m.cls_id = src->v.m.cls_id; } } diff --git a/src/include/module.h b/src/include/module.h index 1618f3e6..451e24e2 100644 --- a/src/include/module.h +++ b/src/include/module.h @@ -116,6 +116,16 @@ int sblib_func_getname(int index, char *func_name); */ int sblib_func_exec(int index, int param_count, slib_par_t *params, var_t *retval); +/** + * @ingroup modlib + * + * executes a function + * + * @param cls_id the variable class identifier + * @param id the variable instance identifier + */ +void sblib_free(int cls_id, int id); + /** * @ingroup modlib * diff --git a/src/include/var.h b/src/include/var.h index ac08b566..437202c5 100644 --- a/src/include/var.h +++ b/src/include/var.h @@ -72,6 +72,8 @@ typedef struct var_s { uint32_t count; uint32_t size; uint32_t id; + uint32_t lib_id; + uint32_t cls_id; } m; // reference variable diff --git a/src/lib/lodepng b/src/lib/lodepng index 997936fd..c18b949b 160000 --- a/src/lib/lodepng +++ b/src/lib/lodepng @@ -1 +1 @@ -Subproject commit 997936fd2b45842031e4180d73d7880e381cf33f +Subproject commit c18b949b71f45e78b1f9a28c5d458bce0da505d6 diff --git a/src/lib/miniaudio b/src/lib/miniaudio index c153a947..ea205fb7 160000 --- a/src/lib/miniaudio +++ b/src/lib/miniaudio @@ -1 +1 @@ -Subproject commit c153a947919808419b0bf3f56b6f2ee606d6c5f4 +Subproject commit ea205fb7b0b63613f7586a4082ec9c42a0381920 diff --git a/src/lib/stb b/src/lib/stb index 8b5f1f37..5736b15f 160000 --- a/src/lib/stb +++ b/src/lib/stb @@ -1 +1 @@ -Subproject commit 8b5f1f37b5b75829fc72d38e7b5d4bcbf8a26d55 +Subproject commit 5736b15f7ea0ffb08dd38af21067c314d6a3aae9 From 627622d2ad34237a1ffd27c00f211e87f5dc2b53 Mon Sep 17 00:00:00 2001 From: chrisws Date: Wed, 14 Jun 2023 20:12:46 +0930 Subject: [PATCH 5/7] PLUGINS: mechanism for cleaning up resources when out of scope --- src/common/hashmap.c | 1 + src/common/plugins.c | 3 ++- src/common/var.c | 1 + src/common/var_map.c | 6 +++++- src/include/var.h | 2 ++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/common/hashmap.c b/src/common/hashmap.c index 863eaf67..9349700b 100644 --- a/src/common/hashmap.c +++ b/src/common/hashmap.c @@ -128,6 +128,7 @@ void hashmap_create(var_p_t map, int size) { map->v.m.id = -1; map->v.m.lib_id = -1; map->v.m.cls_id = -1; + map->v.m.ref = -1; if (size == 0) { map->v.m.size = MAP_SIZE; } else { diff --git a/src/common/plugins.c b/src/common/plugins.c index 5dfddbdc..140965b5 100644 --- a/src/common/plugins.c +++ b/src/common/plugins.c @@ -39,7 +39,7 @@ typedef int (*sblib_exec_fn)(int, int, slib_par_t *, var_t *); typedef int (*sblib_getname_fn) (int, char *); typedef int (*sblib_count_fn) (void); typedef int (*sblib_init_fn) (const char *); -typedef int (*sblib_free_fn)(int, int); +typedef int (*sblib_free_fn) (int, int); typedef void (*sblib_close_fn) (void); typedef struct { @@ -476,6 +476,7 @@ static int slib_exec(slib_t *lib, var_t *ret, int index, int proc) { if (success && v_is_type(ret, V_MAP)) { ret->v.m.lib_id = lib->_id; + ret->v.m.ref = 1; } return success; diff --git a/src/common/var.c b/src/common/var.c index 64f9e679..6fb426c8 100644 --- a/src/common/var.c +++ b/src/common/var.c @@ -567,6 +567,7 @@ void v_move(var_t *dest, const var_t *src) { dest->v.m.id = src->v.m.id; dest->v.m.lib_id = src->v.m.lib_id; dest->v.m.cls_id = src->v.m.cls_id; + dest->v.m.ref = src->v.m.ref; break; case V_REF: dest->v.ref = src->v.ref; diff --git a/src/common/var_map.c b/src/common/var_map.c index 240b2b04..86f7d9fd 100644 --- a/src/common/var_map.c +++ b/src/common/var_map.c @@ -171,7 +171,10 @@ var_p_t map_elem_key(const var_p_t var_p, int index) { */ void map_free(var_p_t var_p) { if (var_p->type == V_MAP) { - if (var_p->v.m.lib_id != -1 && var_p->v.m.cls_id != -1 && var_p->v.m.id != -1) { + if (var_p->v.m.lib_id != -1 && + var_p->v.m.cls_id != -1 && + var_p->v.m.id != -1 && + --var_p->v.m.ref == 0) { plugin_free(var_p->v.m.lib_id, var_p->v.m.cls_id, var_p->v.m.id); } hashmap_destroy(var_p); @@ -297,6 +300,7 @@ void map_set(var_p_t dest, const var_p_t src) { dest->v.m.id = src->v.m.id; dest->v.m.lib_id = src->v.m.lib_id; dest->v.m.cls_id = src->v.m.cls_id; + dest->v.m.ref = src->v.m.ref + 1; } } diff --git a/src/include/var.h b/src/include/var.h index 437202c5..afacb6fc 100644 --- a/src/include/var.h +++ b/src/include/var.h @@ -69,11 +69,13 @@ typedef struct var_s { struct { // pointer the map structure void *map; + uint32_t count; uint32_t size; uint32_t id; uint32_t lib_id; uint32_t cls_id; + uint32_t ref; } m; // reference variable From 82467d8d2b289e082e3b8995297ed6fe28ec379f Mon Sep 17 00:00:00 2001 From: chrisws Date: Sat, 17 Jun 2023 19:54:32 +0930 Subject: [PATCH 6/7] PLUGINS: mechanism for cleaning up resources when out of scope --- src/common/hashmap.c | 1 - src/common/plugins.c | 3 +- src/common/var.c | 2 +- src/common/var_map.c | 201 +++++++++++++++++++++++------------------- src/include/var.h | 8 +- src/include/var_map.h | 1 + 6 files changed, 118 insertions(+), 98 deletions(-) diff --git a/src/common/hashmap.c b/src/common/hashmap.c index 9349700b..863eaf67 100644 --- a/src/common/hashmap.c +++ b/src/common/hashmap.c @@ -128,7 +128,6 @@ void hashmap_create(var_p_t map, int size) { map->v.m.id = -1; map->v.m.lib_id = -1; map->v.m.cls_id = -1; - map->v.m.ref = -1; if (size == 0) { map->v.m.size = MAP_SIZE; } else { diff --git a/src/common/plugins.c b/src/common/plugins.c index 140965b5..0e5159b3 100644 --- a/src/common/plugins.c +++ b/src/common/plugins.c @@ -475,8 +475,7 @@ static int slib_exec(slib_t *lib, var_t *ret, int index, int proc) { } if (success && v_is_type(ret, V_MAP)) { - ret->v.m.lib_id = lib->_id; - ret->v.m.ref = 1; + map_set_lib_id(ret, lib->_id); } return success; diff --git a/src/common/var.c b/src/common/var.c index 6fb426c8..05017773 100644 --- a/src/common/var.c +++ b/src/common/var.c @@ -555,6 +555,7 @@ void v_move(var_t *dest, const var_t *src) { break; case V_ARRAY: memcpy(&dest->v.a, &src->v.a, sizeof(src->v.a)); + v_maxdim(dest) = v_maxdim(src); break; case V_PTR: dest->v.ap.p = src->v.ap.p; @@ -567,7 +568,6 @@ void v_move(var_t *dest, const var_t *src) { dest->v.m.id = src->v.m.id; dest->v.m.lib_id = src->v.m.lib_id; dest->v.m.cls_id = src->v.m.cls_id; - dest->v.m.ref = src->v.m.ref; break; case V_REF: dest->v.ref = src->v.ref; diff --git a/src/common/var_map.c b/src/common/var_map.c index 86f7d9fd..af330924 100644 --- a/src/common/var_map.c +++ b/src/common/var_map.c @@ -21,9 +21,9 @@ #include "lib/jsmn/jsmn.h" -/** - * Container for map_from_str - */ +// +// Container for map_from_str +// typedef struct JsonTokens { const char *js; jsmntok_t *tokens; @@ -43,42 +43,42 @@ typedef struct ArrayList { ArrayNode *tail; } ArrayList; -/** - * Process the next token - */ +// +// Process the next token +// int map_read_next_token(var_p_t dest, JsonTokens *json, int index); -/** - * initialise the variable as a map - */ +// +// initialise the variable as a map +// void map_init(var_p_t map) { hashmap_create(map, 0); } -/** - * Compare one MAP to another. see v_compare comments for return spec. - */ +// +// Compare one MAP to another. see v_compare comments for return spec. +// int map_compare(const var_p_t var_a, const var_p_t var_b) { return 0; } -/** - * Return true if the structure is empty - */ +// +// Return true if the structure is empty +// int map_is_empty(const var_p_t var_p) { return (var_p->v.m.map == NULL); } -/** - * Return the contents of the structure as an integer - */ +// +// Return the contents of the structure as an integer +// int map_to_int(const var_p_t var_p) { return map_length(var_p); } -/** - * Return the number of elements - */ +// +// Return the number of elements +// int map_length(const var_p_t var_p) { int result; if (var_p->type == V_MAP) { @@ -134,9 +134,9 @@ const char *map_get_str(var_p_t base, const char *name) { return result; } -/** - * return the element at the nth position - */ +// +// return the element at the nth position +// int map_elem_cb(hashmap_cb *cb, var_p_t key, var_p_t value) { int result; if (cb->count++ == cb->index) { @@ -148,9 +148,9 @@ int map_elem_cb(hashmap_cb *cb, var_p_t key, var_p_t value) { return result; } -/** - * return the element key at the nth position - */ +// +// return the element key at the nth position +// var_p_t map_elem_key(const var_p_t var_p, int index) { var_p_t result; if (var_p->type == V_MAP) { @@ -166,15 +166,14 @@ var_p_t map_elem_key(const var_p_t var_p, int index) { return result; } -/** - * Free the map data - */ +// +// Free the map data +// void map_free(var_p_t var_p) { if (var_p->type == V_MAP) { if (var_p->v.m.lib_id != -1 && var_p->v.m.cls_id != -1 && - var_p->v.m.id != -1 && - --var_p->v.m.ref == 0) { + var_p->v.m.id != -1) { plugin_free(var_p->v.m.lib_id, var_p->v.m.cls_id, var_p->v.m.id); } hashmap_destroy(var_p); @@ -182,12 +181,33 @@ void map_free(var_p_t var_p) { } } -/** - * Returns the final element eg z in foo.x.y.z - * - * Scan byte code for node kwTYPE_UDS_EL and attach as field elements - * if they don't already exist. - */ +// +// callback for map_set_lib_id +// +int map_set_lib_id_cb(hashmap_cb *cb, var_p_t key, var_p_t value) { + if (v_is_type(value, V_MAP)) { + value->v.m.lib_id = cb->index; + } + return 0; +} + +// +// sets the library-id onto the map parent and direct children +// +void map_set_lib_id(var_p_t var_p, int lib_id) { + if (v_is_type(var_p, V_MAP)) { + hashmap_cb cb; + var_p->v.m.lib_id = lib_id; + cb.index = lib_id; + hashmap_foreach(var_p, map_set_lib_id_cb, &cb); + } +} + +// +// Returns the final element eg z in foo.x.y.z +// Scan byte code for node kwTYPE_UDS_EL and attach as field elements +// if they don't already exist. +// var_p_t map_resolve_fields(var_p_t base, var_p_t *parent) { var_p_t field = NULL; if (code_peek() == kwTYPE_UDS_EL) { @@ -228,9 +248,9 @@ var_p_t map_resolve_fields(var_p_t base, var_p_t *parent) { return field; } -/** - * Adds a new variable onto the map - */ +// +// Adds a new variable onto the map +// var_p_t map_add_var(var_p_t base, const char *name, int value) { var_p_t key = v_new(); v_setstr(key, name); @@ -239,10 +259,10 @@ var_p_t map_add_var(var_p_t base, const char *name, int value) { return var; } -/** - * Return the variable in base keyed by key, if not found then creates - * an empty variable that will be returned in a further call - */ +// +// Return the variable in base keyed by key, if not found then creates +// 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 && v_asize(base)) { // convert the non-empty array to a map @@ -274,9 +294,9 @@ void map_get_value(var_p_t base, var_p_t var_key, var_p_t *result) { *result = hashmap_put(base, var_key->v.p.ptr, v_strlen(var_key)); } -/** - * Traverse the root to copy into dest - */ +// +// Traverse the root to copy into dest +// int map_set_cb(hashmap_cb *cb, var_p_t var_key, var_p_t value) { if (var_key->type != V_STR || var_key->v.p.ptr[0] != MAP_TMP_FIELD[0]) { var_p_t key = v_new(); @@ -287,9 +307,9 @@ int map_set_cb(hashmap_cb *cb, var_p_t var_key, var_p_t value) { return 0; } -/** - * Copy values from one structure to another - */ +// +// Copy values from one structure to another +// void map_set(var_p_t dest, const var_p_t src) { if (dest != src && src->type == V_MAP) { hashmap_cb cb; @@ -298,9 +318,8 @@ void map_set(var_p_t dest, const var_p_t src) { hashmap_foreach(src, map_set_cb, &cb); dest->v.m.count = src->v.m.count; dest->v.m.id = src->v.m.id; - dest->v.m.lib_id = src->v.m.lib_id; - dest->v.m.cls_id = src->v.m.cls_id; - dest->v.m.ref = src->v.m.ref + 1; + dest->v.m.lib_id = -1; + dest->v.m.cls_id = -1; } } @@ -313,9 +332,9 @@ void map_set_int(var_p_t base, const char *name, var_int_t n) { } } -/** - * Helper for map_to_str - */ +// +// Helper for map_to_str +// int map_to_str_cb(hashmap_cb *cb, var_p_t v_key, var_p_t v_var) { char *key = v_str(v_key); char *value = v_str(v_var); @@ -344,9 +363,9 @@ int map_to_str_cb(hashmap_cb *cb, var_p_t v_key, var_p_t v_var) { return 0; } -/** - * Print the array element, growing the buffer as needed - */ +// +// Print the array element, growing the buffer as needed +// void array_append_elem(hashmap_cb *cb, var_t *elem) { char *value = v_str(elem); int required = strlen(cb->buffer) + strlen(value) + BUFFER_PADDING; @@ -358,9 +377,9 @@ void array_append_elem(hashmap_cb *cb, var_t *elem) { free(value); } -/** - * print the array variable - */ +// +// print the array variable +// void array_to_str(hashmap_cb *cb, var_t *var) { strcpy(cb->buffer, "["); if (v_maxdim(var) == 2) { @@ -393,9 +412,9 @@ void array_to_str(hashmap_cb *cb, var_t *var) { strcat(cb->buffer, "]"); } -/** - * Return the contents of the structure as a string - */ +// +// Return the contents of the structure as a string +// char *map_to_str(const var_p_t var_p) { hashmap_cb cb; cb.count = BUFFER_GROW_SIZE; @@ -412,9 +431,9 @@ char *map_to_str(const var_p_t var_p) { return cb.buffer; } -/** - * Print the contents of the structure - */ +// +// Print the contents of the structure +// 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); @@ -423,9 +442,9 @@ void map_write(const var_p_t var_p, int method, intptr_t handle) { } } -/** - * Process the next primative value - */ +// +// Process the next primative value +// void map_set_primative(var_p_t dest, const char *s, int len) { int value = 0; int fract = 0; @@ -458,9 +477,9 @@ void map_set_primative(var_p_t dest, const char *s, int len) { } } -/** - * Adds a node to the array list - */ +// +// Adds a node to the array list +// var_t *map_array_list_add(ArrayList *list, int row, int col) { if (list->head == NULL) { list->head = malloc(sizeof(ArrayNode)); @@ -476,9 +495,9 @@ var_t *map_array_list_add(ArrayList *list, int row, int col) { return list->tail->v; } -/** - * Builds the array from the ArrayNode list - */ +// +// Builds the array from the ArrayNode list +// void map_build_array(var_p_t dest, ArrayNode *node_next, int rows, int cols) { if (rows > 1) { v_tomatrix(dest, rows, cols); @@ -496,9 +515,9 @@ void map_build_array(var_p_t dest, ArrayNode *node_next, int rows, int cols) { } } -/** - * Creates an array variable - */ +// +// Creates an array variable +// int map_create_array(var_p_t dest, JsonTokens *json, int end_position, int index) { int i = index; int rows = 0; @@ -558,9 +577,9 @@ int map_create_array(var_p_t dest, JsonTokens *json, int end_position, int index return i; } -/** - * Creates a map variable - */ +// +// Creates a map variable +// int map_create(var_p_t dest, JsonTokens *json, int end_position, int index) { hashmap_create(dest, 0); int i = index; @@ -581,9 +600,9 @@ int map_create(var_p_t dest, JsonTokens *json, int end_position, int index) { return i; } -/** - * Process the next token - */ +// +// Process the next token +// int map_read_next_token(var_p_t dest, JsonTokens *json, int index) { int next; jsmntok_t token = json->tokens[index]; @@ -636,9 +655,9 @@ void map_parse_str(const char *js, size_t len, var_p_t dest) { free(tokens); } -/** - * Initialise a map from a string - */ +// +// Initialise a map from a string +// void map_from_str(var_p_t dest) { var_t arg; v_init(&arg); @@ -653,8 +672,10 @@ void map_from_str(var_p_t dest) { v_free(&arg); } +// // array <- CODEARRAY(x1,y1...[;x2,y2...]) // dynamic arrays created with the [] operators +// void map_from_codearray(var_p_t dest) { int rows = 0; int cols = 0; diff --git a/src/include/var.h b/src/include/var.h index afacb6fc..003e7949 100644 --- a/src/include/var.h +++ b/src/include/var.h @@ -75,7 +75,6 @@ typedef struct var_s { uint32_t id; uint32_t lib_id; uint32_t cls_id; - uint32_t ref; } m; // reference variable @@ -104,14 +103,15 @@ typedef struct var_s { // upper and lower bounds int32_t ubound[MAXDIM]; int32_t lbound[MAXDIM]; - // number of dimensions - uint8_t maxdim; } a; // next item in the free-list struct var_s *pool_next; } v; + // number of dimensions + uint8_t maxdim; + // variables type uint8_t type; @@ -426,7 +426,7 @@ void v_input2var(const char *str, var_t *var); * < the number of array dimensions (x) * @ingroup var */ -#define v_maxdim(x) ((x)->v.a.maxdim) +#define v_maxdim(x) ((x)->maxdim) /** * < the array lower bound of the given dimension (x) diff --git a/src/include/var_map.h b/src/include/var_map.h index a15853d7..eee18223 100644 --- a/src/include/var_map.h +++ b/src/include/var_map.h @@ -34,6 +34,7 @@ void map_free(var_p_t var_p); 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); +void map_set_lib_id(var_p_t var_p, int lib_id); char *map_to_str(const var_p_t var_p); 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); From e2413b1dc5dfaae51e2a5fbf40cf2a8685752dc6 Mon Sep 17 00:00:00 2001 From: chrisws Date: Sun, 18 Jun 2023 13:48:34 +0930 Subject: [PATCH 7/7] COMMON: Fix redim regression --- ChangeLog | 4 ++++ samples/distro-examples/tests/array.bas | 11 +++++++++++ src/common/blib.c | 2 -- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a3e7f4d..82fc06d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2023-06-18 (12.27) + COMMON: Fix redim regression + PLUGINS: Added mechanism for cleaning up resources when the associated map falls out of scope + 2023-05-12 (12.27) CONSOLE: Fix image save ANDROID: Fix download error when there are duplicate scratch.bas files diff --git a/samples/distro-examples/tests/array.bas b/samples/distro-examples/tests/array.bas index 92da8153..4a99d836 100644 --- a/samples/distro-examples/tests/array.bas +++ b/samples/distro-examples/tests/array.bas @@ -426,4 +426,15 @@ p(asc("|")) = 1 p(asc("}")) = 1 p(asc("~")) = 1 +' +' https://www.syntaxbomb.com/smallbasic/redim-why-to-keep-old-versons/ +' +a = [0,1,2,3,4,5,6,7,8,9,10,11] +redim a(11) : if a != [0,1,2,3,4,5,6,7,8,9,10,11] then throw str(a) +redim a(1, 11) : if a != [0,1,2,3,4,5,6,7,8,9,10,11;0,0,0,0,0,0,0,0,0,0,0,0] then throw str(a) +redim a(2, 10) : if a != [0,1,2,3,4,5,6,7,8,9,10;11,0,0,0,0,0,0,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0] then throw str(a) +redim a(1, 11) : if a != [0,1,2,3,4,5,6,7,8,9,10,11;0,0,0,0,0,0,0,0,0,0,0,0] then throw str(a) +redim a(10) : if a != [0,1,2,3,4,5,6,7,8,9,10] then throw str(a) +redim a(0 to 7): if a != [0,1,2,3,4,5,6,7] then throw str(a) +redim a(0 to 1): if a != [0,1] then throw str(a) diff --git a/src/common/blib.c b/src/common/blib.c index 13c2ea28..6902ab94 100644 --- a/src/common/blib.c +++ b/src/common/blib.c @@ -210,8 +210,6 @@ void cmd_dim(int preserve) { } if (!preserve || var_p->type != V_ARRAY) { v_new_array(var_p, size); - } else if (v_maxdim(var_p) != dimensions) { - err_matdim(); } else { // preserve previous array contents v_resize_array(var_p, size);