mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-08 11:26:31 +00:00
Berry add solidification of strings longer than 255 bytes (#20529)
This commit is contained in:
parent
0f541a963b
commit
a2c4123d79
@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- LVGL option to add `lv.keyboard` extra widget (#20496)
|
- LVGL option to add `lv.keyboard` extra widget (#20496)
|
||||||
- GUI sensor separators (#20495)
|
- GUI sensor separators (#20495)
|
||||||
- Command ``TimedPower<index> <milliseconds>[,ON|OFF|TOGGLE|BLINK]`` executes ``Power<index> [ON|OFF|TOGGLE|BLINK] `` and after <millisecond> executes ``Power<index> [OFF|ON|TOGGLE|OFF]``
|
- Command ``TimedPower<index> <milliseconds>[,ON|OFF|TOGGLE|BLINK]`` executes ``Power<index> [ON|OFF|TOGGLE|BLINK] `` and after <millisecond> executes ``Power<index> [OFF|ON|TOGGLE|OFF]``
|
||||||
|
- Berry add solidification of strings longer than 255 bytes
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -262,6 +262,13 @@ const bntvmodule_t be_native_module(_module) = { \
|
|||||||
BE_STRING \
|
BE_STRING \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* variant for long strings that does not trigger strtab */
|
||||||
|
#define be_nested_str_long(_name_) \
|
||||||
|
{ \
|
||||||
|
{ .s=((bstring*)&be_const_str_##_name_) }, \
|
||||||
|
BE_STRING \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_nested_str_literal(_name_) \
|
#define be_nested_str_literal(_name_) \
|
||||||
{ \
|
{ \
|
||||||
{ .s=(be_nested_const_str(_name_, _hash, sizeof(_name_)-1 ))\
|
{ .s=(be_nested_const_str(_name_, _hash, sizeof(_name_)-1 ))\
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "be_vm.h"
|
#include "be_vm.h"
|
||||||
#include "be_decoder.h"
|
#include "be_decoder.h"
|
||||||
#include "be_sys.h"
|
#include "be_sys.h"
|
||||||
|
#include "be_mem.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -45,6 +46,16 @@ extern const bclass be_class_map;
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/* minimal version without formatting and without size limit */
|
||||||
|
#define lognofmt(__s) \
|
||||||
|
do { \
|
||||||
|
if (fout) { \
|
||||||
|
be_fwrite(fout, __s, strlen(__s)); \
|
||||||
|
} else { \
|
||||||
|
be_writestring(__s); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
* Encode string to identifiers
|
* Encode string to identifiers
|
||||||
*
|
*
|
||||||
@ -200,17 +211,29 @@ static void m_solidify_bvalue(bvm *vm, bbool str_literal, bvalue * value, const
|
|||||||
{
|
{
|
||||||
const char * str = str(var_tostr(value));
|
const char * str = str(var_tostr(value));
|
||||||
size_t len = strlen(str);
|
size_t len = strlen(str);
|
||||||
if (len >= 255) {
|
|
||||||
be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet");
|
|
||||||
}
|
|
||||||
size_t id_len = toidentifier_length(str);
|
size_t id_len = toidentifier_length(str);
|
||||||
char id_buf[id_len];
|
char id_buf_stack[64];
|
||||||
|
char *id_buf = id_buf_stack;
|
||||||
|
if (id_len >= 64) {
|
||||||
|
id_buf = be_os_malloc(id_len);
|
||||||
|
if (!id_buf) {
|
||||||
|
be_raise(vm, "memory_error", "could not allocated buffer");
|
||||||
|
}
|
||||||
|
}
|
||||||
toidentifier(id_buf, str);
|
toidentifier(id_buf, str);
|
||||||
if (!str_literal) {
|
if (len >= 255) {
|
||||||
|
/* decompose to avoid any size limit */
|
||||||
|
lognofmt("be_nested_str_long(");
|
||||||
|
lognofmt(id_buf);
|
||||||
|
lognofmt(")");
|
||||||
|
} else if (!str_literal) {
|
||||||
logfmt("be_nested_str(%s)", id_buf);
|
logfmt("be_nested_str(%s)", id_buf);
|
||||||
} else {
|
} else {
|
||||||
logfmt("be_nested_str_weak(%s)", id_buf);
|
logfmt("be_nested_str_weak(%s)", id_buf);
|
||||||
}
|
}
|
||||||
|
if (id_buf != id_buf_stack) {
|
||||||
|
be_os_free(id_buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BE_CLOSURE:
|
case BE_CLOSURE:
|
||||||
|
@ -27,6 +27,17 @@
|
|||||||
.s = _s \
|
.s = _s \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define be_define_const_str_long(_name, _s, _len) \
|
||||||
|
BERRY_LOCAL const bclstring be_const_str_##_name = { \
|
||||||
|
.next = (bgcobject *)NULL, \
|
||||||
|
.type = BE_STRING, \
|
||||||
|
.marked = GC_CONST, \
|
||||||
|
.extra = 0, \
|
||||||
|
.slen = 255, \
|
||||||
|
.llen = _len, \
|
||||||
|
.s = _s \
|
||||||
|
}
|
||||||
|
|
||||||
/* const string table */
|
/* const string table */
|
||||||
struct bconststrtab {
|
struct bconststrtab {
|
||||||
const bstring* const *table;
|
const bstring* const *table;
|
||||||
@ -279,7 +290,7 @@ void be_gcstrtab(bvm *vm)
|
|||||||
|
|
||||||
uint32_t be_strhash(const bstring *s)
|
uint32_t be_strhash(const bstring *s)
|
||||||
{
|
{
|
||||||
if (gc_isconst(s)) {
|
if (gc_isconst(s) && (s->slen != 255)) {
|
||||||
bcstring* cs = cast(bcstring*, s);
|
bcstring* cs = cast(bcstring*, s);
|
||||||
if (cs->hash) { /* if hash is null we need to compute it */
|
if (cs->hash) { /* if hash is null we need to compute it */
|
||||||
return cs->hash;
|
return cs->hash;
|
||||||
@ -298,12 +309,12 @@ uint32_t be_strhash(const bstring *s)
|
|||||||
const char* be_str2cstr(const bstring *s)
|
const char* be_str2cstr(const bstring *s)
|
||||||
{
|
{
|
||||||
be_assert(cast_str(s) != NULL);
|
be_assert(cast_str(s) != NULL);
|
||||||
if (gc_isconst(s)) {
|
|
||||||
return cstr(s);
|
|
||||||
}
|
|
||||||
if (s->slen == 255) {
|
if (s->slen == 255) {
|
||||||
return lstr(s);
|
return lstr(s);
|
||||||
}
|
}
|
||||||
|
if (gc_isconst(s)) {
|
||||||
|
return cstr(s);
|
||||||
|
}
|
||||||
return sstr(s);
|
return sstr(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,12 @@ typedef struct {
|
|||||||
/* char s[]; */
|
/* char s[]; */
|
||||||
} blstring;
|
} blstring;
|
||||||
|
|
||||||
|
typedef struct { /* const long string */
|
||||||
|
bstring_header;
|
||||||
|
int llen;
|
||||||
|
char s[];
|
||||||
|
} bclstring;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bstring_header;
|
bstring_header;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
@ -23,6 +23,7 @@ class block_builder:
|
|||||||
self.block = block()
|
self.block = block()
|
||||||
self.strtab = []
|
self.strtab = []
|
||||||
self.strtab_weak = []
|
self.strtab_weak = []
|
||||||
|
self.strtab_long = []
|
||||||
|
|
||||||
self.block.name = obj.name
|
self.block.name = obj.name
|
||||||
if depend(obj, macro):
|
if depend(obj, macro):
|
||||||
|
@ -19,6 +19,7 @@ class builder:
|
|||||||
self.macro = None
|
self.macro = None
|
||||||
self.strmap = {}
|
self.strmap = {}
|
||||||
self.strmap_weak = {}
|
self.strmap_weak = {}
|
||||||
|
self.strmap_long = {}
|
||||||
|
|
||||||
self.macro = macro_table()
|
self.macro = macro_table()
|
||||||
for path in self.config:
|
for path in self.config:
|
||||||
@ -27,7 +28,7 @@ class builder:
|
|||||||
for d in self.input:
|
for d in self.input:
|
||||||
self.scandir(d)
|
self.scandir(d)
|
||||||
|
|
||||||
sb = str_build(self.strmap, self.strmap_weak)
|
sb = str_build(self.strmap, self.strmap_weak, self.strmap_long)
|
||||||
sb.build(self.output)
|
sb.build(self.output)
|
||||||
|
|
||||||
def parse_file(self, filename):
|
def parse_file(self, filename):
|
||||||
@ -42,12 +43,16 @@ class builder:
|
|||||||
self.strmap[s] = 0
|
self.strmap[s] = 0
|
||||||
for s in parser.strtab_weak:
|
for s in parser.strtab_weak:
|
||||||
self.strmap_weak[s] = 0
|
self.strmap_weak[s] = 0
|
||||||
|
for s in parser.strtab_long:
|
||||||
|
self.strmap_long[s] = 0
|
||||||
for obj in parser.objects:
|
for obj in parser.objects:
|
||||||
builder = block_builder(obj, self.macro)
|
builder = block_builder(obj, self.macro)
|
||||||
for s in builder.strtab:
|
for s in builder.strtab:
|
||||||
self.strmap[s] = 0
|
self.strmap[s] = 0
|
||||||
for s in builder.strtab_weak:
|
for s in builder.strtab_weak:
|
||||||
self.strmap_weak[s] = 0
|
self.strmap_weak[s] = 0
|
||||||
|
for s in builder.strtab_long:
|
||||||
|
self.strmap_long[s] = 0
|
||||||
builder.dumpfile(self.output)
|
builder.dumpfile(self.output)
|
||||||
|
|
||||||
def scandir(self, srcpath):
|
def scandir(self, srcpath):
|
||||||
|
@ -22,6 +22,7 @@ class coc_parser:
|
|||||||
self.objects = []
|
self.objects = []
|
||||||
self.strtab = set()
|
self.strtab = set()
|
||||||
self.strtab_weak = set()
|
self.strtab_weak = set()
|
||||||
|
self.strtab_long = set()
|
||||||
self.text = text
|
self.text = text
|
||||||
self.parsers = {
|
self.parsers = {
|
||||||
"@const_object_info_begin": self.parse_object,
|
"@const_object_info_begin": self.parse_object,
|
||||||
@ -30,6 +31,7 @@ class coc_parser:
|
|||||||
"be_nested_str(": self.parse_string,
|
"be_nested_str(": self.parse_string,
|
||||||
"be_const_key_weak(": self.parse_string_weak,
|
"be_const_key_weak(": self.parse_string_weak,
|
||||||
"be_nested_str_weak(": self.parse_string_weak,
|
"be_nested_str_weak(": self.parse_string_weak,
|
||||||
|
"be_nested_str_long(": self.parse_string_long,
|
||||||
"be_str_weak(": self.parse_string_weak,
|
"be_str_weak(": self.parse_string_weak,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +133,13 @@ class coc_parser:
|
|||||||
self.strtab_weak.add(literal)
|
self.strtab_weak.add(literal)
|
||||||
# print(f"str '{ident}' -> {literal}")
|
# print(f"str '{ident}' -> {literal}")
|
||||||
|
|
||||||
|
def parse_string_long(self):
|
||||||
|
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||||
|
ident = self.parse_word()
|
||||||
|
literal = unescape_operator(ident)
|
||||||
|
if not literal in self.strtab:
|
||||||
|
self.strtab_long.add(literal)
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
# Parse a block of definition like module, class...
|
# Parse a block of definition like module, class...
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
@ -22,9 +22,10 @@ class str_info:
|
|||||||
self.extra = 0
|
self.extra = 0
|
||||||
|
|
||||||
class str_build:
|
class str_build:
|
||||||
def __init__(self, map, map_weak):
|
def __init__(self, map, map_weak, map_long):
|
||||||
self.map = map.copy()
|
self.map = map.copy()
|
||||||
self.str_weak = []
|
self.str_weak = []
|
||||||
|
self.str_long = []
|
||||||
|
|
||||||
size = int(len(self.map) / 2) # voluntarily reduce hash size to half
|
size = int(len(self.map) / 2) # voluntarily reduce hash size to half
|
||||||
if size < 4: size = 4
|
if size < 4: size = 4
|
||||||
@ -44,6 +45,11 @@ class str_build:
|
|||||||
if not k in self.map:
|
if not k in self.map:
|
||||||
self.str_weak.append(k)
|
self.str_weak.append(k)
|
||||||
|
|
||||||
|
# handle long strings
|
||||||
|
for k in sorted(map_long.keys()):
|
||||||
|
if not k in self.map:
|
||||||
|
self.str_long.append(k)
|
||||||
|
|
||||||
def build(self, path):
|
def build(self, path):
|
||||||
prefix = path + "/be_const_strtab"
|
prefix = path + "/be_const_strtab"
|
||||||
self.writefile(prefix + "_def.h", self.build_table_def())
|
self.writefile(prefix + "_def.h", self.build_table_def())
|
||||||
@ -121,6 +127,10 @@ class str_build:
|
|||||||
ostr += escape_operator(k) + ", " + escape_c(k) + ", "
|
ostr += escape_operator(k) + ", " + escape_c(k) + ", "
|
||||||
ostr += "0u, 0, " + str(len(k)) + ", NULL);\n"
|
ostr += "0u, 0, " + str(len(k)) + ", NULL);\n"
|
||||||
|
|
||||||
|
for k in self.str_long:
|
||||||
|
ostr += "be_define_const_str_long("
|
||||||
|
ostr += escape_operator(k) + ", " + escape_c(k) + ", " + str(len(k)) + ");\n"
|
||||||
|
|
||||||
ostr += "\n"
|
ostr += "\n"
|
||||||
ostr += "static const bstring* const m_string_table[] = {\n"
|
ostr += "static const bstring* const m_string_table[] = {\n"
|
||||||
|
|
||||||
@ -156,4 +166,6 @@ class str_build:
|
|||||||
ostr += "\n/* weak strings */\n"
|
ostr += "\n/* weak strings */\n"
|
||||||
for s in self.str_weak:
|
for s in self.str_weak:
|
||||||
ostr += "extern const bcstring be_const_str_" + escape_operator(s) + ";\n"
|
ostr += "extern const bcstring be_const_str_" + escape_operator(s) + ";\n"
|
||||||
|
for s in self.str_long:
|
||||||
|
ostr += "extern const bclstring be_const_str_" + escape_operator(s) + ";\n"
|
||||||
return ostr
|
return ostr
|
||||||
|
Loading…
x
Reference in New Issue
Block a user