From 90446464736e122cd77ff00844a3e0218c6302b3 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sat, 30 Aug 2014 21:23:43 +1000 Subject: [PATCH 1/2] COMMON: fix uds regression --- src/common/ceval.c | 128 +++++++++++++++--------------------------- src/common/hotspots.h | 18 +++--- src/common/sberr.c | 4 ++ src/common/sberr.h | 28 ++++----- 4 files changed, 73 insertions(+), 105 deletions(-) diff --git a/src/common/ceval.c b/src/common/ceval.c index 25fa5300..65f1b539 100644 --- a/src/common/ceval.c +++ b/src/common/ceval.c @@ -10,43 +10,46 @@ #include "common/smbas.h" #include "common/bc.h" -extern void sc_raise(const char *fmt, ...); -void cev_log(void); +static bc_t *bc_in; +static bc_t *bc_out; + +#define cev_add1(x) bc_add_code(bc_out, (x)) +#define cev_add2(x, y) { bc_add1(bc_out, (x)); bc_add1(bc_out, (y)); } +#define cev_add_addr(x) bc_add_addr(bc_out, (x)) +#define IP bc_in->cp +#define CODE(x) bc_in->ptr[(x)] +#define CODE_PEEK() CODE(IP) +#define IF_ERR_RTN if (comp_error) return -#define IP bc_in->cp -#define CODE(x) bc_in->ptr[(x)] -#define CODE_PEEK() CODE(IP) +void cev_log(void); void cev_udp(void) { sc_raise("(EXPR): UDP INSIDE EXPR"); } void cev_missing_rp(void) { - sc_raise("(EXPR): MISSING ')'"); + sc_raise("(EXPR): MISSING ')' %d", IP); } void cev_opr_err(void) { sc_raise("(EXPR): SYNTAX ERROR (1st OP)"); } -static bc_t *bc_in; -static bc_t *bc_out; - -#define cev_add1(x) bc_add_code(bc_out, (x)) -#define cev_add2(x, y) { bc_add1(bc_out, (x)); bc_add1(bc_out, (y)); } -#define cev_add_addr(x) bc_add_addr(bc_out, (x)) +void cev_prim_str() { + dword len; + memcpy(&len, bc_in->ptr + bc_in->cp, OS_STRLEN); + IP += OS_STRLEN; + bc_add_dword(bc_out, len); + bc_add_n(bc_out, bc_in->ptr + bc_in->cp, len); + IP += len; +} /* * prim */ void cev_prim() { - byte code; - dword len; - - if (comp_error) { - return; - } - code = CODE(IP); + IF_ERR_RTN; + byte code = CODE(IP); IP++; cev_add1(code); switch (code) { @@ -59,11 +62,7 @@ void cev_prim() { IP += OS_REALSZ; break; case kwTYPE_STR: - memcpy(&len, bc_in->ptr + bc_in->cp, OS_STRLEN); - IP += OS_STRLEN; - bc_add_dword(bc_out, len); - bc_add_n(bc_out, bc_in->ptr + bc_in->cp, len); - IP += len; + cev_prim_str(); break; case kwTYPE_CALL_UDP: cev_udp(); @@ -78,6 +77,13 @@ void cev_prim() { bc_add_n(bc_out, bc_in->ptr + bc_in->cp, ADDRSZ); // 1 addr IP += ADDRSZ; + while (CODE_PEEK() == kwTYPE_UDS_EL) { + cev_add1(kwTYPE_UDS_EL); + cev_add1(kwTYPE_STR); + IP += 2; + cev_prim_str(); + } + // support multiple () while (CODE_PEEK() == kwTYPE_LEVEL_BEGIN) { cev_add1(kwTYPE_LEVEL_BEGIN); @@ -145,12 +151,7 @@ void cev_prim() { } } - if (CODE_PEEK() == kwTYPE_UDS_EL) { - // code + string - cev_add1(CODE(IP)); - IP++; - cev_prim(); - } else if (CODE_PEEK() != kwTYPE_LEVEL_END) { + if (CODE_PEEK() != kwTYPE_LEVEL_END) { cev_missing_rp(); } else { cev_add1(kwTYPE_LEVEL_END); @@ -164,29 +165,19 @@ void cev_prim() { * parenthesis */ void cev_parenth() { - if (comp_error) { - return; - } + IF_ERR_RTN; if (CODE_PEEK() == kwTYPE_LEVEL_BEGIN) { cev_add1(kwTYPE_LEVEL_BEGIN); IP++; cev_log(); // R = cev_log - - if (comp_error) { - return; - } + IF_ERR_RTN; if (CODE_PEEK() == kwTYPE_SEP) { cev_add1(kwTYPE_SEP); IP++; cev_add1(CODE(IP)); IP++; - } else if (CODE_PEEK() == kwTYPE_UDS_EL) { - // code + string - cev_add1(CODE(IP)); - IP++; - cev_prim(); } else if (CODE_PEEK() != kwTYPE_LEVEL_END) { cev_missing_rp(); return; @@ -205,9 +196,7 @@ void cev_parenth() { void cev_unary() { char op; - if (comp_error) { - return; - } + IF_ERR_RTN; if (CODE(IP) == kwTYPE_UNROPR || CODE(IP) == kwTYPE_ADDOPR) { op = CODE(IP + 1); IP += 2; @@ -227,17 +216,13 @@ void cev_unary() { void cev_pow() { cev_unary(); // R = cev_unary - if (comp_error) { - return; - } + IF_ERR_RTN; while (CODE(IP) == kwTYPE_POWOPR) { IP += 2; cev_add1(kwTYPE_EVPUSH); // PUSH R cev_unary(); // R = cev_unary - if (comp_error) { - return; - } + IF_ERR_RTN; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_POWOPR, '^'); // R = LEFT op R } @@ -249,9 +234,7 @@ void cev_pow() { void cev_mul() { cev_pow(); // R = cev_pow() - if (comp_error) { - return; - } + IF_ERR_RTN; while (CODE(IP) == kwTYPE_MULOPR) { char op; @@ -260,9 +243,7 @@ void cev_mul() { cev_add1(kwTYPE_EVPUSH); // PUSH R cev_pow(); - if (comp_error) { - return; - } + IF_ERR_RTN; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_MULOPR, op); // R = LEFT op R } @@ -274,9 +255,7 @@ void cev_mul() { void cev_add() { cev_mul(); // R = cev_mul() - if (comp_error) { - return; - } + IF_ERR_RTN; while (CODE(IP) == kwTYPE_ADDOPR) { char op; @@ -286,8 +265,7 @@ void cev_add() { cev_add1(kwTYPE_EVPUSH); // PUSH R cev_mul(); // R = cev_mul - if (comp_error) - return; + IF_ERR_RTN; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_ADDOPR, op); // R = LEFT op R @@ -300,9 +278,7 @@ void cev_add() { void cev_cmp() { cev_add(); // R = cev_add() - if (comp_error) { - return; - } + IF_ERR_RTN; while (CODE(IP) == kwTYPE_CMPOPR) { char op; @@ -310,11 +286,8 @@ void cev_cmp() { op = CODE(IP); IP++; cev_add1(kwTYPE_EVPUSH); // PUSH R - cev_add(); // R = cev_add() - if (comp_error) - return; - + IF_ERR_RTN; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_CMPOPR, op); // R = LEFT op R } @@ -325,9 +298,7 @@ void cev_cmp() { */ void cev_log(void) { cev_cmp(); // R = cev_cmp() - if (comp_error) { - return; - } + IF_ERR_RTN; while (CODE(IP) == kwTYPE_LOGOPR) { char op; addr_t shortcut; @@ -336,17 +307,15 @@ void cev_log(void) { IP++; op = CODE(IP); IP++; - cev_add1(kwTYPE_EVPUSH); // PUSH R (push the left side result + cev_add1(kwTYPE_EVPUSH); // PUSH R (push the left side result cev_add1(kwTYPE_EVAL_SC); cev_add2(kwTYPE_LOGOPR, op); shortcut = bc_out->count; // shortcut jump target (calculated below) cev_add_addr(0); cev_cmp(); // right seg // R = cev_cmp() - if (comp_error) { - return; - } + IF_ERR_RTN; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_LOGOPR, op); // R = LEFT op R @@ -359,14 +328,12 @@ void cev_log(void) { * main */ void expr_parser(bc_t *bc_src) { - byte code; - // init bc_in = bc_src; bc_out = tmp_alloc(sizeof(bc_t)); bc_create(bc_out); - code = CODE_PEEK(); + byte code = CODE_PEEK(); // // empty! @@ -397,7 +364,6 @@ void expr_parser(bc_t *bc_src) { if (kw_check_evexit(code)) { // separator cev_add1(code); IP++; // add sep. - if (code == kwUSE) { cev_add_addr(0); // USE needs 2 ips @@ -416,11 +382,9 @@ void expr_parser(bc_t *bc_src) { IP++; } } - code = CODE_PEEK(); // next continue; } - cev_log(); // do it code = CODE_PEEK(); // next } diff --git a/src/common/hotspots.h b/src/common/hotspots.h index 36e1d6af..a18b63af 100644 --- a/src/common/hotspots.h +++ b/src/common/hotspots.h @@ -150,14 +150,18 @@ static inline var_t* code_getvarptr_parens(int until_parens) { if (code_peek() == kwTYPE_VAR) { code_skipnext(); var_p = tvar[code_getaddr()]; - switch (var_p->type) { - case V_HASH: - case V_ARRAY: + if (code_peek() == kwTYPE_UDS_EL) { var_p = code_resolve_varptr(var_p, until_parens); - break; - default: - if (!until_parens && code_peek() == kwTYPE_LEVEL_BEGIN) { - err_varisnotarray(); + } else { + switch (var_p->type) { + case V_HASH: + case V_ARRAY: + var_p = code_resolve_varptr(var_p, until_parens); + break; + default: + if (!until_parens && code_peek() == kwTYPE_LEVEL_BEGIN) { + err_varisnotarray(); + } } } } diff --git a/src/common/sberr.c b/src/common/sberr.c index 309838a5..b9ccdcb6 100644 --- a/src/common/sberr.c +++ b/src/common/sberr.c @@ -103,6 +103,7 @@ void err_stackunderflow(void) { rt_raise(ERR_STACK_UNDERFLOW); } +// generic stack error void err_stackmess() { rt_raise(ERR_STACK); } @@ -123,6 +124,7 @@ void err_typemismatch(void) { rt_raise(ERR_TYPE); } +// parameter with wrong value void err_argerr(void) { rt_raise(ERR_PARAM); } @@ -199,6 +201,7 @@ void err_parfmt(const char *fmt) { rt_raise(ERR_PARFMT, fmt); } +// UDP/F: parameter is 'by reference' so const not allowed void err_parm_byref(int n) { rt_raise(ERR_BYREF, n); } @@ -211,6 +214,7 @@ void err_fopen(void) { rt_raise(ERR_BAD_FILE_HANDLE); } +// no separator found void err_syntaxanysep(const char *seps) { rt_raise(ERR_SEP_FMT, seps); } diff --git a/src/common/sberr.h b/src/common/sberr.h index fb913d3b..2d61b48e 100644 --- a/src/common/sberr.h +++ b/src/common/sberr.h @@ -23,26 +23,22 @@ extern "C" { void sc_raise2(const char *sec, int scline, const char *buff); void rt_raise(const char *fmt, ...); -#define err_syntax() rt_raise("%s (%d): Syntax error!\n", __FILE__, __LINE__) -#define err_syntaxsep(c) rt_raise("%s (%d): Syntax error. Missing separator '%c'.\n", __FILE__, __LINE__, (c)) -#define err_missing_rp() rt_raise("%s (%d): Missing ')'.\n", __FILE__, __LINE__) -#define err_matdim() rt_raise("%s (%d): Dimension error.\n", __FILE__, __LINE__) -#define err_parm_num() rt_raise("%s (%d): Parameters error.\n", __FILE__, __LINE__) +#define err_syntax() rt_raise("%s (%d): Syntax error!\n", __FILE__, __LINE__) +#define err_syntaxsep(c) rt_raise("%s (%d): Syntax error. Missing separator '%c'.\n", __FILE__, __LINE__, (c)) +#define err_missing_rp() rt_raise("%s (%d): Missing ')'.\n", __FILE__, __LINE__) +#define err_matdim() rt_raise("%s (%d): Dimension error.\n", __FILE__, __LINE__) +#define err_parm_num() rt_raise("%s (%d): Parameters error.\n", __FILE__, __LINE__) -void err_typemismatch(void); // TYPE MISMATCH -void err_stackmess(void);// GENERIC STACK ERROR (if you play -// with GOTOs, you can create it -// easily) -void err_parm_byref(int n);// UDP/F: PARAMETER IS 'BY -// REFERENCE' SO CONSTANTS DOES -// NOT ALLOWED +void err_typemismatch(void); +void err_stackmess(void); +void err_parm_byref(int n); void err_notarray(void); void err_out_of_range(void); void err_missing_lp(void); void err_missing_sep(void); void err_division_by_zero(void); void err_matop(void); -void err_argerr(void);// Parameter with wrong value +void err_argerr(void); void err_stackoverflow(void); void err_stackunderflow(void); void err_arrmis_lp(void); @@ -61,7 +57,7 @@ void err_matsig(void); void err_stridx(int n); void err_parfmt(const char *fmt); void err_fopen(void); -void err_syntaxanysep(const char *seps);// No separator found +void err_syntaxanysep(const char *seps); void err_parsepoly(int idx, int mark); void err_bfn_err(long code); void err_gpf(addr_t addr, int bc); @@ -73,8 +69,8 @@ void err_run_err(const char *file); void err_invkw(addr_t addr, byte code); void err_ref_var(); -#define err_type_mismatch() err_typemismatch() -#define err_syntax_error() err_syntax() +#define err_type_mismatch() err_typemismatch() +#define err_syntax_error() err_syntax() // --- inf_xxx: information messages From abd0534b547db997d33f59ce3b4e8236f7405a88 Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sun, 31 Aug 2014 18:35:46 +1000 Subject: [PATCH 2/2] COMMON: fix uds regression --- src/common/ceval.c | 193 +++++++++++++++++++++++---------------------- src/common/eval.c | 3 +- src/common/scan.c | 1 - src/common/str.c | 18 ++--- 4 files changed, 109 insertions(+), 106 deletions(-) diff --git a/src/common/ceval.c b/src/common/ceval.c index 65f1b539..0b802555 100644 --- a/src/common/ceval.c +++ b/src/common/ceval.c @@ -28,11 +28,11 @@ void cev_udp(void) { } void cev_missing_rp(void) { - sc_raise("(EXPR): MISSING ')' %d", IP); + sc_raise("(EXPR): MISSING ')'"); } void cev_opr_err(void) { - sc_raise("(EXPR): SYNTAX ERROR (1st OP)"); + sc_raise("(EXPR): SYNTAX ERROR"); } void cev_prim_str() { @@ -44,6 +44,96 @@ void cev_prim_str() { IP += len; } +void cev_prim_uds() { + while (CODE_PEEK() == kwTYPE_UDS_EL) { + cev_add1(kwTYPE_UDS_EL); + cev_add1(kwTYPE_STR); + IP += 2; + cev_prim_str(); + } +} + +void cev_prim_var() { + bc_add_n(bc_out, bc_in->ptr + bc_in->cp, ADDRSZ); + IP += ADDRSZ; + + cev_prim_uds(); + + // support multiple () + while (CODE_PEEK() == kwTYPE_LEVEL_BEGIN) { + cev_add1(kwTYPE_LEVEL_BEGIN); + IP++; + if (CODE_PEEK() == kwTYPE_LEVEL_END) { + // NULL ARRAYS + cev_add1(kwTYPE_LEVEL_END); + IP++; + } else { + cev_log(); + + while (CODE_PEEK() == kwTYPE_SEP || CODE_PEEK() == kwTO) { + // DIM X(A TO B) + if (CODE_PEEK() == kwTYPE_SEP) { + cev_add1(CODE(IP)); + IP++; + } + cev_add1(CODE(IP)); + IP++; + + cev_log(); + } + + if (CODE_PEEK() != kwTYPE_LEVEL_END) { + cev_missing_rp(); + } else { + cev_add1(kwTYPE_LEVEL_END); + IP++; + } + } + } +} + +// function [(...)] +void cev_prim_args() { + cev_add1(kwTYPE_LEVEL_BEGIN); + IP++; + + if (CODE_PEEK() == kwTYPE_CALL_PTR) { + cev_add1(CODE(IP)); + IP++; + } + + if (CODE_PEEK() != kwTYPE_SEP) { + // empty parameter + cev_log(); + } + while (CODE_PEEK() == kwTYPE_SEP) { + // while parameters + cev_add1(CODE(IP)); + IP++; + cev_add1(CODE(IP)); + IP++; + + if (CODE_PEEK() != kwTYPE_LEVEL_END) { + if (CODE_PEEK() != kwTYPE_SEP) { + cev_log(); + } + } + } + + // after (), check for UDS field, eg foo(10).x + if (CODE_PEEK() == kwTYPE_UDS_EL) { + cev_prim_uds(); + cev_log(); + } + + if (CODE_PEEK() != kwTYPE_LEVEL_END) { + cev_missing_rp(); + } else { + cev_add1(kwTYPE_LEVEL_END); + IP++; + } +} + /* * prim */ @@ -74,90 +164,20 @@ void cev_prim() { IP += ADDRSZ; break; case kwTYPE_VAR: - bc_add_n(bc_out, bc_in->ptr + bc_in->cp, ADDRSZ); // 1 addr - IP += ADDRSZ; - - while (CODE_PEEK() == kwTYPE_UDS_EL) { - cev_add1(kwTYPE_UDS_EL); - cev_add1(kwTYPE_STR); - IP += 2; - cev_prim_str(); - } - - // support multiple () - while (CODE_PEEK() == kwTYPE_LEVEL_BEGIN) { - cev_add1(kwTYPE_LEVEL_BEGIN); - IP++; - if (CODE_PEEK() == kwTYPE_LEVEL_END) { // NULL ARRAYS - cev_add1(kwTYPE_LEVEL_END); - IP++; - } else { - cev_log(); - - while (CODE_PEEK() == kwTYPE_SEP || CODE_PEEK() == kwTO) { - // DIM X(A TO B) - if (CODE_PEEK() == kwTYPE_SEP) { - cev_add1(CODE(IP)); - IP++; - } - cev_add1(CODE(IP)); - IP++; - - cev_log(); - } - - if (CODE_PEEK() != kwTYPE_LEVEL_END) { - cev_missing_rp(); - } else { - cev_add1(kwTYPE_LEVEL_END); - IP++; - } - } - } + cev_prim_var(); break; case kwTYPE_CALL_UDF: // [udf1][addr2] case kwTYPE_CALLEXTF: // [lib][index] bc_add_n(bc_out, bc_in->ptr + bc_in->cp, ADDRSZ); - IP += ADDRSZ; - // no break here + IP += ADDRSZ; // no break here case kwTYPE_CALLF: // [code] bc_add_n(bc_out, bc_in->ptr + bc_in->cp, ADDRSZ); - IP += ADDRSZ; - // no break here + IP += ADDRSZ; // no break here default: - // function [(...)] if (CODE_PEEK() == kwTYPE_LEVEL_BEGIN) { - cev_add1(kwTYPE_LEVEL_BEGIN); - IP++; - - if (CODE_PEEK() == kwTYPE_CALL_PTR) { - cev_add1(CODE(IP)); - IP++; - } - - if (CODE_PEEK() != kwTYPE_SEP) { // empty parameter - cev_log(); - } - while (CODE_PEEK() == kwTYPE_SEP) { // while parameters - cev_add1(CODE(IP)); - IP++; - cev_add1(CODE(IP)); - IP++; - - if (CODE_PEEK() != kwTYPE_LEVEL_END) { - if (CODE_PEEK() != kwTYPE_SEP) { - cev_log(); - } - } - } - - if (CODE_PEEK() != kwTYPE_LEVEL_END) { - cev_missing_rp(); - } else { - cev_add1(kwTYPE_LEVEL_END); - IP++; - } + cev_prim_args(); } + break; }; } @@ -167,24 +187,7 @@ void cev_prim() { void cev_parenth() { IF_ERR_RTN; if (CODE_PEEK() == kwTYPE_LEVEL_BEGIN) { - cev_add1(kwTYPE_LEVEL_BEGIN); - IP++; - - cev_log(); // R = cev_log - IF_ERR_RTN; - - if (CODE_PEEK() == kwTYPE_SEP) { - cev_add1(kwTYPE_SEP); - IP++; - cev_add1(CODE(IP)); - IP++; - } else if (CODE_PEEK() != kwTYPE_LEVEL_END) { - cev_missing_rp(); - return; - } else { - cev_add1(kwTYPE_LEVEL_END); - IP++; - } + cev_prim_args(); } else { cev_prim(); } diff --git a/src/common/eval.c b/src/common/eval.c index e9f4f3b7..5539746a 100644 --- a/src/common/eval.c +++ b/src/common/eval.c @@ -1297,7 +1297,8 @@ void eval(var_t *r) { // normal exit return; } - rt_raise("UNKNOWN FUNC=%d", code); + rt_raise("UNKNOWN ERROR. IP:%d=0x%02X", IP, code); + hex_dump(prog_source, prog_length); }; // run-time error check diff --git a/src/common/scan.c b/src/common/scan.c index 3c21c24d..bad46e80 100644 --- a/src/common/scan.c +++ b/src/common/scan.c @@ -2582,7 +2582,6 @@ addr_t comp_next_bc_cmd(addr_t ip) { case kwGOSUB: case kwTYPE_LINE: case kwTYPE_VAR: // [addr|id] - case kwTYPE_UDS_EL: ip += ADDRSZ; break; case kwTYPE_PTR: diff --git a/src/common/str.c b/src/common/str.c index 8c110c4c..85c31765 100644 --- a/src/common/str.c +++ b/src/common/str.c @@ -52,10 +52,11 @@ char *trimdup(const char *str) { */ void str_alltrim(char *str) { char *buf; - - buf = trimdup(str); - strcpy(str, buf); - tmp_free(buf); + if (str && str[0]) { + buf = trimdup(str); + strcpy(str, buf); + tmp_free(buf); + } } /** @@ -237,13 +238,12 @@ char *q_strstr(const char *s1, const char *s2, const char *pairs) { * */ int is_alpha(int ch) { - if (ch == 0) + if (ch == 0) { return 0; - if ((ch > 64 && ch < 91) || (ch > 96 && ch < 123)) + } + if ((ch > 64 && ch < 91) || (ch > 96 && ch < 123)) { return -1; - // return - // (strchr("_���������������������������������������������������������", ch) - // != NULL); // Greek + } return (ch & 0x80); // +foreign }