aboutsummaryrefslogtreecommitdiff
path: root/miscutils/bc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils/bc.c')
-rw-r--r--miscutils/bc.c1647
1 files changed, 823 insertions, 824 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 0e5f26ce4..5b79b2db1 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -3090,184 +3090,184 @@ static BC_STATUS zbc_lex_token(void)
// This is the workhorse of the lexer.
switch (c) {
-// case '\0': // probably never reached
-// p->lex_inbuf--;
-// p->lex = XC_LEX_EOF;
-// break;
- case '\n':
- p->lex_line++;
- p->lex = XC_LEX_NLINE;
- break;
- case '\t':
- case '\v':
- case '\f':
- case '\r':
- case ' ':
- bc_lex_whitespace();
- break;
- case '!':
- parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
- if (p->lex == BC_LEX_OP_BOOL_NOT) {
- s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!");
- if (s) RETURN_STATUS(s);
- }
- break;
- case '"':
- s = zbc_lex_string();
- break;
- case '#':
- s = zbc_POSIX_does_not_allow("'#' script comments");
+// case '\0': // probably never reached
+// p->lex_inbuf--;
+// p->lex = XC_LEX_EOF;
+// break;
+ case '\n':
+ p->lex_line++;
+ p->lex = XC_LEX_NLINE;
+ break;
+ case '\t':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ bc_lex_whitespace();
+ break;
+ case '!':
+ parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
+ if (p->lex == BC_LEX_OP_BOOL_NOT) {
+ s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!");
if (s) RETURN_STATUS(s);
- bc_lex_lineComment();
- break;
- case '%':
- parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS);
- break;
- case '&':
- c2 = *p->lex_inbuf;
- if (c2 == '&') {
- s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&");
- if (s) RETURN_STATUS(s);
- p->lex_inbuf++;
- p->lex = BC_LEX_OP_BOOL_AND;
- } else {
- p->lex = XC_LEX_INVALID;
- s = bc_error_bad_character('&');
- }
- break;
- case '(':
- case ')':
- p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN);
- break;
- case '*':
- parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY);
- break;
- case '+':
- c2 = *p->lex_inbuf;
- if (c2 == '+') {
- p->lex_inbuf++;
- p->lex = BC_LEX_OP_INC;
- } else
- parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS);
- break;
- case ',':
- p->lex = BC_LEX_COMMA;
- break;
- case '-':
- c2 = *p->lex_inbuf;
- if (c2 == '-') {
- p->lex_inbuf++;
- p->lex = BC_LEX_OP_DEC;
- } else
- parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS);
- break;
- case '.':
- if (isdigit(*p->lex_inbuf))
- s = zbc_lex_number(c);
- else {
- p->lex = BC_LEX_KEY_LAST;
- s = zbc_POSIX_does_not_allow("'.' as 'last'");
- }
- break;
- case '/':
- c2 = *p->lex_inbuf;
- if (c2 == '*')
- s = zbc_lex_comment();
- else
- parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE);
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
+ }
+ break;
+ case '"':
+ s = zbc_lex_string();
+ break;
+ case '#':
+ s = zbc_POSIX_does_not_allow("'#' script comments");
+ if (s) RETURN_STATUS(s);
+ bc_lex_lineComment();
+ break;
+ case '%':
+ parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS);
+ break;
+ case '&':
+ c2 = *p->lex_inbuf;
+ if (c2 == '&') {
+ s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&");
+ if (s) RETURN_STATUS(s);
+ p->lex_inbuf++;
+ p->lex = BC_LEX_OP_BOOL_AND;
+ } else {
+ p->lex = XC_LEX_INVALID;
+ s = bc_error_bad_character('&');
+ }
+ break;
+ case '(':
+ case ')':
+ p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN);
+ break;
+ case '*':
+ parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY);
+ break;
+ case '+':
+ c2 = *p->lex_inbuf;
+ if (c2 == '+') {
+ p->lex_inbuf++;
+ p->lex = BC_LEX_OP_INC;
+ } else
+ parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS);
+ break;
+ case ',':
+ p->lex = BC_LEX_COMMA;
+ break;
+ case '-':
+ c2 = *p->lex_inbuf;
+ if (c2 == '-') {
+ p->lex_inbuf++;
+ p->lex = BC_LEX_OP_DEC;
+ } else
+ parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS);
+ break;
+ case '.':
+ if (isdigit(*p->lex_inbuf))
s = zbc_lex_number(c);
- break;
- case ';':
- p->lex = BC_LEX_SCOLON;
- break;
- case '<':
- parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT);
- break;
- case '=':
- parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN);
- break;
- case '>':
- parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT);
- break;
- case '[':
- case ']':
- p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET);
- break;
- case '\\':
- if (*p->lex_inbuf == '\n') {
- p->lex = XC_LEX_WHITESPACE;
- p->lex_inbuf++;
- } else
- s = bc_error_bad_character(c);
- break;
- case '^':
- parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER);
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- s = zbc_lex_identifier();
- break;
- case '{':
- case '}':
- p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE);
- break;
- case '|':
- c2 = *p->lex_inbuf;
- if (c2 == '|') {
- s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||");
- if (s) RETURN_STATUS(s);
- p->lex_inbuf++;
- p->lex = BC_LEX_OP_BOOL_OR;
- } else {
- p->lex = XC_LEX_INVALID;
- s = bc_error_bad_character(c);
- }
- break;
- default:
+ else {
+ p->lex = BC_LEX_KEY_LAST;
+ s = zbc_POSIX_does_not_allow("'.' as 'last'");
+ }
+ break;
+ case '/':
+ c2 = *p->lex_inbuf;
+ if (c2 == '*')
+ s = zbc_lex_comment();
+ else
+ parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE);
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ s = zbc_lex_number(c);
+ break;
+ case ';':
+ p->lex = BC_LEX_SCOLON;
+ break;
+ case '<':
+ parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT);
+ break;
+ case '=':
+ parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN);
+ break;
+ case '>':
+ parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT);
+ break;
+ case '[':
+ case ']':
+ p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET);
+ break;
+ case '\\':
+ if (*p->lex_inbuf == '\n') {
+ p->lex = XC_LEX_WHITESPACE;
+ p->lex_inbuf++;
+ } else
+ s = bc_error_bad_character(c);
+ break;
+ case '^':
+ parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER);
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ s = zbc_lex_identifier();
+ break;
+ case '{':
+ case '}':
+ p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE);
+ break;
+ case '|':
+ c2 = *p->lex_inbuf;
+ if (c2 == '|') {
+ s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||");
+ if (s) RETURN_STATUS(s);
+ p->lex_inbuf++;
+ p->lex = BC_LEX_OP_BOOL_OR;
+ } else {
p->lex = XC_LEX_INVALID;
s = bc_error_bad_character(c);
- break;
+ }
+ break;
+ default:
+ p->lex = XC_LEX_INVALID;
+ s = bc_error_bad_character(c);
+ break;
}
RETURN_STATUS(s);
@@ -3357,74 +3357,74 @@ static BC_STATUS zdc_lex_token(void)
// This is the workhorse of the lexer.
switch (c) {
-// case '\0': // probably never reached
-// p->lex = XC_LEX_EOF;
-// break;
- case '\n':
- // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE
- // (and "case '\n':" is not just empty here)
- // only to allow interactive dc have a way to exit
- // "parse" stage of "parse,execute" loop
- // on <enter>, not on _next_ token (which would mean
- // commands are not executed on pressing <enter>).
- // IOW: typing "1p<enter>" should print "1" _at once_,
- // not after some more input.
- p->lex_line++;
- p->lex = XC_LEX_NLINE;
- break;
- case '\t':
- case '\v':
- case '\f':
- case '\r':
- case ' ':
- bc_lex_whitespace();
- break;
- case '!':
- c2 = *p->lex_inbuf;
- if (c2 == '=')
- p->lex = XC_LEX_OP_REL_NE;
- else if (c2 == '<')
- p->lex = XC_LEX_OP_REL_LE;
- else if (c2 == '>')
- p->lex = XC_LEX_OP_REL_GE;
- else
- RETURN_STATUS(bc_error_bad_character(c));
- p->lex_inbuf++;
- break;
- case '#':
- bc_lex_lineComment();
- break;
- case '.':
- if (isdigit(*p->lex_inbuf))
- s = zbc_lex_number(c);
- else
- s = bc_error_bad_character(c);
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
+// case '\0': // probably never reached
+// p->lex = XC_LEX_EOF;
+// break;
+ case '\n':
+ // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE
+ // (and "case '\n':" is not just empty here)
+ // only to allow interactive dc have a way to exit
+ // "parse" stage of "parse,execute" loop
+ // on <enter>, not on _next_ token (which would mean
+ // commands are not executed on pressing <enter>).
+ // IOW: typing "1p<enter>" should print "1" _at once_,
+ // not after some more input.
+ p->lex_line++;
+ p->lex = XC_LEX_NLINE;
+ break;
+ case '\t':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ bc_lex_whitespace();
+ break;
+ case '!':
+ c2 = *p->lex_inbuf;
+ if (c2 == '=')
+ p->lex = XC_LEX_OP_REL_NE;
+ else if (c2 == '<')
+ p->lex = XC_LEX_OP_REL_LE;
+ else if (c2 == '>')
+ p->lex = XC_LEX_OP_REL_GE;
+ else
+ RETURN_STATUS(bc_error_bad_character(c));
+ p->lex_inbuf++;
+ break;
+ case '#':
+ bc_lex_lineComment();
+ break;
+ case '.':
+ if (isdigit(*p->lex_inbuf))
s = zbc_lex_number(c);
- break;
- case '[':
- s = zdc_lex_string();
- break;
- default:
- p->lex = XC_LEX_INVALID;
+ else
s = bc_error_bad_character(c);
- break;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ s = zbc_lex_number(c);
+ break;
+ case '[':
+ s = zdc_lex_string();
+ break;
+ default:
+ p->lex = XC_LEX_INVALID;
+ s = bc_error_bad_character(c);
+ break;
}
RETURN_STATUS(s);
@@ -3559,10 +3559,9 @@ static void bc_parse_reset(void)
static void bc_parse_free(void)
{
- IF_BC(BcParse *p = &G.prs;)
- IF_BC(bc_vec_free(&p->exits);)
- IF_BC(bc_vec_free(&p->conds);)
- IF_BC(bc_vec_free(&p->ops);)
+ IF_BC(bc_vec_free(&G.prs.exits);)
+ IF_BC(bc_vec_free(&G.prs.conds);)
+ IF_BC(bc_vec_free(&G.prs.ops);)
bc_vec_free(&G.prs.lex_strnumbuf);
}
@@ -3571,7 +3570,7 @@ static void bc_parse_create(size_t fidx)
BcParse *p = &G.prs;
memset(p, 0, sizeof(BcParse));
- bc_char_vec_init(&G.prs.lex_strnumbuf);
+ bc_char_vec_init(&p->lex_strnumbuf);
IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);)
IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);)
IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);)
@@ -3938,26 +3937,26 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr,
*nexprs = *nexprs + 1;
switch (type) {
- case XC_LEX_NAME:
- s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL);
- break;
- case BC_LEX_KEY_IBASE:
- case BC_LEX_KEY_LAST:
- case BC_LEX_KEY_OBASE:
- bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE);
- s = zbc_lex_next();
- break;
- case BC_LEX_KEY_SCALE:
- s = zbc_lex_next();
- if (s) RETURN_STATUS(s);
- if (p->lex == BC_LEX_LPAREN)
- s = bc_error_bad_token();
- else
- bc_parse_push(XC_INST_SCALE);
- break;
- default:
+ case XC_LEX_NAME:
+ s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL);
+ break;
+ case BC_LEX_KEY_IBASE:
+ case BC_LEX_KEY_LAST:
+ case BC_LEX_KEY_OBASE:
+ bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE);
+ s = zbc_lex_next();
+ break;
+ case BC_LEX_KEY_SCALE:
+ s = zbc_lex_next();
+ if (s) RETURN_STATUS(s);
+ if (p->lex == BC_LEX_LPAREN)
s = bc_error_bad_token();
- break;
+ else
+ bc_parse_push(XC_INST_SCALE);
+ break;
+ default:
+ s = bc_error_bad_token();
+ break;
}
if (!s) bc_parse_push(inst);
@@ -4489,74 +4488,74 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed)
dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex);
switch (p->lex) {
- case XC_LEX_OP_MINUS:
- case BC_LEX_OP_INC:
- case BC_LEX_OP_DEC:
- case BC_LEX_OP_BOOL_NOT:
- case BC_LEX_LPAREN:
- case XC_LEX_NAME:
- case XC_LEX_NUMBER:
- case BC_LEX_KEY_IBASE:
- case BC_LEX_KEY_LAST:
- case BC_LEX_KEY_LENGTH:
- case BC_LEX_KEY_OBASE:
- case BC_LEX_KEY_READ:
- case BC_LEX_KEY_SCALE:
- case BC_LEX_KEY_SQRT:
- s = zbc_parse_expr(BC_PARSE_PRINT);
- break;
- case XC_LEX_STR:
- s = zbc_parse_pushSTR();
- bc_parse_push(XC_INST_PRINT_STR);
- break;
- case BC_LEX_KEY_BREAK:
- case BC_LEX_KEY_CONTINUE:
- s = zbc_parse_break_or_continue(p->lex);
- break;
- case BC_LEX_KEY_FOR:
- s = zbc_parse_for();
- break;
- case BC_LEX_KEY_HALT:
- bc_parse_push(BC_INST_HALT);
- s = zbc_lex_next();
- break;
- case BC_LEX_KEY_IF:
- s = zbc_parse_if();
- break;
- case BC_LEX_KEY_LIMITS:
- // "limits" is a compile-time command,
- // the output is produced at _parse time_.
- printf(
- "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n"
- "BC_DIM_MAX = "BC_MAX_DIM_STR "\n"
- "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n"
- "BC_STRING_MAX = "BC_MAX_STRING_STR"\n"
- "BC_NAME_MAX = "BC_MAX_NAME_STR "\n"
- "BC_NUM_MAX = "BC_MAX_NUM_STR "\n"
- "MAX Exponent = "BC_MAX_EXP_STR "\n"
- "Number of vars = "BC_MAX_VARS_STR "\n"
- );
- s = zbc_lex_next();
- break;
- case BC_LEX_KEY_PRINT:
- s = zbc_parse_print();
- break;
- case BC_LEX_KEY_QUIT:
- // "quit" is a compile-time command. For example,
- // "if (0 == 1) quit" terminates when parsing the statement,
- // not when it is executed
- QUIT_OR_RETURN_TO_MAIN;
- case BC_LEX_KEY_RETURN:
- if (!p->in_funcdef)
- RETURN_STATUS(bc_error("'return' not in a function"));
- s = zbc_parse_return();
- break;
- case BC_LEX_KEY_WHILE:
- s = zbc_parse_while();
- break;
- default:
- s = bc_error_bad_token();
- break;
+ case XC_LEX_OP_MINUS:
+ case BC_LEX_OP_INC:
+ case BC_LEX_OP_DEC:
+ case BC_LEX_OP_BOOL_NOT:
+ case BC_LEX_LPAREN:
+ case XC_LEX_NAME:
+ case XC_LEX_NUMBER:
+ case BC_LEX_KEY_IBASE:
+ case BC_LEX_KEY_LAST:
+ case BC_LEX_KEY_LENGTH:
+ case BC_LEX_KEY_OBASE:
+ case BC_LEX_KEY_READ:
+ case BC_LEX_KEY_SCALE:
+ case BC_LEX_KEY_SQRT:
+ s = zbc_parse_expr(BC_PARSE_PRINT);
+ break;
+ case XC_LEX_STR:
+ s = zbc_parse_pushSTR();
+ bc_parse_push(XC_INST_PRINT_STR);
+ break;
+ case BC_LEX_KEY_BREAK:
+ case BC_LEX_KEY_CONTINUE:
+ s = zbc_parse_break_or_continue(p->lex);
+ break;
+ case BC_LEX_KEY_FOR:
+ s = zbc_parse_for();
+ break;
+ case BC_LEX_KEY_HALT:
+ bc_parse_push(BC_INST_HALT);
+ s = zbc_lex_next();
+ break;
+ case BC_LEX_KEY_IF:
+ s = zbc_parse_if();
+ break;
+ case BC_LEX_KEY_LIMITS:
+ // "limits" is a compile-time command,
+ // the output is produced at _parse time_.
+ printf(
+ "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n"
+ "BC_DIM_MAX = "BC_MAX_DIM_STR "\n"
+ "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n"
+ "BC_STRING_MAX = "BC_MAX_STRING_STR"\n"
+ "BC_NAME_MAX = "BC_MAX_NAME_STR "\n"
+ "BC_NUM_MAX = "BC_MAX_NUM_STR "\n"
+ "MAX Exponent = "BC_MAX_EXP_STR "\n"
+ "Number of vars = "BC_MAX_VARS_STR "\n"
+ );
+ s = zbc_lex_next();
+ break;
+ case BC_LEX_KEY_PRINT:
+ s = zbc_parse_print();
+ break;
+ case BC_LEX_KEY_QUIT:
+ // "quit" is a compile-time command. For example,
+ // "if (0 == 1) quit" terminates when parsing the statement,
+ // not when it is executed
+ QUIT_OR_RETURN_TO_MAIN;
+ case BC_LEX_KEY_RETURN:
+ if (!p->in_funcdef)
+ RETURN_STATUS(bc_error("'return' not in a function"));
+ s = zbc_parse_return();
+ break;
+ case BC_LEX_KEY_WHILE:
+ s = zbc_parse_while();
+ break;
+ default:
+ s = bc_error_bad_token();
+ break;
}
dbg_lex_done("%s:%d done", __func__, __LINE__);
@@ -4612,162 +4611,162 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags)
get_token = false;
s = BC_STATUS_SUCCESS;
switch (t) {
- case BC_LEX_OP_INC:
- case BC_LEX_OP_DEC:
- dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__);
- s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags);
- rprn = bin_last = false;
- //get_token = false; - already is
- break;
- case XC_LEX_OP_MINUS:
- dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__);
- s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs);
- rprn = false;
- //get_token = false; - already is
- bin_last = (prev == XC_INST_MINUS);
- break;
- case BC_LEX_OP_ASSIGN_POWER:
- case BC_LEX_OP_ASSIGN_MULTIPLY:
- case BC_LEX_OP_ASSIGN_DIVIDE:
- case BC_LEX_OP_ASSIGN_MODULUS:
- case BC_LEX_OP_ASSIGN_PLUS:
- case BC_LEX_OP_ASSIGN_MINUS:
- case BC_LEX_OP_ASSIGN:
- dbg_lex("%s:%d LEX_ASSIGNxyz", __func__, __LINE__);
- if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM
- && prev != XC_INST_SCALE && prev != XC_INST_IBASE
- && prev != XC_INST_OBASE && prev != BC_INST_LAST
- ) {
- return bc_error("bad assignment:"
- " left side must be variable"
- " or array element"
- ); // note: shared string
- }
- // Fallthrough.
- case XC_LEX_OP_POWER:
- case XC_LEX_OP_MULTIPLY:
- case XC_LEX_OP_DIVIDE:
- case XC_LEX_OP_MODULUS:
- case XC_LEX_OP_PLUS:
- case XC_LEX_OP_REL_EQ:
- case XC_LEX_OP_REL_LE:
- case XC_LEX_OP_REL_GE:
- case XC_LEX_OP_REL_NE:
- case XC_LEX_OP_REL_LT:
- case XC_LEX_OP_REL_GT:
- case BC_LEX_OP_BOOL_NOT:
- case BC_LEX_OP_BOOL_OR:
- case BC_LEX_OP_BOOL_AND:
- dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__);
- if (((t == BC_LEX_OP_BOOL_NOT) != bin_last)
- || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT)
- ) {
- return bc_error_bad_expression();
- }
- nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT);
- prev = BC_TOKEN_2_INST(t);
- bc_parse_operator(t, ops_bgn, &nexprs);
- s = zbc_lex_next();
- rprn = false;
- //get_token = false; - already is
- bin_last = (t != BC_LEX_OP_BOOL_NOT);
- break;
- case BC_LEX_LPAREN:
- dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- bc_vec_push(&p->ops, &t);
- nparens++;
- get_token = true;
- paren_expr = false;
- rprn = bin_last = false;
- break;
- case BC_LEX_RPAREN:
- dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__);
- if (bin_last || prev == XC_INST_BOOL_NOT)
- return bc_error_bad_expression();
- if (nparens == 0) {
- goto exit_loop;
- }
- if (!paren_expr) {
- dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__);
- return BC_STATUS_PARSE_EMPTY_EXP;
- }
- s = zbc_parse_rightParen(ops_bgn, &nexprs);
- nparens--;
- get_token = true;
- paren_expr = rprn = true;
- bin_last = false;
- break;
- case XC_LEX_NAME:
- dbg_lex("%s:%d LEX_NAME", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL);
- paren_expr = true;
- rprn = bin_last = false;
- //get_token = false; - already is
- nexprs++;
- break;
- case XC_LEX_NUMBER:
- dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- bc_parse_pushNUM();
- prev = XC_INST_NUM;
- get_token = true;
- paren_expr = true;
- rprn = bin_last = false;
- nexprs++;
- break;
- case BC_LEX_KEY_IBASE:
- case BC_LEX_KEY_LAST:
- case BC_LEX_KEY_OBASE:
- dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE);
- bc_parse_push((char) prev);
- get_token = true;
- paren_expr = true;
- rprn = bin_last = false;
- nexprs++;
- break;
- case BC_LEX_KEY_LENGTH:
- case BC_LEX_KEY_SQRT:
- dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- s = zbc_parse_builtin(t, flags, &prev);
- get_token = true;
- paren_expr = true;
- rprn = bin_last = false;
- nexprs++;
- break;
- case BC_LEX_KEY_READ:
- dbg_lex("%s:%d LEX_READ", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- s = zbc_parse_read();
- prev = XC_INST_READ;
- get_token = true;
- paren_expr = true;
- rprn = bin_last = false;
- nexprs++;
- break;
- case BC_LEX_KEY_SCALE:
- dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__);
- if (BC_PARSE_LEAF(prev, rprn))
- return bc_error_bad_expression();
- s = zbc_parse_scale(&prev, flags);
- prev = XC_INST_SCALE;
- //get_token = false; - already is
- paren_expr = true;
- rprn = bin_last = false;
- nexprs++;
- break;
- default:
- return bc_error_bad_token();
+ case BC_LEX_OP_INC:
+ case BC_LEX_OP_DEC:
+ dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__);
+ s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags);
+ rprn = bin_last = false;
+ //get_token = false; - already is
+ break;
+ case XC_LEX_OP_MINUS:
+ dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__);
+ s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs);
+ rprn = false;
+ //get_token = false; - already is
+ bin_last = (prev == XC_INST_MINUS);
+ break;
+ case BC_LEX_OP_ASSIGN_POWER:
+ case BC_LEX_OP_ASSIGN_MULTIPLY:
+ case BC_LEX_OP_ASSIGN_DIVIDE:
+ case BC_LEX_OP_ASSIGN_MODULUS:
+ case BC_LEX_OP_ASSIGN_PLUS:
+ case BC_LEX_OP_ASSIGN_MINUS:
+ case BC_LEX_OP_ASSIGN:
+ dbg_lex("%s:%d LEX_ASSIGNxyz", __func__, __LINE__);
+ if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM
+ && prev != XC_INST_SCALE && prev != XC_INST_IBASE
+ && prev != XC_INST_OBASE && prev != BC_INST_LAST
+ ) {
+ return bc_error("bad assignment:"
+ " left side must be variable"
+ " or array element"
+ ); // note: shared string
+ }
+ // Fallthrough.
+ case XC_LEX_OP_POWER:
+ case XC_LEX_OP_MULTIPLY:
+ case XC_LEX_OP_DIVIDE:
+ case XC_LEX_OP_MODULUS:
+ case XC_LEX_OP_PLUS:
+ case XC_LEX_OP_REL_EQ:
+ case XC_LEX_OP_REL_LE:
+ case XC_LEX_OP_REL_GE:
+ case XC_LEX_OP_REL_NE:
+ case XC_LEX_OP_REL_LT:
+ case XC_LEX_OP_REL_GT:
+ case BC_LEX_OP_BOOL_NOT:
+ case BC_LEX_OP_BOOL_OR:
+ case BC_LEX_OP_BOOL_AND:
+ dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__);
+ if (((t == BC_LEX_OP_BOOL_NOT) != bin_last)
+ || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT)
+ ) {
+ return bc_error_bad_expression();
+ }
+ nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT);
+ prev = BC_TOKEN_2_INST(t);
+ bc_parse_operator(t, ops_bgn, &nexprs);
+ s = zbc_lex_next();
+ rprn = false;
+ //get_token = false; - already is
+ bin_last = (t != BC_LEX_OP_BOOL_NOT);
+ break;
+ case BC_LEX_LPAREN:
+ dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ bc_vec_push(&p->ops, &t);
+ nparens++;
+ get_token = true;
+ paren_expr = false;
+ rprn = bin_last = false;
+ break;
+ case BC_LEX_RPAREN:
+ dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__);
+ if (bin_last || prev == XC_INST_BOOL_NOT)
+ return bc_error_bad_expression();
+ if (nparens == 0) {
+ goto exit_loop;
+ }
+ if (!paren_expr) {
+ dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__);
+ return BC_STATUS_PARSE_EMPTY_EXP;
+ }
+ s = zbc_parse_rightParen(ops_bgn, &nexprs);
+ nparens--;
+ get_token = true;
+ paren_expr = rprn = true;
+ bin_last = false;
+ break;
+ case XC_LEX_NAME:
+ dbg_lex("%s:%d LEX_NAME", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL);
+ paren_expr = true;
+ rprn = bin_last = false;
+ //get_token = false; - already is
+ nexprs++;
+ break;
+ case XC_LEX_NUMBER:
+ dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ bc_parse_pushNUM();
+ prev = XC_INST_NUM;
+ get_token = true;
+ paren_expr = true;
+ rprn = bin_last = false;
+ nexprs++;
+ break;
+ case BC_LEX_KEY_IBASE:
+ case BC_LEX_KEY_LAST:
+ case BC_LEX_KEY_OBASE:
+ dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE);
+ bc_parse_push((char) prev);
+ get_token = true;
+ paren_expr = true;
+ rprn = bin_last = false;
+ nexprs++;
+ break;
+ case BC_LEX_KEY_LENGTH:
+ case BC_LEX_KEY_SQRT:
+ dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ s = zbc_parse_builtin(t, flags, &prev);
+ get_token = true;
+ paren_expr = true;
+ rprn = bin_last = false;
+ nexprs++;
+ break;
+ case BC_LEX_KEY_READ:
+ dbg_lex("%s:%d LEX_READ", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ s = zbc_parse_read();
+ prev = XC_INST_READ;
+ get_token = true;
+ paren_expr = true;
+ rprn = bin_last = false;
+ nexprs++;
+ break;
+ case BC_LEX_KEY_SCALE:
+ dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__);
+ if (BC_PARSE_LEAF(prev, rprn))
+ return bc_error_bad_expression();
+ s = zbc_parse_scale(&prev, flags);
+ prev = XC_INST_SCALE;
+ //get_token = false; - already is
+ paren_expr = true;
+ rprn = bin_last = false;
+ nexprs++;
+ break;
+ default:
+ return bc_error_bad_token();
}
if (s || G_interrupt) // error, or ^C: stop parsing
@@ -4913,65 +4912,65 @@ static BC_STATUS zdc_parse_token(BcLexType t)
s = BC_STATUS_SUCCESS;
get_token = true;
switch (t) {
- case XC_LEX_OP_REL_EQ:
- case XC_LEX_OP_REL_LE:
- case XC_LEX_OP_REL_GE:
- case XC_LEX_OP_REL_NE:
- case XC_LEX_OP_REL_LT:
- case XC_LEX_OP_REL_GT:
- dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__);
- s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ);
- get_token = false;
- break;
- case DC_LEX_SCOLON:
- case DC_LEX_COLON:
- dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__);
- s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON);
- break;
- case XC_LEX_STR:
- dbg_lex("%s:%d LEX_STR", __func__, __LINE__);
- dc_parse_string();
- break;
- case XC_LEX_NEG:
- dbg_lex("%s:%d LEX_NEG", __func__, __LINE__);
- s = zbc_lex_next();
- if (s) RETURN_STATUS(s);
- if (G.prs.lex != XC_LEX_NUMBER)
- RETURN_STATUS(bc_error_bad_token());
- bc_parse_pushNUM();
- bc_parse_push(XC_INST_NEG);
- break;
- case XC_LEX_NUMBER:
- dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
- bc_parse_pushNUM();
- break;
- case DC_LEX_READ:
- dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__);
- bc_parse_push(XC_INST_READ);
- break;
- case DC_LEX_OP_ASSIGN:
- case DC_LEX_STORE_PUSH:
- dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__);
- assign = (t == DC_LEX_OP_ASSIGN);
- inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR;
- s = zdc_parse_mem(inst, true, assign);
- break;
- case DC_LEX_LOAD:
- case DC_LEX_LOAD_POP:
- dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__);
- inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD;
- s = zdc_parse_mem(inst, true, false);
- break;
- case DC_LEX_STORE_IBASE:
- case DC_LEX_STORE_SCALE:
- case DC_LEX_STORE_OBASE:
- dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__);
- inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE;
- s = zdc_parse_mem(inst, false, true);
- break;
- default:
- dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__);
+ case XC_LEX_OP_REL_EQ:
+ case XC_LEX_OP_REL_LE:
+ case XC_LEX_OP_REL_GE:
+ case XC_LEX_OP_REL_NE:
+ case XC_LEX_OP_REL_LT:
+ case XC_LEX_OP_REL_GT:
+ dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__);
+ s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ);
+ get_token = false;
+ break;
+ case DC_LEX_SCOLON:
+ case DC_LEX_COLON:
+ dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__);
+ s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON);
+ break;
+ case XC_LEX_STR:
+ dbg_lex("%s:%d LEX_STR", __func__, __LINE__);
+ dc_parse_string();
+ break;
+ case XC_LEX_NEG:
+ dbg_lex("%s:%d LEX_NEG", __func__, __LINE__);
+ s = zbc_lex_next();
+ if (s) RETURN_STATUS(s);
+ if (G.prs.lex != XC_LEX_NUMBER)
RETURN_STATUS(bc_error_bad_token());
+ bc_parse_pushNUM();
+ bc_parse_push(XC_INST_NEG);
+ break;
+ case XC_LEX_NUMBER:
+ dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
+ bc_parse_pushNUM();
+ break;
+ case DC_LEX_READ:
+ dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__);
+ bc_parse_push(XC_INST_READ);
+ break;
+ case DC_LEX_OP_ASSIGN:
+ case DC_LEX_STORE_PUSH:
+ dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__);
+ assign = (t == DC_LEX_OP_ASSIGN);
+ inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR;
+ s = zdc_parse_mem(inst, true, assign);
+ break;
+ case DC_LEX_LOAD:
+ case DC_LEX_LOAD_POP:
+ dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__);
+ inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD;
+ s = zdc_parse_mem(inst, true, false);
+ break;
+ case DC_LEX_STORE_IBASE:
+ case DC_LEX_STORE_SCALE:
+ case DC_LEX_STORE_OBASE:
+ dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__);
+ inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE;
+ s = zdc_parse_mem(inst, false, true);
+ break;
+ default:
+ dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__);
+ RETURN_STATUS(bc_error_bad_token());
}
if (!s && get_token) s = zbc_lex_next();
@@ -5050,62 +5049,62 @@ static BcVec* bc_program_search(char *id, bool var)
static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex)
{
switch (r->t) {
- case XC_RESULT_STR:
- case XC_RESULT_TEMP:
- case XC_RESULT_IBASE:
- case XC_RESULT_SCALE:
- case XC_RESULT_OBASE:
- *num = &r->d.n;
- break;
- case XC_RESULT_CONSTANT: {
- BcStatus s;
- char *str;
- unsigned base_t;
- size_t len;
-
- str = *bc_program_const(r->d.id.idx);
- len = strlen(str);
-
- bc_num_init(&r->d.n, len);
-
- hex = hex && len == 1;
- base_t = hex ? 16 : G.prog.ib_t;
- s = zbc_num_parse(&r->d.n, str, base_t);
- if (s) {
- bc_num_free(&r->d.n);
- RETURN_STATUS(s);
- }
- *num = &r->d.n;
- r->t = XC_RESULT_TEMP;
- break;
- }
- case XC_RESULT_VAR:
- case XC_RESULT_ARRAY:
- case XC_RESULT_ARRAY_ELEM: {
- BcVec *v;
+ case XC_RESULT_STR:
+ case XC_RESULT_TEMP:
+ case XC_RESULT_IBASE:
+ case XC_RESULT_SCALE:
+ case XC_RESULT_OBASE:
+ *num = &r->d.n;
+ break;
+ case XC_RESULT_CONSTANT: {
+ BcStatus s;
+ char *str;
+ unsigned base_t;
+ size_t len;
- v = bc_program_search(r->d.id.name, r->t == XC_RESULT_VAR);
+ str = *bc_program_const(r->d.id.idx);
+ len = strlen(str);
- if (r->t == XC_RESULT_ARRAY_ELEM) {
- v = bc_vec_top(v);
- if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1);
- *num = bc_vec_item(v, r->d.id.idx);
- } else
- *num = bc_vec_top(v);
- break;
+ bc_num_init(&r->d.n, len);
+
+ hex = hex && len == 1;
+ base_t = hex ? 16 : G.prog.ib_t;
+ s = zbc_num_parse(&r->d.n, str, base_t);
+ if (s) {
+ bc_num_free(&r->d.n);
+ RETURN_STATUS(s);
}
+ *num = &r->d.n;
+ r->t = XC_RESULT_TEMP;
+ break;
+ }
+ case XC_RESULT_VAR:
+ case XC_RESULT_ARRAY:
+ case XC_RESULT_ARRAY_ELEM: {
+ BcVec *v;
+
+ v = bc_program_search(r->d.id.name, r->t == XC_RESULT_VAR);
+
+ if (r->t == XC_RESULT_ARRAY_ELEM) {
+ v = bc_vec_top(v);
+ if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1);
+ *num = bc_vec_item(v, r->d.id.idx);
+ } else
+ *num = bc_vec_top(v);
+ break;
+ }
#if ENABLE_BC
- case BC_RESULT_LAST:
- *num = &G.prog.last;
- break;
- case BC_RESULT_ONE:
- *num = &G.prog.one;
- break;
+ case BC_RESULT_LAST:
+ *num = &G.prog.last;
+ break;
+ case BC_RESULT_ONE:
+ *num = &G.prog.one;
+ break;
#endif
#if SANITY_CHECKS
- default:
- // Testing the theory that dc does not reach LAST/ONE
- bb_error_msg_and_die("BUG:%d", r->t);
+ default:
+ // Testing the theory that dc does not reach LAST/ONE
+ bb_error_msg_and_die("BUG:%d", r->t);
#endif
}
@@ -6422,245 +6421,245 @@ static BC_STATUS zbc_program_exec(void)
dbg_exec("inst at %zd:%d results.len:%d", ip->inst_idx - 1, inst, G.prog.results.len);
switch (inst) {
#if ENABLE_BC
- case BC_INST_JUMP_ZERO: {
- BcNum *num;
- bool zero;
- dbg_exec("BC_INST_JUMP_ZERO:");
- s = zbc_program_prep(&ptr, &num);
- if (s) RETURN_STATUS(s);
- zero = (bc_num_cmp(num, &G.prog.zero) == 0);
- bc_vec_pop(&G.prog.results);
- if (!zero) {
- bc_program_index(code, &ip->inst_idx);
- break;
- }
- // else: fall through
- }
- case BC_INST_JUMP: {
- size_t idx = bc_program_index(code, &ip->inst_idx);
- size_t *addr = bc_vec_item(&func->labels, idx);
- dbg_exec("BC_INST_JUMP: to %ld", (long)*addr);
- ip->inst_idx = *addr;
+ case BC_INST_JUMP_ZERO: {
+ BcNum *num;
+ bool zero;
+ dbg_exec("BC_INST_JUMP_ZERO:");
+ s = zbc_program_prep(&ptr, &num);
+ if (s) RETURN_STATUS(s);
+ zero = (bc_num_cmp(num, &G.prog.zero) == 0);
+ bc_vec_pop(&G.prog.results);
+ if (!zero) {
+ bc_program_index(code, &ip->inst_idx);
break;
}
- case BC_INST_CALL:
- dbg_exec("BC_INST_CALL:");
- s = zbc_program_call(code, &ip->inst_idx);
- goto read_updated_ip;
- case BC_INST_INC_PRE:
- case BC_INST_DEC_PRE:
- case BC_INST_INC_POST:
- case BC_INST_DEC_POST:
- dbg_exec("BC_INST_INCDEC:");
- s = zbc_program_incdec(inst);
- break;
- case BC_INST_HALT:
- dbg_exec("BC_INST_HALT:");
- QUIT_OR_RETURN_TO_MAIN;
- break;
- case XC_INST_RET:
- case BC_INST_RET0:
- dbg_exec("BC_INST_RET[0]:");
- s = zbc_program_return(inst);
- goto read_updated_ip;
- case XC_INST_BOOL_OR:
- case XC_INST_BOOL_AND:
+ // else: fall through
+ }
+ case BC_INST_JUMP: {
+ size_t idx = bc_program_index(code, &ip->inst_idx);
+ size_t *addr = bc_vec_item(&func->labels, idx);
+ dbg_exec("BC_INST_JUMP: to %ld", (long)*addr);
+ ip->inst_idx = *addr;
+ break;
+ }
+ case BC_INST_CALL:
+ dbg_exec("BC_INST_CALL:");
+ s = zbc_program_call(code, &ip->inst_idx);
+ goto read_updated_ip;
+ case BC_INST_INC_PRE:
+ case BC_INST_DEC_PRE:
+ case BC_INST_INC_POST:
+ case BC_INST_DEC_POST:
+ dbg_exec("BC_INST_INCDEC:");
+ s = zbc_program_incdec(inst);
+ break;
+ case BC_INST_HALT:
+ dbg_exec("BC_INST_HALT:");
+ QUIT_OR_RETURN_TO_MAIN;
+ break;
+ case XC_INST_RET:
+ case BC_INST_RET0:
+ dbg_exec("BC_INST_RET[0]:");
+ s = zbc_program_return(inst);
+ goto read_updated_ip;
+ case XC_INST_BOOL_OR:
+ case XC_INST_BOOL_AND:
#endif // ENABLE_BC
- case XC_INST_REL_EQ:
- case XC_INST_REL_LE:
- case XC_INST_REL_GE:
- case XC_INST_REL_NE:
- case XC_INST_REL_LT:
- case XC_INST_REL_GT:
- dbg_exec("BC_INST_BOOL:");
- s = zbc_program_logical(inst);
- break;
- case XC_INST_READ:
- dbg_exec("XC_INST_READ:");
- s = zbc_program_read();
- goto read_updated_ip;
- case XC_INST_VAR:
- dbg_exec("XC_INST_VAR:");
- s = zbc_program_pushVar(code, &ip->inst_idx, false, false);
- break;
- case XC_INST_ARRAY_ELEM:
- case XC_INST_ARRAY:
- dbg_exec("XC_INST_ARRAY[_ELEM]:");
- s = zbc_program_pushArray(code, &ip->inst_idx, inst);
- break;
+ case XC_INST_REL_EQ:
+ case XC_INST_REL_LE:
+ case XC_INST_REL_GE:
+ case XC_INST_REL_NE:
+ case XC_INST_REL_LT:
+ case XC_INST_REL_GT:
+ dbg_exec("BC_INST_BOOL:");
+ s = zbc_program_logical(inst);
+ break;
+ case XC_INST_READ:
+ dbg_exec("XC_INST_READ:");
+ s = zbc_program_read();
+ goto read_updated_ip;
+ case XC_INST_VAR:
+ dbg_exec("XC_INST_VAR:");
+ s = zbc_program_pushVar(code, &ip->inst_idx, false, false);
+ break;
+ case XC_INST_ARRAY_ELEM:
+ case XC_INST_ARRAY:
+ dbg_exec("XC_INST_ARRAY[_ELEM]:");
+ s = zbc_program_pushArray(code, &ip->inst_idx, inst);
+ break;
#if ENABLE_BC
- case BC_INST_LAST:
- dbg_exec("BC_INST_LAST:");
- r.t = BC_RESULT_LAST;
- bc_vec_push(&G.prog.results, &r);
- break;
+ case BC_INST_LAST:
+ dbg_exec("BC_INST_LAST:");
+ r.t = BC_RESULT_LAST;
+ bc_vec_push(&G.prog.results, &r);
+ break;
#endif
- case XC_INST_IBASE:
- case XC_INST_OBASE:
- case XC_INST_SCALE:
- dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE);
- bc_program_pushGlobal(inst);
- break;
- case XC_INST_SCALE_FUNC:
- case XC_INST_LENGTH:
- case XC_INST_SQRT:
- dbg_exec("BC_INST_builtin:");
- s = zbc_program_builtin(inst);
- break;
- case XC_INST_NUM:
- dbg_exec("XC_INST_NUM:");
- r.t = XC_RESULT_CONSTANT;
- r.d.id.idx = bc_program_index(code, &ip->inst_idx);
- bc_vec_push(&G.prog.results, &r);
- break;
- case XC_INST_POP:
- dbg_exec("XC_INST_POP:");
- if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
- s = bc_error_stack_has_too_few_elements();
- else
- bc_vec_pop(&G.prog.results);
- break;
- case XC_INST_PRINT:
- case XC_INST_PRINT_POP:
- case XC_INST_PRINT_STR:
- dbg_exec("XC_INST_PRINTxyz:");
- s = zbc_program_print(inst, 0);
- break;
- case XC_INST_STR:
- dbg_exec("XC_INST_STR:");
- r.t = XC_RESULT_STR;
- r.d.id.idx = bc_program_index(code, &ip->inst_idx);
- bc_vec_push(&G.prog.results, &r);
- break;
- case XC_INST_POWER:
- case XC_INST_MULTIPLY:
- case XC_INST_DIVIDE:
- case XC_INST_MODULUS:
- case XC_INST_PLUS:
- case XC_INST_MINUS:
- dbg_exec("BC_INST_binaryop:");
- s = zbc_program_op(inst);
- break;
- case XC_INST_BOOL_NOT: {
- BcNum *num;
- dbg_exec("XC_INST_BOOL_NOT:");
- s = zbc_program_prep(&ptr, &num);
- if (s) RETURN_STATUS(s);
- bc_num_init_DEF_SIZE(&r.d.n);
- if (bc_num_cmp(num, &G.prog.zero) == 0)
- bc_num_one(&r.d.n);
- //else bc_num_zero(&r.d.n); - already is
- bc_program_retire(&r, XC_RESULT_TEMP);
- break;
- }
- case XC_INST_NEG:
- dbg_exec("XC_INST_NEG:");
- s = zbc_program_negate();
- break;
+ case XC_INST_IBASE:
+ case XC_INST_OBASE:
+ case XC_INST_SCALE:
+ dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE);
+ bc_program_pushGlobal(inst);
+ break;
+ case XC_INST_SCALE_FUNC:
+ case XC_INST_LENGTH:
+ case XC_INST_SQRT:
+ dbg_exec("BC_INST_builtin:");
+ s = zbc_program_builtin(inst);
+ break;
+ case XC_INST_NUM:
+ dbg_exec("XC_INST_NUM:");
+ r.t = XC_RESULT_CONSTANT;
+ r.d.id.idx = bc_program_index(code, &ip->inst_idx);
+ bc_vec_push(&G.prog.results, &r);
+ break;
+ case XC_INST_POP:
+ dbg_exec("XC_INST_POP:");
+ if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
+ s = bc_error_stack_has_too_few_elements();
+ else
+ bc_vec_pop(&G.prog.results);
+ break;
+ case XC_INST_PRINT:
+ case XC_INST_PRINT_POP:
+ case XC_INST_PRINT_STR:
+ dbg_exec("XC_INST_PRINTxyz:");
+ s = zbc_program_print(inst, 0);
+ break;
+ case XC_INST_STR:
+ dbg_exec("XC_INST_STR:");
+ r.t = XC_RESULT_STR;
+ r.d.id.idx = bc_program_index(code, &ip->inst_idx);
+ bc_vec_push(&G.prog.results, &r);
+ break;
+ case XC_INST_POWER:
+ case XC_INST_MULTIPLY:
+ case XC_INST_DIVIDE:
+ case XC_INST_MODULUS:
+ case XC_INST_PLUS:
+ case XC_INST_MINUS:
+ dbg_exec("BC_INST_binaryop:");
+ s = zbc_program_op(inst);
+ break;
+ case XC_INST_BOOL_NOT: {
+ BcNum *num;
+ dbg_exec("XC_INST_BOOL_NOT:");
+ s = zbc_program_prep(&ptr, &num);
+ if (s) RETURN_STATUS(s);
+ bc_num_init_DEF_SIZE(&r.d.n);
+ if (bc_num_cmp(num, &G.prog.zero) == 0)
+ bc_num_one(&r.d.n);
+ //else bc_num_zero(&r.d.n); - already is
+ bc_program_retire(&r, XC_RESULT_TEMP);
+ break;
+ }
+ case XC_INST_NEG:
+ dbg_exec("XC_INST_NEG:");
+ s = zbc_program_negate();
+ break;
#if ENABLE_BC
- case BC_INST_ASSIGN_POWER:
- case BC_INST_ASSIGN_MULTIPLY:
- case BC_INST_ASSIGN_DIVIDE:
- case BC_INST_ASSIGN_MODULUS:
- case BC_INST_ASSIGN_PLUS:
- case BC_INST_ASSIGN_MINUS:
+ case BC_INST_ASSIGN_POWER:
+ case BC_INST_ASSIGN_MULTIPLY:
+ case BC_INST_ASSIGN_DIVIDE:
+ case BC_INST_ASSIGN_MODULUS:
+ case BC_INST_ASSIGN_PLUS:
+ case BC_INST_ASSIGN_MINUS:
#endif
- case XC_INST_ASSIGN:
- dbg_exec("BC_INST_ASSIGNxyz:");
- s = zbc_program_assign(inst);
- break;
+ case XC_INST_ASSIGN:
+ dbg_exec("BC_INST_ASSIGNxyz:");
+ s = zbc_program_assign(inst);
+ break;
#if ENABLE_DC
- case DC_INST_POP_EXEC:
- dbg_exec("DC_INST_POP_EXEC:");
- bc_vec_pop(&G.prog.exestack);
- goto read_updated_ip;
- case DC_INST_MODEXP:
- dbg_exec("DC_INST_MODEXP:");
- s = zdc_program_modexp();
- break;
- case DC_INST_DIVMOD:
- dbg_exec("DC_INST_DIVMOD:");
- s = zdc_program_divmod();
- break;
- case DC_INST_EXECUTE:
- case DC_INST_EXEC_COND:
- dbg_exec("DC_INST_EXEC[_COND]:");
- s = zdc_program_execStr(code, &ip->inst_idx, inst == DC_INST_EXEC_COND);
- goto read_updated_ip;
- case DC_INST_PRINT_STACK: {
- size_t idx;
- dbg_exec("DC_INST_PRINT_STACK:");
- for (idx = 0; idx < G.prog.results.len; ++idx) {
- s = zbc_program_print(XC_INST_PRINT, idx);
- if (s) break;
- }
- break;
- }
- case DC_INST_CLEAR_STACK:
- dbg_exec("DC_INST_CLEAR_STACK:");
- bc_vec_pop_all(&G.prog.results);
- break;
- case DC_INST_STACK_LEN:
- dbg_exec("DC_INST_STACK_LEN:");
- dc_program_stackLen();
- break;
- case DC_INST_DUPLICATE:
- dbg_exec("DC_INST_DUPLICATE:");
- if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
- RETURN_STATUS(bc_error_stack_has_too_few_elements());
- ptr = bc_vec_top(&G.prog.results);
- dc_result_copy(&r, ptr);
- bc_vec_push(&G.prog.results, &r);
- break;
- case DC_INST_SWAP: {
- BcResult *ptr2;
- dbg_exec("DC_INST_SWAP:");
- if (!STACK_HAS_MORE_THAN(&G.prog.results, 1))
- RETURN_STATUS(bc_error_stack_has_too_few_elements());
- ptr = bc_vec_item_rev(&G.prog.results, 0);
- ptr2 = bc_vec_item_rev(&G.prog.results, 1);
- memcpy(&r, ptr, sizeof(BcResult));
- memcpy(ptr, ptr2, sizeof(BcResult));
- memcpy(ptr2, &r, sizeof(BcResult));
- break;
- }
- case DC_INST_ASCIIFY:
- dbg_exec("DC_INST_ASCIIFY:");
- s = zdc_program_asciify();
- break;
- case DC_INST_PRINT_STREAM:
- dbg_exec("DC_INST_PRINT_STREAM:");
- s = zdc_program_printStream();
- break;
- case DC_INST_LOAD:
- case DC_INST_PUSH_VAR: {
- bool copy = inst == DC_INST_LOAD;
- s = zbc_program_pushVar(code, &ip->inst_idx, true, copy);
- break;
- }
- case DC_INST_PUSH_TO_VAR: {
- char *name = bc_program_name(code, &ip->inst_idx);
- s = zbc_program_copyToVar(name, true);
- free(name);
- break;
+ case DC_INST_POP_EXEC:
+ dbg_exec("DC_INST_POP_EXEC:");
+ bc_vec_pop(&G.prog.exestack);
+ goto read_updated_ip;
+ case DC_INST_MODEXP:
+ dbg_exec("DC_INST_MODEXP:");
+ s = zdc_program_modexp();
+ break;
+ case DC_INST_DIVMOD:
+ dbg_exec("DC_INST_DIVMOD:");
+ s = zdc_program_divmod();
+ break;
+ case DC_INST_EXECUTE:
+ case DC_INST_EXEC_COND:
+ dbg_exec("DC_INST_EXEC[_COND]:");
+ s = zdc_program_execStr(code, &ip->inst_idx, inst == DC_INST_EXEC_COND);
+ goto read_updated_ip;
+ case DC_INST_PRINT_STACK: {
+ size_t idx;
+ dbg_exec("DC_INST_PRINT_STACK:");
+ for (idx = 0; idx < G.prog.results.len; ++idx) {
+ s = zbc_program_print(XC_INST_PRINT, idx);
+ if (s) break;
}
- case DC_INST_QUIT:
- dbg_exec("DC_INST_QUIT:");
- if (G.prog.exestack.len <= 2)
- QUIT_OR_RETURN_TO_MAIN;
- bc_vec_npop(&G.prog.exestack, 2);
- goto read_updated_ip;
- case DC_INST_NQUIT:
- dbg_exec("DC_INST_NQUIT:");
- s = zdc_program_nquit();
- //goto read_updated_ip; - just fall through to it
+ break;
+ }
+ case DC_INST_CLEAR_STACK:
+ dbg_exec("DC_INST_CLEAR_STACK:");
+ bc_vec_pop_all(&G.prog.results);
+ break;
+ case DC_INST_STACK_LEN:
+ dbg_exec("DC_INST_STACK_LEN:");
+ dc_program_stackLen();
+ break;
+ case DC_INST_DUPLICATE:
+ dbg_exec("DC_INST_DUPLICATE:");
+ if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
+ RETURN_STATUS(bc_error_stack_has_too_few_elements());
+ ptr = bc_vec_top(&G.prog.results);
+ dc_result_copy(&r, ptr);
+ bc_vec_push(&G.prog.results, &r);
+ break;
+ case DC_INST_SWAP: {
+ BcResult *ptr2;
+ dbg_exec("DC_INST_SWAP:");
+ if (!STACK_HAS_MORE_THAN(&G.prog.results, 1))
+ RETURN_STATUS(bc_error_stack_has_too_few_elements());
+ ptr = bc_vec_item_rev(&G.prog.results, 0);
+ ptr2 = bc_vec_item_rev(&G.prog.results, 1);
+ memcpy(&r, ptr, sizeof(BcResult));
+ memcpy(ptr, ptr2, sizeof(BcResult));
+ memcpy(ptr2, &r, sizeof(BcResult));
+ break;
+ }
+ case DC_INST_ASCIIFY:
+ dbg_exec("DC_INST_ASCIIFY:");
+ s = zdc_program_asciify();
+ break;
+ case DC_INST_PRINT_STREAM:
+ dbg_exec("DC_INST_PRINT_STREAM:");
+ s = zdc_program_printStream();
+ break;
+ case DC_INST_LOAD:
+ case DC_INST_PUSH_VAR: {
+ bool copy = inst == DC_INST_LOAD;
+ s = zbc_program_pushVar(code, &ip->inst_idx, true, copy);
+ break;
+ }
+ case DC_INST_PUSH_TO_VAR: {
+ char *name = bc_program_name(code, &ip->inst_idx);
+ s = zbc_program_copyToVar(name, true);
+ free(name);
+ break;
+ }
+ case DC_INST_QUIT:
+ dbg_exec("DC_INST_QUIT:");
+ if (G.prog.exestack.len <= 2)
+ QUIT_OR_RETURN_TO_MAIN;
+ bc_vec_npop(&G.prog.exestack, 2);
+ goto read_updated_ip;
+ case DC_INST_NQUIT:
+ dbg_exec("DC_INST_NQUIT:");
+ s = zdc_program_nquit();
+ //goto read_updated_ip; - just fall through to it
#endif // ENABLE_DC
read_updated_ip:
- // Instruction stack has changed, read new pointers
- ip = bc_vec_top(&G.prog.exestack);
- func = bc_program_func(ip->func);
- code = func->code.v;
- dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx);
+ // Instruction stack has changed, read new pointers
+ ip = bc_vec_top(&G.prog.exestack);
+ func = bc_program_func(ip->func);
+ code = func->code.v;
+ dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx);
}
if (s || G_interrupt) {