diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 32e3b532..4cc99a6a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,10 +48,10 @@ jobs: - name: Add MD5 checksum to ESP32 binary run: cd HeishaMon && MD5=`md5sum HeishaMon.ino.bin | cut -d\ -f1` && mv HeishaMon.ino.bin HeishaMon_ESP32-alpha-$MD5.bin - shell: bash + shell: bash - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: HeishaMon.ino.bin - path: HeishaMon/HeishaMon_*.bin \ No newline at end of file + path: HeishaMon/HeishaMon_*.bin diff --git a/HeishaMon/src/rules/rules.cpp b/HeishaMon/src/rules/rules.cpp index a006023a..529ab4e2 100644 --- a/HeishaMon/src/rules/rules.cpp +++ b/HeishaMon/src/rules/rules.cpp @@ -105,6 +105,13 @@ typedef struct vm_vfloat_t { static void *jmptbl[JMPSIZE] = { NULL }; +/* + * This additional category is needed to seperate + * the event that is used to define a new function + * block and when calling an event. + */ +#define TCEVENT 30 + #if defined(DEBUG) || defined(COVERALLS) uint16_t memused = 0; #endif @@ -142,7 +149,8 @@ struct { "VPTR", "VINTEGER", "VFLOAT", - "VNULL" + "VNULL", + "TCEVENT" }; struct { @@ -183,7 +191,6 @@ static void print_bytecode(struct rules_t *obj); #endif /*LCOV_EXCL_STOP*/ -//only already defined for ESP8266, not for ESP32 #if !defined(ESP8266) /*LCOV_EXCL_START*/ uint8_t mmu_set_uint8(void *ptr, uint8_t src) { *(uint8_t *)ptr = src; return src; } @@ -296,7 +303,7 @@ static int8_t lexer_parse_number(char *text, uint16_t len, uint16_t *pos) { * The dot cannot be the first character * and we cannot have more than 1 dot */ - while(*pos <= len && + while(*pos < len && ( isdigit(current) || (i == 0 && current == '-') || @@ -320,7 +327,7 @@ static int8_t lexer_parse_number(char *text, uint16_t len, uint16_t *pos) { static uint16_t lexer_parse_string(char *text, uint16_t len, uint16_t *pos) { char current = getval(text[*pos]); - while(*pos <= len && + while(*pos < len && (current != ' ' && current != ',' && current != ';' && @@ -363,7 +370,7 @@ static int8_t lexer_parse_quoted_string(char *text, uint16_t len, uint16_t *pos) static int8_t lexer_parse_skip_characters(char *text, uint16_t len, uint16_t *pos) { char current = getval(text[*pos]); - while(*pos <= len && + while(*pos < len && (current == ' ' || current == '\n' || current == '\t' || @@ -697,7 +704,7 @@ static int8_t rule_prepare(char **text, pos+=2; } } else if(isdigit(current) || (current == '-' && pos < *len && isdigit(next))) { - if(ctx == TEVENT) { + if(ctx == TCEVENT) { /* LCOV_EXCL_START*/ /* FIXME */ if((*len - pos) > 5) { @@ -952,12 +959,12 @@ static int8_t rule_prepare(char **text, uint16_t s = pos; lexer_parse_string((*text), *len, &pos); - if(ctx == TEVENT || ctx == TTHEN) { + if(ctx == TCEVENT || ctx == TTHEN) { logprintf_P(F("ERROR: nested 'on' block")); return -1; } - ctx = TEVENT; + ctx = TCEVENT; { uint16_t len = pos - s; @@ -1034,12 +1041,12 @@ static int8_t rule_prepare(char **text, } else if(current == ',') { nrtokens++; *heapsize += sizeof(struct vm_vnull_t); - if(ctx != TEVENT) { + if(ctx != TCEVENT) { *bcsize += sizeof(struct vm_top_t); } #ifdef DEBUG - if(ctx != TEVENT) { + if(ctx != TCEVENT) { printf("[BC] OP_PUSH: %lu\n", sizeof(struct vm_top_t)); } printf("[HEAP] VNULL: %lu\n", sizeof(struct vm_vnull_t)); @@ -1194,10 +1201,10 @@ static int8_t rule_prepare(char **text, if(ctx == TSEMICOLON) { *bcsize += sizeof(struct vm_top_t); } - if(ctx == TEVENT) { + if(ctx == TCEVENT) { do_clear = 0; } - if(ctx == TTHEN || ctx == TEVENT) { + if(ctx == TTHEN || ctx == TCEVENT) { *bcsize += sizeof(struct vm_top_t); } *heapsize += sizeof(struct vm_vnull_t); @@ -1207,7 +1214,7 @@ static int8_t rule_prepare(char **text, if(ctx == TIF || ctx == TASSIGN || ctx == TSEMICOLON) { printf("[BC] OP_SETVAL: %lu\n", sizeof(struct vm_top_t)); } - if(ctx == TTHEN || ctx == TEVENT) { + if(ctx == TTHEN || ctx == TCEVENT) { printf("[BC] OP_SETVAL: %lu\n", sizeof(struct vm_top_t)); } #endif @@ -1237,9 +1244,14 @@ static int8_t rule_prepare(char **text, printf("[BC] OP_SETVAL: %lu\n", sizeof(struct vm_top_t)); #endif + } else if(ctx == TCEVENT) { +#ifdef DEBUG + printf("[BC] OP_SETVAL: %lu\n", sizeof(struct vm_top_t)); +#endif + *bcsize += sizeof(struct vm_top_t); } } - if(ctx == TFUNCTION) { + if(ctx == TFUNCTION || ctx == TEVENT) { *bcsize += sizeof(struct vm_top_t); #ifdef DEBUG @@ -1303,6 +1315,7 @@ static int8_t rule_prepare(char **text, #endif if(ctx != TASSIGN) { do_clear = 1; + ctx = TEVENT; } } else { if((*len - pos) > 5) { @@ -2188,9 +2201,323 @@ static void bc_assign_slots(struct rules_t *obj) { } } +static int16_t bc_find_math_dep(struct rules_t *obj, uint16_t start, uint16_t a) { + struct vm_top_t *tmp = NULL; + int32_t pos = -1; + if(a >= 0) { + pos = start; + while((pos = bc_before(obj, pos)) != -1) { + tmp = (struct vm_top_t *)&obj->bc.buffer[pos]; + if(a == getval(tmp->a)) { + break; + } + } + } + return pos; +} + +static void bc_math_move_closest(struct rules_t *obj, int16_t limit) { + int16_t tmp1 = -1, tmp1B = -1, tmp1C = -1; + uint16_t nrbytes = bc_before(obj, getval(obj->bc.nrbytes)); + + while(nrbytes > limit) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[nrbytes]; + + if(gettype(x->type) == OP_GETVAL) { + tmp1 = nrbytes; + tmp1B = -1; + + if(getval(x->a) >= 0) { + tmp1B = tmp1; + while((tmp1B = bc_before(obj, tmp1B)) != -1 && tmp1B >= limit) { + struct vm_top_t *xB = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + if(gettype(xB->type) == OP_GETVAL || gettype(xB->type) == OP_CALL) { + continue; + } + if(getval(x->a) == getval(xB->c) && gettype(xB->type) != OP_GETVAL) { + break; + } + } + } + + if(tmp1B != -1 && tmp1B >= limit) { + while(tmp1B < tmp1) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + + if((tmp1B = bc_next(obj, tmp1B)) == -1) { + /* LCOV_EXCL_START*/ + logprintf_P(F("FATAL: Internal error in %s #%d %d"), __FUNCTION__, __LINE__); + exit(-1); + /* LCOV_EXCL_STOP*/ + } + + if(tmp1B < limit) { + break; + } + + struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + int8_t xT = getval(x->type), xA = getval(x->a), xB = getval(x->b), xC = getval(x->c); + int8_t yA = getval(y->a); + + setval(x->type, getval(y->type)); + setval(x->b, getval(y->b)); + setval(x->c, getval(y->c)); + + setval(y->type, xT); + setval(y->b, xB); + setval(y->c, xC); + + tmp1C = limit; + while(tmp1C != -1) { + struct vm_top_t *z = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + + if(gettype(z->type) != OP_GETVAL && + gettype(z->type) != OP_CALL) { + if(getval(z->c) == xA) { + setval(z->c, yA); + } else if(getval(z->c) == yA) { + setval(z->c, xA); + } + if(getval(z->b) == xA) { + setval(z->b, yA); + } else if(getval(z->b) == yA) { + setval(z->b, xA); + } + } + tmp1C = bc_next(obj, tmp1C); + } + } + } + } + x = (struct vm_top_t *)&obj->bc.buffer[nrbytes]; + if(gettype(x->type) == OP_GETVAL) { + tmp1 = nrbytes; + tmp1B = -1; + + if(getval(x->a) >= 0) { + tmp1B = tmp1; + while((tmp1B = bc_before(obj, tmp1B)) != -1 && tmp1B >= limit) { + struct vm_top_t *xB = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + if(gettype(xB->type) == OP_GETVAL || gettype(xB->type) == OP_CALL) { + continue; + } + if(getval(x->a) == getval(xB->b)) { + break; + } + } + } + + if(tmp1B != -1 && tmp1B >= limit) { + while(tmp1B < tmp1) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + + if((tmp1B = bc_next(obj, tmp1B)) == -1) { + /* LCOV_EXCL_START*/ + logprintf_P(F("FATAL: Internal error in %s #%d %d"), __FUNCTION__, __LINE__); + exit(-1); + /* LCOV_EXCL_STOP*/ + } + + if(tmp1B < limit) { + break; + } + + struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + int8_t xT = getval(x->type), xA = getval(x->a), xB = getval(x->b), xC = getval(x->c); + int8_t yA = getval(y->a); + + setval(x->type, getval(y->type)); + setval(x->b, getval(y->b)); + setval(x->c, getval(y->c)); + + setval(y->type, xT); + setval(y->b, xB); + setval(y->c, xC); + + tmp1C = limit; + while(tmp1C != -1) { + struct vm_top_t *z = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + + if(gettype(z->type) != OP_GETVAL && + gettype(z->type) != OP_CALL) { + if(getval(z->c) == xA) { + setval(z->c, yA); + } else if(getval(z->c) == yA) { + setval(z->c, xA); + } + if(getval(z->b) == xA) { + setval(z->b, yA); + } else if(getval(z->b) == yA) { + setval(z->b, xA); + } + } + tmp1C = bc_next(obj, tmp1C); + } + } + } + } + + x = (struct vm_top_t *)&obj->bc.buffer[nrbytes]; + if(is_op_and_math(gettype(x->type))) { + tmp1 = nrbytes; + tmp1C = -1; + if(getval(x->c) >= 0) { + tmp1C = tmp1; + while((tmp1C = bc_before(obj, tmp1C)) != -1) { + struct vm_top_t *xC = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + + if(getval(x->c) == getval(xC->a)) { + break; + } + } + } + + if(tmp1C != -1 && tmp1B >= limit) { + tmp1B = bc_find_math_dep(obj, tmp1, getval(x->b)); + struct vm_top_t *xC = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + struct vm_top_t *xB = NULL; + if(tmp1B != -1) { + xB = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + } + + if(xB == NULL || gettype(xC->type) == OP_GETVAL || (((int8_t)getval(xB->b) >= 0)+((int8_t)getval(xB->c) >= 0) < ((int8_t)getval(xC->b) >= 0)+((int8_t)getval(xC->c) >= 0))) { + while(tmp1C < tmp1) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + if(!is_op_and_math(gettype(x->type)) && gettype(x->type) != OP_GETVAL) { + break; + } + + if((tmp1C = bc_next(obj, tmp1C)) == -1) { + /* LCOV_EXCL_START*/ + logprintf_P(F("FATAL: Internal error in %s #%d %d"), __FUNCTION__, __LINE__); + exit(-1); + /* LCOV_EXCL_STOP*/ + } + + if(tmp1C == tmp1 || tmp1C < limit) { + break; + } + + struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + int8_t xT = getval(x->type), xA = getval(x->a), xB = getval(x->b), xC = getval(x->c); + int8_t yA = getval(y->a); + + setval(x->type, getval(y->type)); + setval(x->b, getval(y->b)); + setval(x->c, getval(y->c)); + + setval(y->type, xT); + setval(y->b, xB); + setval(y->c, xC); + + tmp1B = limit; + while(tmp1B != -1) { + struct vm_top_t *z = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + + if(gettype(z->type) != OP_GETVAL && + gettype(z->type) != OP_CALL) { + if(getval(z->c) == xA) { + setval(z->c, yA); + } else if(getval(z->c) == yA) { + setval(z->c, xA); + } + if(getval(z->b) == xA) { + setval(z->b, yA); + } else if(getval(z->b) == yA) { + setval(z->b, xA); + } + } + tmp1B = bc_next(obj, tmp1B); + } + } + } + } + } + + x = (struct vm_top_t *)&obj->bc.buffer[nrbytes]; + if(is_op_and_math(gettype(x->type))) { + tmp1 = nrbytes; + tmp1B = -1; + + if(getval(x->b) >= 0) { + tmp1B = tmp1; + while((tmp1B = bc_before(obj, tmp1B)) != -1) { + struct vm_top_t *xB = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + if(getval(x->b) == getval(xB->a)) { + break; + } + } + } + + if(tmp1B != -1 && tmp1B >= limit) { + tmp1C = bc_find_math_dep(obj, tmp1, getval(x->c)); + struct vm_top_t *xB = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + struct vm_top_t *xC = NULL; + if(tmp1C != -1) { + xC = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + } + + if(xC == NULL || gettype(xB->type) == OP_GETVAL || (((int8_t)getval(xB->b) >= 0)+((int8_t)getval(xB->c) >= 0) < ((int8_t)getval(xC->b) >= 0)+((int8_t)getval(xC->c) >= 0))) { + while(tmp1B < tmp1) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + if(!is_op_and_math(gettype(x->type)) && gettype(x->type) != OP_GETVAL) { + break; + } + + if((tmp1B = bc_next(obj, tmp1B)) == -1) { + /* LCOV_EXCL_START*/ + logprintf_P(F("FATAL: Internal error in %s #%d %d"), __FUNCTION__, __LINE__); + exit(-1); + /* LCOV_EXCL_STOP*/ + } + + if(tmp1B == tmp1 || tmp1B < limit) { + break; + } + + struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1B]; + int8_t xT = getval(x->type), xA = getval(x->a), xB = getval(x->b), xC = getval(x->c); + int8_t yA = getval(y->a); + + setval(x->type, getval(y->type)); + setval(x->b, getval(y->b)); + setval(x->c, getval(y->c)); + + setval(y->type, xT); + setval(y->b, xB); + setval(y->c, xC); + + tmp1C = limit; + while(tmp1C != -1) { + struct vm_top_t *z = (struct vm_top_t *)&obj->bc.buffer[tmp1C]; + + if(gettype(z->type) != OP_GETVAL && + gettype(z->type) != OP_CALL) { + if(getval(z->c) == xA) { + setval(z->c, yA); + } else if(getval(z->c) == yA) { + setval(z->c, xA); + } + if(getval(z->b) == xA) { + setval(z->b, yA); + } else if(getval(z->b) == yA) { + setval(z->b, xA); + } + } + tmp1C = bc_next(obj, tmp1C); + } + } + } + } + } + + nrbytes = bc_before(obj, nrbytes); + } +} + static int32_t bc_parse_math_order(char **text, struct rules_t *obj, uint16_t *pos, uint8_t *cnt) { uint16_t start = 0, len = 0; - int32_t first = 0, step = 0, bc_in = 0, heap_in = 0; + int32_t first = 0, step = 0, bc_in = 0, heap_in = 0, limit = 0; int16_t d = 0; uint8_t a = 0, b = 0, c = 0; @@ -2279,6 +2606,7 @@ static int32_t bc_parse_math_order(char **text, struct rules_t *obj, uint16_t *p } break; case TVAR: case VNULL: + case TSTRING: case TNUMBER1: case TNUMBER2: case TNUMBER3: @@ -2309,8 +2637,19 @@ static int32_t bc_parse_math_order(char **text, struct rules_t *obj, uint16_t *p step = bc_parent(obj, rule_operators[idx].opcode, ++(*cnt), heap_in, d); - if(first == 0) { - first = step; + if(*cnt > (INT8_MAX/2)) { + logprintf_P(F("ERROR: Too many stacked conditions")); + return -1; + } + + uint16_t nrbytes = getval(obj->bc.nrbytes); + while(nrbytes > 0) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[nrbytes]; + if(getval(x->a) == 1) { + limit = nrbytes; + break; + } + nrbytes = bc_before(obj, nrbytes); } if(step >= 0 && bc_in >= 0 && bc_in >= first && step >= first) { @@ -2340,139 +2679,128 @@ static int32_t bc_parse_math_order(char **text, struct rules_t *obj, uint16_t *p uint8_t a_a = rule_operators[a_is_op].associativity; if(a_p > b_p || (b_p == a_p && a_a == 2)) { + int32_t tmp1 = bc_in, tmp2 = step, tmp2B = -1; + if(a_a == 1) { - int32_t tmp1 = step, tmp2 = step; - uint8_t runs = 1, i = 0; + tmp1 = step, tmp2 = step; - tmp1 = bc_before(obj, step); - if(tmp1 >= 0) { - if(gettype(obj->bc.buffer[tmp1]) == OP_GETVAL) { - runs = 2; - } + tmp1 = bc_before(obj, tmp2); + while(tmp2 >= limit && tmp1 >= limit) { - for(i=0;ibc.buffer[tmp2]; - tmp1 = bc_before(obj, tmp2); - while(tmp2 >= bc_in && tmp2 != bc_in && tmp1 >= 0) { - struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp2]; - struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1]; - uint8_t typeX = gettype(obj->bc.buffer[tmp2]); - uint8_t typeY = gettype(obj->bc.buffer[tmp1]); + if(gettype(x->type) != OP_GETVAL) { + int8_t a = (int8_t)getval(x->type), d = (int8_t)getval(x->c); + tmp2B = bc_find_math_dep(obj, tmp2, getval(x->b)); + if(tmp2B == -1) { + break; + } - if(typeY == OP_GETVAL || typeX == OP_GETVAL) { - int8_t a = (int8_t)getval(x->type), b = (int8_t)getval(x->a), c = (int8_t)getval(x->b), d = (int8_t)getval(x->c); + struct vm_top_t *z = (struct vm_top_t *)&obj->bc.buffer[tmp2B]; + if(is_op_and_math(gettype(x->type)) && is_op_and_math(gettype(z->type))) { + for(i=0;itype) == rule_operators[i].opcode) { + a_is_op = i; + break; + } + } - setval(x->type, getval(y->type)); - setval(x->a, (int8_t)getval(y->a)); - setval(x->b, (int8_t)getval(y->b)); - setval(x->c, (int8_t)getval(y->c)); + for(i=0;itype) == rule_operators[i].opcode) { + b_is_op = i; + break; + } + } - setval(y->type, a); - setval(y->a, b); - setval(y->b, c); - setval(y->c, d); - } else { - int8_t a = (int8_t)getval(x->type), b = (int8_t)getval(x->a), c = (int8_t)getval(x->b), d = (int8_t)getval(x->c); + b_p = rule_operators[b_is_op].precedence; + a_p = rule_operators[a_is_op].precedence; + a_a = rule_operators[a_is_op].associativity; - setval(x->type, getval(y->type)); - setval(y->type, a); + if(get_group(obj->bc.buffer[tmp2B]) != 0) { + break; + } - setval(x->a, b); - setval(x->b, (int8_t)getval(y->b)); - setval(x->c, c); + if(!(a_p > b_p || (b_p == a_p && a_a == 2))) { + break; + } - setval(y->a, c); - setval(y->b, (int8_t)getval(y->c)); - setval(y->c, d); + if(gettype(z->type) == OP_GETVAL) { + break; } + setval(x->type, getval(z->type)); + setval(x->b, getval(z->b)); + setval(x->c, getval(z->a)); + + setval(z->type, a); + setval(z->b, getval(z->c)); + setval(z->c, d); + + bc_math_move_closest(obj, limit); + + tmp2 = tmp2B; + } else { tmp2 = tmp1; - tmp1 = bc_before(obj, tmp2); } + } else { + tmp2 = tmp1; } + tmp1 = bc_before(obj, tmp2); } } else { - uint16_t tmp = step; - tmp = bc_in; - bc_in = bc_before(obj, bc_in); - while(tmp >= 0 && tmp >= first && bc_in >= 0) { - struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp]; - struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[bc_in]; - uint8_t type = gettype(obj->bc.buffer[bc_in]); - uint8_t a_immu = get_group(obj->bc.buffer[step]); - uint8_t b_immu = get_group(obj->bc.buffer[bc_in]); - - if(type == OP_GETVAL) { - bc_in = bc_before(obj, bc_in); - continue; - } - - if(a_immu > 0 || b_immu > 0) { - break; - } + tmp1 = step, tmp2 = step; + tmp1 = bc_before(obj, tmp2); + while(tmp2 >= limit && tmp1 >= limit) { + struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp2]; - if((int8_t)getval(y->a) != (int8_t)getval(x->c)) { - break; - } + if(is_op_and_math(gettype(x->type))) { + for(i=0;itype) == rule_operators[i].opcode) { + a_is_op = i; + break; + } + } - tmp = bc_in; + a_a = rule_operators[a_is_op].associativity; + if(a_a == 2) { + int8_t a = (int8_t)getval(x->type), d = (int8_t)getval(x->c); - if(bc_in > 0) { - bc_in = bc_before(obj, bc_in); - } else { - break; - } - } + tmp2B = bc_find_math_dep(obj, tmp2, getval(x->b)); + if(tmp2B == -1) { + tmp2 = tmp1; + tmp1 = bc_before(obj, tmp2); + continue; + } - uint16_t tmp1 = step, tmp2 = step; - uint8_t runs = 1, i = 0; + struct vm_top_t *z = (struct vm_top_t *)&obj->bc.buffer[tmp2B]; - tmp1 = bc_before(obj, tmp2); - if(tmp1 >= 0) { - if(gettype(obj->bc.buffer[tmp1]) == OP_GETVAL) { - runs = 2; - } + if(get_group(obj->bc.buffer[tmp2B]) != 0) { + tmp2 = tmp1; + tmp1 = bc_before(obj, tmp2); + continue; + } - for(i=0;i= tmp && tmp2 != tmp && tmp1 >= 0) { - struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp2]; - struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1]; - uint8_t typeX = gettype(obj->bc.buffer[tmp2]); - uint8_t typeY = gettype(obj->bc.buffer[tmp1]); - - if(typeY == OP_GETVAL || typeX == OP_GETVAL) { - int8_t a = (int8_t)getval(x->type), b = (int8_t)getval(x->a), c = (int8_t)getval(x->b), d = (int8_t)getval(x->c); - - setval(x->type, getval(y->type)); - setval(x->a, (int8_t)getval(y->a)); - setval(x->b, (int8_t)getval(y->b)); - setval(x->c, (int8_t)getval(y->c)); - - setval(y->type, a); - setval(y->a, b); - setval(y->b, c); - setval(y->c, d); - } else { - int8_t a = (int8_t)getval(x->type), d = (int8_t)getval(x->c); - - setval(x->type, getval(y->type)); - setval(x->b, (int8_t)getval(y->b)); - setval(x->c, (int8_t)getval(y->a)); - - setval(y->type, a); - setval(y->b, (int8_t)getval(y->c)); - setval(y->c, d); + if(getval(z->type) == OP_GETVAL) { + break; } + setval(x->type, getval(z->type)); + setval(x->b, getval(z->b)); + setval(x->c, getval(z->a)); + + setval(z->type, a); + setval(z->b, getval(z->c)); + setval(z->c, d); + + bc_math_move_closest(obj, limit); + } else { tmp2 = tmp1; - tmp1 = bc_before(obj, tmp2); } + } else { + tmp2 = tmp1; } + tmp1 = bc_before(obj, tmp2); } } } @@ -2482,84 +2810,6 @@ static int32_t bc_parse_math_order(char **text, struct rules_t *obj, uint16_t *p bc_in = step; } - /* - * Move all operations as close to it's - * matching operation as possible - */ - uint8_t l = 0; - for(l=0;l<2;l++) { - uint8_t upd = 1; - while(upd == 1) { - int32_t i = 0, a = 0; - upd = 0; - - for(i=first;ibc.buffer[i]; - if(is_op_and_math(gettype(obj->bc.buffer[i])) || - gettype(obj->bc.buffer[i]) == OP_GETVAL) { - for(a=bc_next(obj, i);a<=step;a = bc_next(obj, a)) { - if(a == -1) { - break; - } - struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[a]; - if(((int8_t)getval(z->a) == (int8_t)getval(y->b) && is_op_and_math(gettype(y->type)) /* || (int8_t)getval(z->a) == (int8_t)getval(y->c)*/)) { - if(((a-i)/sizeof(struct vm_top_t)) > 2) { - upd = 1; - } - break; - } - } - } - if(upd == 1) { - break; - } - } - if(upd == 1) { - int32_t tmp1 = a, tmp2 = a; - uint8_t runs = 1, t = 0; - - tmp1 = bc_before(obj, i); - a = bc_before(obj, a); - if(tmp1 >= 0 && a >= 0) { - if(gettype(obj->bc.buffer[tmp1]) == OP_GETVAL) { - runs = 2; - } - - for(t=0;t= 0 && - tmp2 <= (int32_t)(a-(t*sizeof(struct vm_top_t))) && - tmp2 != (int32_t)(a-(t*sizeof(struct vm_top_t))) - ) { - struct vm_top_t *x = (struct vm_top_t *)&obj->bc.buffer[tmp2]; - struct vm_top_t *y = (struct vm_top_t *)&obj->bc.buffer[tmp1]; - - int8_t p = (int8_t)getval(x->type), b = (int8_t)getval(x->a), c = (int8_t)getval(x->b), d = (int8_t)getval(x->c); - - setval(x->type, getval(y->type)); - setval(x->a, (int8_t)getval(y->a)); - setval(x->b, (int8_t)getval(y->b)); - setval(x->c, (int8_t)getval(y->c)); - - setval(y->type, p); - setval(y->a, b); - setval(y->b, c); - setval(y->c, d); - - tmp2 = tmp1; - tmp1 = bc_next(obj, tmp2); - } - } - } - } - } - } - return step; } @@ -2761,9 +3011,8 @@ static int16_t rule_create(char **text, struct rules_t *obj) { while(loop) { #ifdef ESP8266 - ESP.wdtFeed(); //keep the dog happy loading large rules on the esp8266 + ESP.wdtFeed();; #endif - #ifdef DEBUG printf("%s %d %d %d %d %s\n", __FUNCTION__, __LINE__, depth, pos, getval(obj->bc.nrbytes), token_names[go].name); #endif @@ -3941,7 +4190,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { uint8_t b = vm_val_pos((int8_t)getval(node->b)); uint8_t c = vm_val_pos((int8_t)getval(node->c)); -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) if((int8_t)getval(node->a) >= 0) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; @@ -3954,11 +4203,11 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } - if(b > obj->heap->nrbytes) { + if(b > getval(obj->heap->nrbytes)) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } - if(c > obj->heap->nrbytes) { + if(c > getval(obj->heap->nrbytes)) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } @@ -4241,7 +4490,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { /*****************/ STEP_JMP: { struct vm_top_t *node = (struct vm_top_t *)&obj->bc.buffer[pos]; -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) /* LCOV_EXCL_START*/ if((uint8_t)getval(node->a) <= 0) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); @@ -4324,7 +4573,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { uint16_t b = (int8_t)getval(node->b)*sizeof(struct vm_vchar_t); uint16_t a = vm_val_pos(getval(node->a)); -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) if((int8_t)getval(node->b) < 0) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; @@ -4333,7 +4582,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } - if(a > obj->heap->nrbytes) { + if(a > getval(obj->heap->nrbytes)) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } @@ -4343,7 +4592,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { rule_options.vm_value_get(obj); -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) /* LCOV_EXCL_START*/ if(rules_gettop(obj) < 2) { logprintf_P(F("FATAL: Internal error in %s #%d"), __FUNCTION__, __LINE__); @@ -4417,7 +4666,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { STEP_SETVAL: { struct vm_top_t *node = (struct vm_top_t *)&obj->bc.buffer[pos]; -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) if((int8_t)getval(node->a) < 0) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; @@ -4432,12 +4681,14 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { uint16_t a = (int8_t)getval(node->a)*sizeof(struct vm_vchar_t); uint16_t b = vm_val_pos((int8_t)getval(node->b)); -#ifdef DEBUG - if(b > obj->heap->nrbytes) { +#if defined(DEBUG) || defined(COVERALLS) + if(b > getval(obj->heap->nrbytes)) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } +#endif +#ifdef DEBUG struct vm_vchar_t *var = (struct vm_vchar_t *)&varstack->buffer[a]; switch(gettype(obj->heap->buffer[b])) { case VINTEGER: { @@ -4474,7 +4725,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { uint16_t a = (int8_t)getval(node->a)*sizeof(struct vm_vchar_t); uint16_t b = (int8_t)(getval(node->b)-1)*sizeof(struct vm_vchar_t); -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) if(b > varstack->nrbytes) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; @@ -4519,8 +4770,8 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { if((int8_t)getval(node->a) < 0) { uint16_t a = vm_val_pos((int8_t)getval(node->a)); -#ifdef DEBUG - if(a > obj->heap->nrbytes) { +#if defined(DEBUG) || defined(COVERALLS) + if(a > getval(obj->heap->nrbytes)) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } @@ -4530,7 +4781,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { } else { uint16_t a = (uint8_t)(getval(node->a)-1)*sizeof(struct vm_vchar_t); -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) if(a > varstack->nrbytes) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; @@ -4553,7 +4804,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { uint16_t b = (int8_t)getval(node->b); uint16_t c = (int8_t)getval(node->c); -#ifdef DEBUG +#if defined(DEBUG) || defined(COVERALLS) if((int8_t)getval(node->a) >= 0) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; @@ -4566,7 +4817,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } - if(a > obj->heap->nrbytes) { + if(a > getval(obj->heap->nrbytes)) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } @@ -4851,7 +5102,6 @@ static void print_bytecode(struct rules_t *obj) { printf("\n"); } } -/*LCOV_EXCL_STOP*/ #endif #if defined(DEBUG) || defined(COVERALLS) @@ -5224,6 +5474,7 @@ int8_t rule_initialize(struct pbuf *input, struct rules_t ***rules, uint8_t *nrr /*LCOV_EXCL_STOP*/ if(stack != NULL) { +/*LCOV_EXCL_START*/ if((getval(stack->bufsize) % 4) != 0) { #if defined(ESP8266) || defined(ESP32) Serial.printf("Rules AST not 4 byte aligned!\n"); @@ -5231,6 +5482,7 @@ int8_t rule_initialize(struct pbuf *input, struct rules_t ***rules, uint8_t *nrr printf("Rules AST not 4 byte aligned!\n"); #endif exit(-1); +/*LCOV_EXCL_STOP*/ } }