mirror of https://github.com/arendst/Tasmota.git
Berry bytes solidification (#21558)
* Berry prepare for bytes() solidification * Berry solidification of bytes objects * Berry solidification of `bytes` instances
This commit is contained in:
parent
243411916b
commit
a51c511d52
|
@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [14.1.0.1]
|
## [14.1.0.1]
|
||||||
### Added
|
### Added
|
||||||
|
- Berry solidification of `bytes` instances
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
|
|
@ -16,28 +16,7 @@
|
||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "be_byteslib.h"
|
||||||
#define BYTES_DEFAULT_SIZE 28 // default pre-reserved size for buffer (keep 4 bytes for len/size)
|
|
||||||
#define BYTES_OVERHEAD 4 // bytes overhead to be added when allocating (used to store len and size)
|
|
||||||
#define BYTES_HEADROOM 8 // keep a natural headroom of 8 bytes when resizing
|
|
||||||
|
|
||||||
#define BYTES_SIZE_FIXED -1 // if size is -1, then the bytes object cannot be reized
|
|
||||||
#define BYTES_SIZE_MAPPED -2 // if size is -2, then the bytes object is mapped to a fixed memory region, i.e. cannot be resized
|
|
||||||
|
|
||||||
#define BYTES_RESIZE_ERROR "attribute_error"
|
|
||||||
#define BYTES_RESIZE_MESSAGE "bytes object size if fixed and cannot be resized"
|
|
||||||
/* be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); */
|
|
||||||
|
|
||||||
typedef struct buf_impl {
|
|
||||||
int32_t size; // size in bytes of the buffer
|
|
||||||
int32_t len; // current size of the data in buffer. Invariant: len <= size
|
|
||||||
uint8_t *bufptr; // the actual data
|
|
||||||
int32_t prev_size; // previous value read from the instance
|
|
||||||
int32_t prev_len; // previous value read from the instance
|
|
||||||
uint8_t *prev_bufptr;
|
|
||||||
bbool fixed; // is size fixed? (actually encoded as negative size)
|
|
||||||
bbool mapped;
|
|
||||||
} buf_impl;
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Base64 lib from https://github.com/Densaugeo/base64_arduino
|
** Base64 lib from https://github.com/Densaugeo/base64_arduino
|
||||||
|
@ -481,7 +460,16 @@ static void buf_add_hex(buf_impl* attr, const char *hex, size_t len)
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
/* if the bufptr is null, don't try to dereference and raise an exception instead */
|
/* if the bufptr is null, don't try to dereference and raise an exception instead */
|
||||||
static void check_ptr(bvm *vm, buf_impl* attr) {
|
static void check_ptr(bvm *vm, const buf_impl* attr) {
|
||||||
|
if (!attr->bufptr) {
|
||||||
|
be_raise(vm, "value_error", "operation not allowed on <null> pointer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_ptr_modifiable(bvm *vm, const buf_impl* attr) {
|
||||||
|
if (attr->solidified) {
|
||||||
|
be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE);
|
||||||
|
}
|
||||||
if (!attr->bufptr) {
|
if (!attr->bufptr) {
|
||||||
be_raise(vm, "value_error", "operation not allowed on <null> pointer");
|
be_raise(vm, "value_error", "operation not allowed on <null> pointer");
|
||||||
}
|
}
|
||||||
|
@ -504,10 +492,14 @@ buf_impl m_read_attributes(bvm *vm, int idx)
|
||||||
int32_t signed_size = be_toint(vm, -1);
|
int32_t signed_size = be_toint(vm, -1);
|
||||||
attr.fixed = bfalse;
|
attr.fixed = bfalse;
|
||||||
attr.mapped = bfalse;
|
attr.mapped = bfalse;
|
||||||
|
attr.solidified = bfalse;
|
||||||
if (signed_size < 0) {
|
if (signed_size < 0) {
|
||||||
if (signed_size == BYTES_SIZE_MAPPED) {
|
if (signed_size == BYTES_SIZE_MAPPED) {
|
||||||
attr.mapped = btrue;
|
attr.mapped = btrue;
|
||||||
}
|
}
|
||||||
|
if (signed_size == BYTES_SIZE_SOLIDIFIED) {
|
||||||
|
attr.solidified = btrue;
|
||||||
|
}
|
||||||
signed_size = attr.len;
|
signed_size = attr.len;
|
||||||
attr.fixed = btrue;
|
attr.fixed = btrue;
|
||||||
}
|
}
|
||||||
|
@ -516,10 +508,18 @@ buf_impl m_read_attributes(bvm *vm, int idx)
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void m_assert_not_readlonly(bvm *vm, const buf_impl* attr)
|
||||||
|
{
|
||||||
|
if (attr->solidified) {
|
||||||
|
be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Write back attributes to the bytes instance, only if values changed after loading */
|
/* Write back attributes to the bytes instance, only if values changed after loading */
|
||||||
/* stack item 1 must contain the instance */
|
/* stack item 1 must contain the instance */
|
||||||
void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
|
void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
|
||||||
{
|
{
|
||||||
|
m_assert_not_readlonly(vm, attr);
|
||||||
int idx = be_absindex(vm, rel_idx);
|
int idx = be_absindex(vm, rel_idx);
|
||||||
if (attr->bufptr != attr->prev_bufptr) {
|
if (attr->bufptr != attr->prev_bufptr) {
|
||||||
be_pushcomptr(vm, attr->bufptr);
|
be_pushcomptr(vm, attr->bufptr);
|
||||||
|
@ -549,6 +549,7 @@ void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr)
|
||||||
// buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size)
|
// buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size)
|
||||||
void bytes_realloc(bvm *vm, buf_impl * attr, int32_t size)
|
void bytes_realloc(bvm *vm, buf_impl * attr, int32_t size)
|
||||||
{
|
{
|
||||||
|
m_assert_not_readlonly(vm, attr);
|
||||||
if (!attr->fixed && size < 4) { size = 4; }
|
if (!attr->fixed && size < 4) { size = 4; }
|
||||||
if (size > vm->bytesmaxsize) { size = vm->bytesmaxsize; }
|
if (size > vm->bytesmaxsize) { size = vm->bytesmaxsize; }
|
||||||
size_t oldsize = attr->bufptr ? attr->size : 0;
|
size_t oldsize = attr->bufptr ? attr->size : 0;
|
||||||
|
@ -590,7 +591,7 @@ static void bytes_new_object(bvm *vm, size_t size)
|
||||||
static int m_init(bvm *vm)
|
static int m_init(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = { 0, 0, NULL, 0, -1, NULL, bfalse, bfalse }; /* initialize prev_values to invalid to force a write at the end */
|
buf_impl attr = { 0, 0, NULL, 0, -1, NULL, bfalse, bfalse, bfalse }; /* initialize prev_values to invalid to force a write at the end */
|
||||||
/* size cannot be 0, len cannot be negative */
|
/* size cannot be 0, len cannot be negative */
|
||||||
const char * hex_in = NULL;
|
const char * hex_in = NULL;
|
||||||
|
|
||||||
|
@ -713,7 +714,7 @@ buf_impl bytes_check_data(bvm *vm, size_t add_size) {
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) {
|
size_t be_bytes_tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) {
|
||||||
static const char * hex = "0123456789ABCDEF";
|
static const char * hex = "0123456789ABCDEF";
|
||||||
const uint8_t * pin = in;
|
const uint8_t * pin = in;
|
||||||
char * pout = out;
|
char * pout = out;
|
||||||
|
@ -745,7 +746,7 @@ static int m_tostring(bvm *vm)
|
||||||
|
|
||||||
char * hex_out = be_pushbuffer(vm, hex_len);
|
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||||
size_t l = be_strlcpy(hex_out, "bytes('", hex_len);
|
size_t l = be_strlcpy(hex_out, "bytes('", hex_len);
|
||||||
l += tohex(&hex_out[l], hex_len - l, attr.bufptr, len);
|
l += be_bytes_tohex(&hex_out[l], hex_len - l, attr.bufptr, len);
|
||||||
if (truncated) {
|
if (truncated) {
|
||||||
l += be_strlcpy(&hex_out[l], "...", hex_len - l);
|
l += be_strlcpy(&hex_out[l], "...", hex_len - l);
|
||||||
}
|
}
|
||||||
|
@ -767,7 +768,7 @@ static int m_tohex(bvm *vm)
|
||||||
size_t hex_len = len * 2 + 1;
|
size_t hex_len = len * 2 + 1;
|
||||||
|
|
||||||
char * hex_out = be_pushbuffer(vm, hex_len);
|
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||||
size_t l = tohex(hex_out, hex_len, attr.bufptr, len);
|
size_t l = be_bytes_tohex(hex_out, hex_len, attr.bufptr, len);
|
||||||
|
|
||||||
be_pushnstring(vm, hex_out, l); /* make escape string from buffer */
|
be_pushnstring(vm, hex_out, l); /* make escape string from buffer */
|
||||||
be_remove(vm, -2); /* remove buffer */
|
be_remove(vm, -2); /* remove buffer */
|
||||||
|
@ -795,7 +796,7 @@ static int m_fromstring(bvm *vm)
|
||||||
const char *s = be_tostring(vm, 2);
|
const char *s = be_tostring(vm, 2);
|
||||||
int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */
|
int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */
|
||||||
buf_impl attr = bytes_check_data(vm, 0);
|
buf_impl attr = bytes_check_data(vm, 0);
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed && attr.len != len) {
|
if (attr.fixed && attr.len != len) {
|
||||||
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
||||||
}
|
}
|
||||||
|
@ -823,7 +824,7 @@ static int m_add(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||||
if (argc >= 2 && be_isint(vm, 2)) {
|
if (argc >= 2 && be_isint(vm, 2)) {
|
||||||
int32_t v = be_toint(vm, 2);
|
int32_t v = be_toint(vm, 2);
|
||||||
|
@ -949,7 +950,7 @@ static int m_set(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
||||||
int32_t idx = be_toint(vm, 2);
|
int32_t idx = be_toint(vm, 2);
|
||||||
int32_t value = be_toint(vm, 3);
|
int32_t value = be_toint(vm, 3);
|
||||||
|
@ -985,7 +986,7 @@ static int m_setfloat(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (argc >=3 && be_isint(vm, 2) && (be_isint(vm, 3) || be_isreal(vm, 3))) {
|
if (argc >=3 && be_isint(vm, 2) && (be_isint(vm, 3) || be_isreal(vm, 3))) {
|
||||||
int32_t idx = be_toint(vm, 2);
|
int32_t idx = be_toint(vm, 2);
|
||||||
float val_f = (float) be_toreal(vm, 3);
|
float val_f = (float) be_toreal(vm, 3);
|
||||||
|
@ -1011,7 +1012,7 @@ static int m_addfloat(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||||
if (argc >=2 && (be_isint(vm, 2) || be_isreal(vm, 2))) {
|
if (argc >=2 && (be_isint(vm, 2) || be_isreal(vm, 2))) {
|
||||||
float val_f = (float) be_toreal(vm, 2);
|
float val_f = (float) be_toreal(vm, 2);
|
||||||
|
@ -1040,7 +1041,7 @@ static int m_setbytes(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (argc >=3 && be_isint(vm, 2) && (be_isbytes(vm, 3))) {
|
if (argc >=3 && be_isint(vm, 2) && (be_isbytes(vm, 3))) {
|
||||||
int32_t idx = be_toint(vm, 2);
|
int32_t idx = be_toint(vm, 2);
|
||||||
size_t from_len_total;
|
size_t from_len_total;
|
||||||
|
@ -1084,7 +1085,7 @@ static int m_reverse(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
|
|
||||||
int32_t idx = 0; /* start from index 0 */
|
int32_t idx = 0; /* start from index 0 */
|
||||||
int32_t len = attr.len; /* entire len */
|
int32_t len = attr.len; /* entire len */
|
||||||
|
@ -1135,7 +1136,7 @@ static int m_setitem(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
||||||
int index = be_toint(vm, 2);
|
int index = be_toint(vm, 2);
|
||||||
int val = be_toint(vm, 3);
|
int val = be_toint(vm, 3);
|
||||||
|
@ -1153,7 +1154,7 @@ static int m_item(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (argc >=2 && be_isint(vm, 2)) { /* single byte */
|
if (argc >=2 && be_isint(vm, 2)) { /* single byte */
|
||||||
int index = be_toint(vm,2);
|
int index = be_toint(vm,2);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
@ -1215,6 +1216,7 @@ static int m_resize(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = m_read_attributes(vm, 1);
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
|
check_ptr_modifiable(vm, &attr);
|
||||||
|
|
||||||
if (argc <= 1 || !be_isint(vm, 2)) {
|
if (argc <= 1 || !be_isint(vm, 2)) {
|
||||||
be_raise(vm, "type_error", "size must be of type 'int'");
|
be_raise(vm, "type_error", "size must be of type 'int'");
|
||||||
|
@ -1237,6 +1239,7 @@ static int m_resize(bvm *vm)
|
||||||
static int m_clear(bvm *vm)
|
static int m_clear(bvm *vm)
|
||||||
{
|
{
|
||||||
buf_impl attr = m_read_attributes(vm, 1);
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||||
attr.len = 0;
|
attr.len = 0;
|
||||||
m_write_attributes(vm, 1, &attr); /* update instance */
|
m_write_attributes(vm, 1, &attr); /* update instance */
|
||||||
|
@ -1293,7 +1296,7 @@ static int m_connect(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
buf_impl attr = m_read_attributes(vm, 1);
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
|
||||||
if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2) || be_isstring(vm, 2))) {
|
if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2) || be_isstring(vm, 2))) {
|
||||||
if (be_isint(vm, 2)) {
|
if (be_isint(vm, 2)) {
|
||||||
|
@ -1390,7 +1393,7 @@ static int m_fromb64(bvm *vm)
|
||||||
int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */
|
int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */
|
||||||
|
|
||||||
buf_impl attr = m_read_attributes(vm, 1);
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed && attr.len != bin_len) {
|
if (attr.fixed && attr.len != bin_len) {
|
||||||
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
||||||
}
|
}
|
||||||
|
@ -1429,7 +1432,7 @@ static int m_fromhex(bvm *vm)
|
||||||
int32_t bin_len = (s_len - from) / 2;
|
int32_t bin_len = (s_len - from) / 2;
|
||||||
|
|
||||||
buf_impl attr = m_read_attributes(vm, 1);
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
check_ptr(vm, &attr);
|
check_ptr_modifiable(vm, &attr);
|
||||||
if (attr.fixed && attr.len != bin_len) {
|
if (attr.fixed && attr.len != bin_len) {
|
||||||
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
|
||||||
}
|
}
|
||||||
|
@ -1483,6 +1486,18 @@ static int m_is_mapped(bvm *vm)
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns `btrue` if the buffer is solidified and read only
|
||||||
|
*
|
||||||
|
* `isreadonly() -> bool`
|
||||||
|
*/
|
||||||
|
static int m_is_readonly(bvm *vm)
|
||||||
|
{
|
||||||
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
|
be_pushbool(vm, attr.solidified);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change the pointer to a mapped buffer.
|
* Change the pointer to a mapped buffer.
|
||||||
*
|
*
|
||||||
|
@ -1497,6 +1512,9 @@ static int m_change_buffer(bvm *vm)
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
if (argc >= 2 && be_iscomptr(vm, 2)) {
|
if (argc >= 2 && be_iscomptr(vm, 2)) {
|
||||||
buf_impl attr = m_read_attributes(vm, 1);
|
buf_impl attr = m_read_attributes(vm, 1);
|
||||||
|
if (attr.solidified) {
|
||||||
|
be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE);
|
||||||
|
}
|
||||||
if (!attr.mapped) {
|
if (!attr.mapped) {
|
||||||
be_raise(vm, "type_error", "bytes() object must be mapped");
|
be_raise(vm, "type_error", "bytes() object must be mapped");
|
||||||
}
|
}
|
||||||
|
@ -1764,11 +1782,12 @@ void be_load_byteslib(bvm *vm)
|
||||||
{
|
{
|
||||||
static const bnfuncinfo members[] = {
|
static const bnfuncinfo members[] = {
|
||||||
{ ".p", NULL },
|
{ ".p", NULL },
|
||||||
{ ".size", NULL },
|
|
||||||
{ ".len", NULL },
|
{ ".len", NULL },
|
||||||
|
{ ".size", NULL },
|
||||||
{ "_buffer", m_buffer },
|
{ "_buffer", m_buffer },
|
||||||
{ "_change_buffer", m_change_buffer },
|
{ "_change_buffer", m_change_buffer },
|
||||||
{ "ismapped", m_is_mapped },
|
{ "ismapped", m_is_mapped },
|
||||||
|
{ "isreadonly", m_is_readonly },
|
||||||
{ "init", m_init },
|
{ "init", m_init },
|
||||||
{ "deinit", m_deinit },
|
{ "deinit", m_deinit },
|
||||||
{ "tostring", m_tostring },
|
{ "tostring", m_tostring },
|
||||||
|
@ -1810,14 +1829,18 @@ void be_load_byteslib(bvm *vm)
|
||||||
be_regclass(vm, "bytes", members);
|
be_regclass(vm, "bytes", members);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#include "../generate/be_const_bytes_def.h"
|
||||||
|
|
||||||
/* @const_object_info_begin
|
/* @const_object_info_begin
|
||||||
class be_class_bytes (scope: global, name: bytes) {
|
class be_class_bytes (scope: global, name: bytes) {
|
||||||
.p, var
|
.p, var
|
||||||
.size, var
|
|
||||||
.len, var
|
.len, var
|
||||||
|
.size, var
|
||||||
_buffer, func(m_buffer)
|
_buffer, func(m_buffer)
|
||||||
_change_buffer, func(m_change_buffer)
|
_change_buffer, func(m_change_buffer)
|
||||||
ismapped, func(m_is_mapped)
|
ismapped, func(m_is_mapped)
|
||||||
|
isreadonly, func(m_is_readonly)
|
||||||
init, func(m_init)
|
init, func(m_init)
|
||||||
deinit, func(m_deinit)
|
deinit, func(m_deinit)
|
||||||
tostring, func(m_tostring)
|
tostring, func(m_tostring)
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/********************************************************************
|
||||||
|
** Copyright (c) 2018-2020 Guan Wenliang - Stephan Hadinger
|
||||||
|
** This file is part of the Berry default interpreter.
|
||||||
|
** skiars@qq.com, https://github.com/Skiars/berry
|
||||||
|
** See Copyright Notice in the LICENSE file or at
|
||||||
|
** https://github.com/Skiars/berry/blob/master/LICENSE
|
||||||
|
********************************************************************/
|
||||||
|
#ifndef __BE_BYTESLIB_H
|
||||||
|
#define __BE_BYTESLIB_H
|
||||||
|
|
||||||
|
#include "be_object.h"
|
||||||
|
|
||||||
|
#define BYTES_DEFAULT_SIZE 28 /* default pre-reserved size for buffer (keep 4 bytes for len/size) */
|
||||||
|
#define BYTES_OVERHEAD 4 /* bytes overhead to be added when allocating (used to store len and size) */
|
||||||
|
#define BYTES_HEADROOM 8 /* keep a natural headroom of 8 bytes when resizing */
|
||||||
|
|
||||||
|
#define BYTES_SIZE_FIXED -1 /* if size is -1, then the bytes object cannot be reized */
|
||||||
|
#define BYTES_SIZE_MAPPED -2 /* if size is -2, then the bytes object is mapped to a fixed memory region, i.e. cannot be resized */
|
||||||
|
#define BYTES_SIZE_SOLIDIFIED -3 /* is size is -3, then the bytes object is solidified and cannot be resized nor modified */
|
||||||
|
|
||||||
|
#define BYTES_RESIZE_ERROR "attribute_error"
|
||||||
|
#define BYTES_RESIZE_MESSAGE "bytes object size if fixed and cannot be resized"
|
||||||
|
#define BYTES_READ_ONLY_MESSAGE "bytes object is read only"
|
||||||
|
/* be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); */
|
||||||
|
|
||||||
|
typedef struct buf_impl {
|
||||||
|
int32_t size; // size in bytes of the buffer
|
||||||
|
int32_t len; // current size of the data in buffer. Invariant: len <= size
|
||||||
|
uint8_t *bufptr; // the actual data
|
||||||
|
int32_t prev_size; // previous value read from the instance
|
||||||
|
int32_t prev_len; // previous value read from the instance
|
||||||
|
uint8_t *prev_bufptr;
|
||||||
|
bbool fixed; // is size fixed? (actually encoded as negative size)
|
||||||
|
bbool mapped;
|
||||||
|
bbool solidified;
|
||||||
|
} buf_impl;
|
||||||
|
|
||||||
|
size_t be_bytes_tohex(char * out, size_t outsz, const uint8_t * in, size_t insz);
|
||||||
|
|
||||||
|
#if BE_USE_PRECOMPILED_OBJECT
|
||||||
|
#include "../generate/be_const_bytes.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -49,6 +49,16 @@ struct binstance {
|
||||||
bvalue members[1]; /* members variable data field */
|
bvalue members[1]; /* members variable data field */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* special structure accepting 3 instance variables used only for bytes() solidification */
|
||||||
|
struct binstance_arg3 {
|
||||||
|
bcommon_header;
|
||||||
|
struct binstance *super;
|
||||||
|
struct binstance *sub;
|
||||||
|
bclass *_class;
|
||||||
|
bgcobject *gray; /* for gc gray list */
|
||||||
|
bvalue members[3]; /* members variable data field */
|
||||||
|
};
|
||||||
|
|
||||||
bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
|
bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
|
||||||
void be_class_compress(bvm *vm, bclass *c);
|
void be_class_compress(bvm *vm, bclass *c);
|
||||||
int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
|
int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
|
||||||
|
|
|
@ -19,6 +19,7 @@ extern "C" {
|
||||||
#include "be_class.h"
|
#include "be_class.h"
|
||||||
#include "be_string.h"
|
#include "be_string.h"
|
||||||
#include "be_module.h"
|
#include "be_module.h"
|
||||||
|
#include "be_byteslib.h"
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
@ -27,6 +28,25 @@ extern "C" {
|
||||||
.type = (_t), \
|
.type = (_t), \
|
||||||
.marked = GC_CONST
|
.marked = GC_CONST
|
||||||
|
|
||||||
|
#define be_define_const_bytes(_name, ...) \
|
||||||
|
const uint8_t be_const_bin_##_name[] = { __VA_ARGS__ }
|
||||||
|
|
||||||
|
#define be_const_bytes_instance(_bytes) { \
|
||||||
|
.v.c = ( \
|
||||||
|
& (const binstance_arg3) { \
|
||||||
|
be_const_header(BE_INSTANCE), \
|
||||||
|
.super = NULL, \
|
||||||
|
.sub = NULL, \
|
||||||
|
._class = (bclass*) &be_class_bytes, \
|
||||||
|
.members = { \
|
||||||
|
be_const_comptr(&be_const_bin_##_bytes), \
|
||||||
|
be_const_int(sizeof(#_bytes) / 2), \
|
||||||
|
be_const_int(BYTES_SIZE_SOLIDIFIED) \
|
||||||
|
} \
|
||||||
|
}), \
|
||||||
|
.type = BE_INSTANCE \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_define_const_str_weak(_name, _s, _len) \
|
#define be_define_const_str_weak(_name, _s, _len) \
|
||||||
const bcstring be_const_str_##_name = { \
|
const bcstring be_const_str_##_name = { \
|
||||||
.next = NULL, \
|
.next = NULL, \
|
||||||
|
@ -232,6 +252,27 @@ const bntvmodule_t be_native_module(_module) = { \
|
||||||
.members = _members \
|
.members = _members \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define be_nested_simple_instance_1_arg(_class_ptr, arg0) \
|
||||||
|
& (const binstance) { \
|
||||||
|
be_const_header(BE_INSTANCE), \
|
||||||
|
.super = NULL, \
|
||||||
|
.sub = NULL, \
|
||||||
|
._class = (bclass*) _class_ptr, \
|
||||||
|
.members = { arg0 } \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* only instances with no super and no sub instance are supported */
|
||||||
|
/* primarily for `list` and `map`*/
|
||||||
|
#define be_nested_simple_instance_3_args(_class_ptr, arg0, arg1, arg2) \
|
||||||
|
& (const binstance_arg3) { \
|
||||||
|
be_const_header(BE_INSTANCE), \
|
||||||
|
.super = NULL, \
|
||||||
|
.sub = NULL, \
|
||||||
|
._class = (bclass*) _class_ptr, \
|
||||||
|
.members = { arg0, arg1, arg2 } \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_nested_map(_size, _slots) \
|
#define be_nested_map(_size, _slots) \
|
||||||
& (const bmap) { \
|
& (const bmap) { \
|
||||||
be_const_header(BE_MAP), \
|
be_const_header(BE_MAP), \
|
||||||
|
@ -298,6 +339,9 @@ const bntvmodule_t be_native_module(_module) = { \
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#define be_define_const_bytes(_name, ...) \
|
||||||
|
const uint8_t be_const_bin_##_name[] = { __VA_ARGS__ }
|
||||||
|
|
||||||
#define be_define_const_str_weak(_name, _s, _len) \
|
#define be_define_const_str_weak(_name, _s, _len) \
|
||||||
const bcstring be_const_str_##_name = { \
|
const bcstring be_const_str_##_name = { \
|
||||||
NULL, \
|
NULL, \
|
||||||
|
@ -440,6 +484,7 @@ const bntvmodule_t be_native_module_##_module = { \
|
||||||
/* provide pointers to map and list classes for solidified code */
|
/* provide pointers to map and list classes for solidified code */
|
||||||
extern const bclass be_class_list;
|
extern const bclass be_class_list;
|
||||||
extern const bclass be_class_map;
|
extern const bclass be_class_map;
|
||||||
|
extern const bclass be_class_bytes;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ typedef struct bclosure bclosure;
|
||||||
typedef struct bntvclos bntvclos;
|
typedef struct bntvclos bntvclos;
|
||||||
typedef struct bclass bclass;
|
typedef struct bclass bclass;
|
||||||
typedef struct binstance binstance;
|
typedef struct binstance binstance;
|
||||||
|
typedef struct binstance_arg3 binstance_arg3;
|
||||||
typedef struct blist blist;
|
typedef struct blist blist;
|
||||||
typedef struct bmap bmap;
|
typedef struct bmap bmap;
|
||||||
typedef struct bupval bupval;
|
typedef struct bupval bupval;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "be_decoder.h"
|
#include "be_decoder.h"
|
||||||
#include "be_sys.h"
|
#include "be_sys.h"
|
||||||
#include "be_mem.h"
|
#include "be_mem.h"
|
||||||
|
#include "be_byteslib.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
|
|
||||||
extern const bclass be_class_list;
|
extern const bclass be_class_list;
|
||||||
extern const bclass be_class_map;
|
extern const bclass be_class_map;
|
||||||
|
extern const bclass be_class_bytes;
|
||||||
|
|
||||||
#if BE_USE_SOLIDIFY_MODULE
|
#if BE_USE_SOLIDIFY_MODULE
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -288,12 +290,23 @@ static void m_solidify_bvalue(bvm *vm, bbool str_literal, const bvalue * value,
|
||||||
bclass * cl = ins->_class;
|
bclass * cl = ins->_class;
|
||||||
if (ins->super || ins->sub) {
|
if (ins->super || ins->sub) {
|
||||||
be_raise(vm, "internal_error", "instance must not have a super/sub class");
|
be_raise(vm, "internal_error", "instance must not have a super/sub class");
|
||||||
} else if (cl->nvar != 1) {
|
|
||||||
be_raise(vm, "internal_error", "instance must have only one instance variable");
|
|
||||||
} else if ((cl != &be_class_map && cl != &be_class_list) || 1) { // TODO
|
} else if ((cl != &be_class_map && cl != &be_class_list) || 1) { // TODO
|
||||||
const char * cl_ptr = "";
|
const char * cl_ptr = "";
|
||||||
if (cl == &be_class_map) { cl_ptr = "map"; }
|
if (cl == &be_class_map) { cl_ptr = "map"; }
|
||||||
if (cl == &be_class_list) { cl_ptr = "list"; }
|
else if (cl == &be_class_list) { cl_ptr = "list"; }
|
||||||
|
else if (cl == &be_class_bytes) { cl_ptr = "bytes"; }
|
||||||
|
else { be_raise(vm, "internal_error", "unsupported class"); }
|
||||||
|
|
||||||
|
if (cl == &be_class_bytes) {
|
||||||
|
const void * bufptr = var_toobj(&ins->members[0]);
|
||||||
|
int32_t len = var_toint(&ins->members[1]);
|
||||||
|
size_t hex_len = len * 2 + 1;
|
||||||
|
|
||||||
|
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||||
|
be_bytes_tohex(hex_out, hex_len, bufptr, len);
|
||||||
|
logfmt("be_const_bytes_instance(%s)", hex_out);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
} else {
|
||||||
logfmt("be_const_simple_instance(be_nested_simple_instance(&be_class_%s, {\n", cl_ptr);
|
logfmt("be_const_simple_instance(be_nested_simple_instance(&be_class_%s, {\n", cl_ptr);
|
||||||
if (cl == &be_class_map) {
|
if (cl == &be_class_map) {
|
||||||
logfmt(" be_const_map( * ");
|
logfmt(" be_const_map( * ");
|
||||||
|
@ -304,6 +317,7 @@ static void m_solidify_bvalue(bvm *vm, bbool str_literal, const bvalue * value,
|
||||||
logfmt(" ) } ))");
|
logfmt(" ) } ))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case BE_MAP:
|
case BE_MAP:
|
||||||
m_solidify_map(vm, str_literal, (bmap *) var_toobj(value), prefixname, fout);
|
m_solidify_map(vm, str_literal, (bmap *) var_toobj(value), prefixname, fout);
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
class bytes_build:
|
||||||
|
def __init__(self, map):
|
||||||
|
self.map = map.copy()
|
||||||
|
|
||||||
|
def build(self, path):
|
||||||
|
prefix = path + "/be_const_bytes"
|
||||||
|
self.writefile(prefix + "_def.h", self.build_bytes_def())
|
||||||
|
self.writefile(prefix + ".h", self.build_bytes_ext())
|
||||||
|
|
||||||
|
def writefile(self, filename, text):
|
||||||
|
buf = ""
|
||||||
|
try:
|
||||||
|
with open(filename) as f:
|
||||||
|
buf = f.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
if buf != text:
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
f.write(text)
|
||||||
|
|
||||||
|
def build_bytes_def(self):
|
||||||
|
ostr = ""
|
||||||
|
ostr += "/* binary arrays */\n"
|
||||||
|
ostr += "be_define_const_bytes(,);\n"
|
||||||
|
for k in self.map:
|
||||||
|
ostr += "be_define_const_bytes("
|
||||||
|
ostr += k + ", " + ", ".join( [ "0x" + k[i:i+2] for i in range(0, len(k), 2)] )
|
||||||
|
ostr += ");\n"
|
||||||
|
|
||||||
|
return ostr
|
||||||
|
|
||||||
|
def build_bytes_ext(self):
|
||||||
|
ostr = ""
|
||||||
|
ostr += "/* extern binary arrays */\n"
|
||||||
|
ostr += "extern const uint8_t be_const_bin_[];\n"
|
||||||
|
for k in self.map:
|
||||||
|
ostr += "extern const uint8_t be_const_bin_" + k + "[];\n"
|
||||||
|
|
||||||
|
return ostr
|
|
@ -4,6 +4,7 @@ import re
|
||||||
import os
|
import os
|
||||||
from coc_parser import *
|
from coc_parser import *
|
||||||
from str_build import *
|
from str_build import *
|
||||||
|
from bytes_build import *
|
||||||
from block_builder import *
|
from block_builder import *
|
||||||
from macro_table import *
|
from macro_table import *
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ class builder:
|
||||||
self.strmap = {}
|
self.strmap = {}
|
||||||
self.strmap_weak = {}
|
self.strmap_weak = {}
|
||||||
self.strmap_long = {}
|
self.strmap_long = {}
|
||||||
|
self.bytesmap = {}
|
||||||
|
|
||||||
self.macro = macro_table()
|
self.macro = macro_table()
|
||||||
for path in self.config:
|
for path in self.config:
|
||||||
|
@ -31,6 +33,9 @@ class builder:
|
||||||
sb = str_build(self.strmap, self.strmap_weak, self.strmap_long)
|
sb = str_build(self.strmap, self.strmap_weak, self.strmap_long)
|
||||||
sb.build(self.output)
|
sb.build(self.output)
|
||||||
|
|
||||||
|
sbytes = bytes_build(self.bytesmap)
|
||||||
|
sbytes.build(self.output)
|
||||||
|
|
||||||
def parse_file(self, filename):
|
def parse_file(self, filename):
|
||||||
if re.search(r"\.(h|c|cc|cpp)$", filename):
|
if re.search(r"\.(h|c|cc|cpp)$", filename):
|
||||||
# print(f"> parse {filename}")
|
# print(f"> parse {filename}")
|
||||||
|
@ -45,6 +50,8 @@ class builder:
|
||||||
self.strmap_weak[s] = 0
|
self.strmap_weak[s] = 0
|
||||||
for s in parser.strtab_long:
|
for s in parser.strtab_long:
|
||||||
self.strmap_long[s] = 0
|
self.strmap_long[s] = 0
|
||||||
|
for s in parser.bintab:
|
||||||
|
self.bytesmap[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:
|
||||||
|
|
|
@ -23,10 +23,12 @@ class coc_parser:
|
||||||
self.strtab = set()
|
self.strtab = set()
|
||||||
self.strtab_weak = set()
|
self.strtab_weak = set()
|
||||||
self.strtab_long = set()
|
self.strtab_long = set()
|
||||||
|
self.bintab = 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,
|
||||||
"be_const_str_": self.parse_string,
|
"be_const_str_": self.parse_string,
|
||||||
|
"be_const_bytes_instance(": self.parse_bin,
|
||||||
"be_const_key(": self.parse_string,
|
"be_const_key(": self.parse_string,
|
||||||
"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,
|
||||||
|
@ -77,6 +79,7 @@ class coc_parser:
|
||||||
def parse_word(self):
|
def parse_word(self):
|
||||||
self.skip_space()
|
self.skip_space()
|
||||||
r = re.match(r"\w+", self.text)
|
r = re.match(r"\w+", self.text)
|
||||||
|
if not r: return None
|
||||||
self.text = self.text[r.end(0):]
|
self.text = self.text[r.end(0):]
|
||||||
return r[0]
|
return r[0]
|
||||||
|
|
||||||
|
@ -120,6 +123,7 @@ class coc_parser:
|
||||||
def parse_string(self):
|
def parse_string(self):
|
||||||
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||||
ident = self.parse_word()
|
ident = self.parse_word()
|
||||||
|
if not ident: return
|
||||||
literal = unescape_operator(ident)
|
literal = unescape_operator(ident)
|
||||||
if not literal in self.strtab:
|
if not literal in self.strtab:
|
||||||
self.strtab.add(literal)
|
self.strtab.add(literal)
|
||||||
|
@ -128,6 +132,7 @@ class coc_parser:
|
||||||
def parse_string_weak(self):
|
def parse_string_weak(self):
|
||||||
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||||
ident = self.parse_word()
|
ident = self.parse_word()
|
||||||
|
if not ident: return
|
||||||
literal = unescape_operator(ident)
|
literal = unescape_operator(ident)
|
||||||
if not literal in self.strtab:
|
if not literal in self.strtab:
|
||||||
self.strtab_weak.add(literal)
|
self.strtab_weak.add(literal)
|
||||||
|
@ -136,10 +141,19 @@ class coc_parser:
|
||||||
def parse_string_long(self):
|
def parse_string_long(self):
|
||||||
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify
|
||||||
ident = self.parse_word()
|
ident = self.parse_word()
|
||||||
|
if not ident: return
|
||||||
literal = unescape_operator(ident)
|
literal = unescape_operator(ident)
|
||||||
if not literal in self.strtab:
|
if not literal in self.strtab:
|
||||||
self.strtab_long.add(literal)
|
self.strtab_long.add(literal)
|
||||||
|
|
||||||
|
def parse_bin(self):
|
||||||
|
ident = self.parse_word()
|
||||||
|
if not ident: return
|
||||||
|
if not re.fullmatch(r"[0-9A-Za-z]*", ident): return
|
||||||
|
if not ident in self.bintab:
|
||||||
|
self.bintab.add(ident)
|
||||||
|
# print(f"str '{ident}' -> {literal}")
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
# Parse a block of definition like module, class...
|
# Parse a block of definition like module, class...
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
|
Loading…
Reference in New Issue