//kbuild:lib-$(CONFIG_BC) += bc.o
//kbuild:lib-$(CONFIG_DC) += bc.o
+//See www.gnu.org/software/bc/manual/bc.html
//usage:#define bc_trivial_usage
-//usage: "EXPRESSION...\n"
-//usage: "function_definition\n"
+//usage: "[-sqli] FILE..."
//usage:
-//usage:#define bc_full_usage "\n\n"
-//usage: "See www.gnu.org/software/bc/manual/bc.html\n"
+//usage:#define bc_full_usage "\n"
+//usage: "\nArbitrary precision calculator"
+//usage: "\n"
+//usage: "\n -i Interactive"
+//usage: "\n -l Load standard math library"
+//usage: "\n -s Be POSIX compatible"
+//usage: "\n -q Quiet"
+//usage: "\n -w Warn if extensions are used"
+///////: "\n -v Version"
//usage:
//usage:#define bc_example_usage
//usage: "3 + 4.129\n"
#include "libbb.h"
typedef enum BcStatus {
-
BC_STATUS_SUCCESS,
- BC_STATUS_ALLOC_ERR,
+// BC_STATUS_ALLOC_ERR,
BC_STATUS_INPUT_EOF,
BC_STATUS_BIN_FILE,
- BC_STATUS_PATH_IS_DIR,
+// BC_STATUS_PATH_IS_DIR,
BC_STATUS_LEX_BAD_CHAR,
BC_STATUS_LEX_NO_STRING_END,
#if ENABLE_DC
BC_STATUS_LEX_EXTENDED_REG,
#endif
-
BC_STATUS_PARSE_BAD_TOKEN,
BC_STATUS_PARSE_BAD_EXP,
BC_STATUS_PARSE_EMPTY_EXP,
BC_STATUS_MATH_DIVIDE_BY_ZERO,
BC_STATUS_MATH_BAD_STRING,
- BC_STATUS_EXEC_FILE_ERR,
+// BC_STATUS_EXEC_FILE_ERR,
BC_STATUS_EXEC_MISMATCHED_PARAMS,
BC_STATUS_EXEC_UNDEFINED_FUNC,
BC_STATUS_EXEC_FILE_NOT_EXECUTABLE,
BC_STATUS_EXEC_STRING_LEN,
BC_STATUS_EXEC_ARRAY_LEN,
BC_STATUS_EXEC_BAD_IBASE,
- BC_STATUS_EXEC_BAD_SCALE,
+// BC_STATUS_EXEC_BAD_SCALE,
BC_STATUS_EXEC_BAD_READ_EXPR,
BC_STATUS_EXEC_REC_READ,
BC_STATUS_EXEC_BAD_TYPE,
- BC_STATUS_EXEC_BAD_OBASE,
+// BC_STATUS_EXEC_BAD_OBASE,
BC_STATUS_EXEC_SIGNAL,
BC_STATUS_EXEC_STACK,
- BC_STATUS_VEC_OUT_OF_BOUNDS,
+// BC_STATUS_VEC_OUT_OF_BOUNDS,
BC_STATUS_VEC_ITEM_EXISTS,
-
#if ENABLE_BC
BC_STATUS_POSIX_NAME_LEN,
BC_STATUS_POSIX_COMMENT,
BC_STATUS_POSIX_FOR3,
BC_STATUS_POSIX_BRACE,
#endif
-
BC_STATUS_QUIT,
BC_STATUS_LIMITS,
- BC_STATUS_INVALID_OPTION,
-
+// BC_STATUS_INVALID_OPTION,
} BcStatus;
+// Keep enum above and messages below in sync!
+static const char *const bc_err_msgs[] = {
+ NULL,
+// "memory allocation error",
+ "I/O error",
+ "file is not text:",
+// "path is a directory:",
+
+ "bad character",
+ "string end could not be found",
+ "comment end could not be found",
+ "end of file",
+#if ENABLE_DC
+ "extended register",
+#endif
+ "bad token",
+ "bad expression",
+ "empty expression",
+ "bad print statement",
+ "bad function definition",
+ "bad assignment: left side must be scale, ibase, "
+ "obase, last, var, or array element",
+ "no auto variable found",
+ "function parameter or auto var has the same name as another",
+ "block end could not be found",
-#define BC_ERR_IDX_VM (0)
-#define BC_ERR_IDX_LEX (1)
-#define BC_ERR_IDX_PARSE (2)
-#define BC_ERR_IDX_MATH (3)
-#define BC_ERR_IDX_EXEC (4)
-#define BC_ERR_IDX_VEC (5)
+ "negative number",
+ "non integer number",
+ "overflow",
+ "divide by zero",
+ "bad number string",
+
+// "could not open file:",
+ "mismatched parameters", // wrong number of them, to be exact
+ "undefined function",
+ "file is not executable:",
+ "number too long: must be [1, BC_NUM_MAX]",
+ "name too long: must be [1, BC_NAME_MAX]",
+ "string too long: must be [1, BC_STRING_MAX]",
+ "array too long; must be [1, BC_DIM_MAX]",
+ "bad ibase; must be [2, 16]",
+// "bad scale; must be [0, BC_SCALE_MAX]",
+ "bad read() expression",
+ "read() call inside of a read() call",
+ "variable is wrong type",
+// "bad obase; must be [2, BC_BASE_MAX]",
+ "signal caught and not handled",
+ "stack has too few elements",
+
+// "index is out of bounds",
+ "item already exists",
#if ENABLE_BC
-#define BC_ERR_IDX_POSIX (6)
+ "POSIX only allows one character names; the following is bad:",
+ "POSIX does not allow '#' script comments",
+ "POSIX does not allow the following keyword:",
+ "POSIX does not allow a period ('.') as a shortcut for the last result",
+ "POSIX requires parentheses around return expressions",
+ "POSIX does not allow boolean operators; the following is bad:",
+ "POSIX does not allow comparison operators outside if or loops",
+ "POSIX requires exactly one comparison operator per condition",
+ "POSIX does not allow an empty init expression in a for loop",
+ "POSIX does not allow an empty condition expression in a for loop",
+ "POSIX does not allow an empty update expression in a for loop",
+ "POSIX requires the left brace be on the same line as the function header",
#endif
+};
#define BC_VEC_INVALID_IDX ((size_t) -1)
#define BC_VEC_START_CAP (1 << 5)
static void bc_num_free(void *num);
static BcStatus bc_num_ulong(BcNum *n, unsigned long *result);
-static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val);
+static void bc_num_ulong2num(BcNum *n, unsigned long val);
static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale);
static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale);
#define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i)))
#define bc_parse_updateFunc(p, f) \
- ((p)->func = bc_vec_item(&(p)->prog->fns, ((p)->fidx = (f))))
+ ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f))))
#define BC_PARSE_REL (1 << 0)
#define BC_PARSE_PRINT (1 << 1)
BcVec ops;
- struct BcProgram *prog;
BcFunc *func;
size_t fidx;
// first in the expr enum. Note: This only works for binary operators.
#define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG))
-static BcStatus bc_parse_parse(BcParse *p);
static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next);
#endif // ENABLE_BC
typedef unsigned long (*BcProgramBuiltIn)(BcNum *);
-static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx);
-static BcStatus bc_program_reset(BcProgram *p, BcStatus s);
+static void bc_program_addFunc(char *name, size_t *idx);
+static BcStatus bc_program_reset(BcStatus s);
#define BC_FLAG_X (1 << 0)
#define BC_FLAG_W (1 << 1)
#define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
#define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
-#define BC_MAX_OBASE ((unsigned long) 999)
-#define BC_MAX_DIM ((unsigned long) INT_MAX)
-#define BC_MAX_SCALE ((unsigned long) UINT_MAX)
-#define BC_MAX_STRING ((unsigned long) UINT_MAX - 1)
-#define BC_MAX_NAME BC_MAX_STRING
-#define BC_MAX_NUM BC_MAX_STRING
-#define BC_MAX_EXP ((unsigned long) LONG_MAX)
-#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
+#define BC_MAX_OBASE ((unsigned) 999)
+#define BC_MAX_DIM ((unsigned) INT_MAX)
+#define BC_MAX_SCALE ((unsigned) UINT_MAX)
+#define BC_MAX_STRING ((unsigned) UINT_MAX - 1)
+#define BC_MAX_NAME BC_MAX_STRING
+#define BC_MAX_NUM BC_MAX_STRING
+#define BC_MAX_EXP ((unsigned long) LONG_MAX)
+#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
struct globals {
char sbgn;
static void bc_vm_info(void);
-static const char* const bc_args_env_name = "BC_ENV_ARGS";
-
-static const char bc_err_fmt[] = "\n%s error: %s\n";
-static const char bc_warn_fmt[] = "\n%s warning: %s\n";
+static const char bc_err_fmt[] = "\nerror: %s\n";
+static const char bc_warn_fmt[] = "\nwarning: %s\n";
static const char bc_err_line[] = ":%zu\n\n";
-static const char *bc_errs[] = {
- "VM",
- "Lex",
- "Parse",
- "Math",
- "Runtime",
- "Vector",
-#if ENABLE_BC
- "POSIX",
-#endif
-};
-
-static const uint8_t bc_err_ids[] = {
- BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM,
- BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX,
-#if ENABLE_DC
- BC_ERR_IDX_LEX,
-#endif
- BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
- BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
- BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH,
- BC_ERR_IDX_MATH,
-#if ENABLE_DC
- BC_ERR_IDX_MATH,
-#endif
- BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
- BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
- BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
- BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
- BC_ERR_IDX_EXEC,
- BC_ERR_IDX_VEC, BC_ERR_IDX_VEC,
-#if ENABLE_BC
- BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX,
- BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX,
- BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX,
-#endif
- BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM,
-};
-
-static const char *bc_err_msgs[] = {
-
- NULL,
- "memory allocation error",
- "I/O error",
- "file is not text:",
- "path is a directory:",
-
- "bad character",
- "string end could not be found",
- "comment end could not be found",
- "end of file",
-#if ENABLE_DC
- "extended register",
-#endif
-
- "bad token",
- "bad expression",
- "empty expression",
- "bad print statement",
- "bad function definition",
- "bad assignment: left side must be scale, ibase, "
- "obase, last, var, or array element",
- "no auto variable found",
- "function parameter or auto var has the same name as another",
- "block end could not be found",
-
- "negative number",
- "non integer number",
- "overflow",
- "divide by zero",
- "bad number string",
-
- "could not open file:",
- "mismatched parameters",
- "undefined function",
- "file is not executable:",
- "number too long: must be [1, BC_NUM_MAX]",
- "name too long: must be [1, BC_NAME_MAX]",
- "string too long: must be [1, BC_STRING_MAX]",
- "array too long; must be [1, BC_DIM_MAX]",
- "bad ibase; must be [2, 16]",
- "bad scale; must be [0, BC_SCALE_MAX]",
- "bad read() expression",
- "read() call inside of a read() call",
- "variable is wrong type",
- "bad obase; must be [2, BC_BASE_MAX]",
- "signal caught and not handled",
- "stack has too few elements",
-
- "index is out of bounds",
- "item already exists",
-
-#if ENABLE_BC
- "POSIX only allows one character names; the following is bad:",
- "POSIX does not allow '#' script comments",
- "POSIX does not allow the following keyword:",
- "POSIX does not allow a period ('.') as a shortcut for the last result",
- "POSIX requires parentheses around return expressions",
- "POSIX does not allow boolean operators; the following is bad:",
- "POSIX does not allow comparison operators outside if or loops",
- "POSIX requires exactly one comparison operator per condition",
- "POSIX does not allow an empty init expression in a for loop",
- "POSIX does not allow an empty condition expression in a for loop",
- "POSIX does not allow an empty update expression in a for loop",
- "POSIX requires the left brace be on the same line as the function header",
-#endif
-
-};
-
-static const char bc_func_main[] = "(main)";
-static const char bc_func_read[] = "(read)";
-
#if ENABLE_BC
static const BcLexKeyword bc_lex_kws[20] = {
BC_LEX_KW_ENTRY("auto", 4, true),
#if ENABLE_FEATURE_BC_SIGNALS
if (bb_got_signal) { /* ^C was pressed */
intr:
+ bb_got_signal = 0; /* resets G_interrupt to zero */
fputs(IS_BC
? "\ninterrupt (type \"quit\" to exit)\n"
: "\ninterrupt (type \"q\" to exit)\n"
, stderr);
}
- bb_got_signal = 0; /* resets G_interrupt to zero */
#endif
if (G.ttyin && !G_posix)
fputs(prompt, stderr);
return BC_STATUS_SUCCESS;
}
-static BcStatus bc_read_file(const char *path, char **buf)
+static char* bc_read_file(const char *path)
{
- BcStatus s = BC_STATUS_BIN_FILE;
+ char *buf;
size_t size = ((size_t) -1);
size_t i;
- *buf = xmalloc_open_read_close(path, &size);
+ buf = xmalloc_open_read_close(path, &size);
for (i = 0; i < size; ++i) {
- if (BC_READ_BIN_CHAR((*buf)[i]))
- goto read_err;
+ if (BC_READ_BIN_CHAR(buf[i])) {
+ free(buf);
+ buf = NULL;
+ break;
+ }
}
- return BC_STATUS_SUCCESS;
-
-read_err:
- free(*buf);
- return s;
+ return buf;
}
static void bc_args(int argc, char **argv)
n->num[1] = 1;
}
-static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
+static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
size_t len)
{
size_t i, j;
- for (i = 0; !G_interrupt && i < len; ++i) {
- for (a[i] -= b[i], j = 0; !G_interrupt && a[i + j] < 0;) {
+ for (i = 0; i < len; ++i) {
+ for (a[i] -= b[i], j = 0; a[i + j] < 0;) {
a[i + j++] += 10;
a[i + j] -= 1;
}
}
- return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
}
static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
{
size_t i;
int c = 0;
- for (i = len - 1; !G_interrupt && i < len && !(c = a[i] - b[i]); --i);
+ for (i = len - 1; i < len && !(c = a[i] - b[i]); --i);
return BC_NUM_NEG(i + 1, c < 0);
}
cmp = bc_num_compare(max_num, min_num, b_int + min);
if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg);
- for (max_num -= diff, i = diff - 1; !G_interrupt && i < diff; --i) {
+ for (max_num -= diff, i = diff - 1; i < diff; --i) {
if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg);
}
ptr = ptr_b;
}
- for (carry = 0, i = 0; !G_interrupt && i < min_rdx + min_int; ++i, ++c->len) {
+ for (carry = 0, i = 0; i < min_rdx + min_int; ++i, ++c->len) {
in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry;
carry = in / 10;
ptr_c[i] = (BcDig)(in % 10);
}
- for (; !G_interrupt && i < max + min_rdx; ++i, ++c->len) {
+ for (; i < max + min_rdx; ++i, ++c->len) {
in = ((int) ptr[i]) + carry;
carry = in / 10;
ptr_c[i] = (BcDig)(in % 10);
if (carry != 0) c->num[c->len++] = (BcDig) carry;
- return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
+ return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
}
static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
{
- BcStatus s;
ssize_t cmp;
BcNum *minuend, *subtrahend;
size_t start;
else
start = c->rdx - subtrahend->rdx;
- s = bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len);
+ bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len);
bc_num_clean(c);
- return s;
+ return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
}
static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b,
BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
bool aone = BC_NUM_ONE(a);
- if (G_interrupt) return BC_STATUS_EXEC_SIGNAL;
if (a->len == 0 || b->len == 0) {
bc_num_zero(c);
return BC_STATUS_SUCCESS;
memset(c->num, 0, sizeof(BcDig) * c->cap);
c->len = carry = len = 0;
- for (i = 0; !G_interrupt && i < b->len; ++i) {
+ for (i = 0; i < b->len; ++i) {
- for (j = 0; !G_interrupt && j < a->len; ++j) {
+ for (j = 0; j < a->len; ++j) {
int in = (int) c->num[i + j];
in += ((int) a->num[j]) * ((int) b->num[i]) + carry;
carry = in / 10;
c->len = len;
- return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
+ return BC_STATUS_SUCCESS;
}
bc_num_init(&l1, max);
c->len = cp.len;
p = b->num;
- for (i = end - 1; !G_interrupt && !s && i < end; --i) {
+ for (i = end - 1; !s && i < end; --i) {
n = cp.num + i;
for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
- s = bc_num_subArrays(n, p, len);
+ bc_num_subArrays(n, p, len);
c->num[i] = q;
}
- if (!s) bc_num_retireMul(c, scale, a->neg, b->neg);
+ bc_num_retireMul(c, scale, a->neg, b->neg);
bc_num_free(&cp);
- return s;
+ return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
}
static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
b->neg = neg;
- for (powrdx = a->rdx; !G_interrupt && !(pow & 1); pow >>= 1) {
+ for (powrdx = a->rdx; !(pow & 1); pow >>= 1) {
powrdx <<= 1;
s = bc_num_mul(©, ©, ©, powrdx);
if (s) goto err;
}
- if (G_interrupt) {
- s = BC_STATUS_EXEC_SIGNAL;
- goto err;
- }
-
bc_num_copy(c, ©);
- for (resrdx = powrdx, pow >>= 1; !G_interrupt && pow != 0; pow >>= 1) {
+ for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) {
powrdx <<= 1;
s = bc_num_mul(©, ©, ©, powrdx);
if (s) goto err;
}
- if (G_interrupt) {
- s = BC_STATUS_EXEC_SIGNAL;
- goto err;
- }
-
if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
// We can't use bc_num_clean() here.
s = bc_num_mul(n, base, &mult, 0);
if (s) goto int_err;
- s = bc_num_ulong2num(&temp, v);
- if (s) goto int_err;
+ bc_num_ulong2num(&temp, v);
s = bc_num_add(&mult, &temp, n, 0);
if (s) goto int_err;
}
s = bc_num_mul(&result, base, &result, 0);
if (s) goto err;
- s = bc_num_ulong2num(&temp, v);
- if (s) goto err;
+ bc_num_ulong2num(&temp, v);
s = bc_num_add(&result, &temp, &result, 0);
if (s) goto err;
s = bc_num_mul(&mult, base, &mult, 0);
if (s) goto err;
s = bc_num_ulong(&fracp, &dig);
if (s) goto err;
- s = bc_num_ulong2num(&intp, dig);
- if (s) goto err;
+ bc_num_ulong2num(&intp, dig);
s = bc_num_sub(&fracp, &intp, &fracp, 0);
if (s) goto err;
print(dig, width, radix, nchars, len);
return BC_STATUS_SUCCESS;
}
-static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val)
+static void bc_num_ulong2num(BcNum *n, unsigned long val)
{
size_t len;
BcDig *ptr;
bc_num_zero(n);
- if (val == 0) return BC_STATUS_SUCCESS;
+ if (val == 0) return;
for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len);
for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
-
- return BC_STATUS_SUCCESS;
}
static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
resrdx = scale + 2;
len = BC_NUM_INT(x0) + resrdx - 1;
- while (!G_interrupt && (cmp != 0 || digs < len)) {
+ while (cmp != 0 || digs < len) {
s = bc_num_div(a, x0, &f, resrdx);
if (s) goto err;
x1 = temp;
}
- if (G_interrupt) {
- s = BC_STATUS_EXEC_SIGNAL;
- goto err;
- }
-
bc_num_copy(b, x0);
scale -= 1;
if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale);
static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx)
{
- bc_program_addFunc(p->prog, name, idx);
- p->func = bc_vec_item(&p->prog->fns, p->fidx);
+ bc_program_addFunc(name, idx);
+ p->func = bc_vec_item(&G.prog.fns, p->fidx);
}
static void bc_parse_pushName(BcParse *p, char *name)
static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs)
{
char *num = xstrdup(p->l.t.v.v);
- size_t idx = p->prog->consts.len;
+ size_t idx = G.prog.consts.len;
- bc_vec_push(&p->prog->consts, &num);
+ bc_vec_push(&G.prog.consts, &num);
bc_parse_push(p, BC_INST_NUM);
bc_parse_pushIndex(p, idx);
{
BcStatus s;
- p->func = bc_vec_item(&p->prog->fns, p->fidx);
+ p->func = bc_vec_item(&G.prog.fns, p->fidx);
if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) {
p->l.t.t = BC_LEX_INVALID;
bc_vec_npop(&p->conds, p->conds.len);
bc_vec_npop(&p->ops, p->ops.len);
- return bc_program_reset(p->prog, s);
+ return bc_program_reset(s);
}
static void bc_parse_free(BcParse *p)
bc_lex_free(&p->l);
}
-static void bc_parse_create(BcParse *p, BcProgram *prog, size_t func,
+static void bc_parse_create(BcParse *p, size_t func,
BcParseParse parse, BcLexNext next)
{
memset(p, 0, sizeof(BcParse));
bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
p->parse = parse;
- p->prog = prog;
p->auto_part = (p->nbraces = 0);
bc_parse_updateFunc(p, func);
}
goto err;
}
- idx = bc_map_index(&p->prog->fn_map, &entry);
+ idx = bc_map_index(&G.prog.fn_map, &entry);
if (idx == BC_VEC_INVALID_IDX) {
name = xstrdup(entry.name);
bc_parse_addFunc(p, name, &idx);
- idx = bc_map_index(&p->prog->fn_map, &entry);
+ idx = bc_map_index(&G.prog.fn_map, &entry);
free(entry.name);
}
else
free(name);
- entry_ptr = bc_vec_item(&p->prog->fn_map, idx);
+ entry_ptr = bc_vec_item(&G.prog.fn_map, idx);
bc_parse_pushIndex(p, entry_ptr->idx);
return bc_lex_next(&p->l);
char *str = xstrdup(p->l.t.v.v);
bc_parse_push(p, BC_INST_STR);
- bc_parse_pushIndex(p, p->prog->strs.len);
- bc_vec_push(&p->prog->strs, &str);
+ bc_parse_pushIndex(p, G.prog.strs.len);
+ bc_vec_push(&G.prog.strs, &str);
bc_parse_push(p, inst);
return bc_lex_next(&p->l);
return s;
}
-static void bc_parse_init(BcParse *p, BcProgram *prog, size_t func)
+static void bc_parse_init(BcParse *p, size_t func)
{
- bc_parse_create(p, prog, func, bc_parse_parse, bc_lex_token);
+ bc_parse_create(p, func, bc_parse_parse, bc_lex_token);
}
static BcStatus bc_parse_expression(BcParse *p, uint8_t flags)
static BcStatus dc_parse_string(BcParse *p)
{
char *str, *name, b[DC_PARSE_BUF_LEN + 1];
- size_t idx, len = p->prog->strs.len;
+ size_t idx, len = G.prog.strs.len;
sprintf(b, "%0*zu", DC_PARSE_BUF_LEN, len);
name = xstrdup(b);
str = xstrdup(p->l.t.v.v);
bc_parse_push(p, BC_INST_STR);
bc_parse_pushIndex(p, len);
- bc_vec_push(&p->prog->strs, &str);
+ bc_vec_push(&G.prog.strs, &str);
bc_parse_addFunc(p, name, &idx);
return bc_lex_next(&p->l);
BcInst inst;
BcLexType t;
- if (flags & BC_PARSE_NOCALL) p->nbraces = p->prog->results.len;
+ if (flags & BC_PARSE_NOCALL) p->nbraces = G.prog.results.len;
for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) {
return s;
}
-static void dc_parse_init(BcParse *p, BcProgram *prog, size_t func)
+static void dc_parse_init(BcParse *p, size_t func)
{
- bc_parse_create(p, prog, func, dc_parse_parse, dc_lex_token);
+ bc_parse_create(p, func, dc_parse_parse, dc_lex_token);
}
#endif // ENABLE_DC
-static void common_parse_init(BcParse *p, BcProgram *prog, size_t func)
+static void common_parse_init(BcParse *p, size_t func)
{
if (IS_BC) {
- bc_parse_init(p, prog, func);
+ bc_parse_init(p, func);
} else {
- dc_parse_init(p, prog, func);
+ dc_parse_init(p, func);
}
}
}
}
-static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var)
+static BcVec* bc_program_search(char *id, bool var)
{
BcStatus s;
BcId e, *ptr;
BcResultData data;
bool new;
- v = var ? &p->vars : &p->arrs;
- map = var ? &p->var_map : &p->arr_map;
+ v = var ? &G.prog.vars : &G.prog.arrs;
+ map = var ? &G.prog.var_map : &G.prog.arr_map;
e.name = id;
e.idx = v->len;
ptr = bc_vec_item(map, i);
if (new) ptr->name = xstrdup(e.name);
- *ret = bc_vec_item(v, ptr->idx);
+ return bc_vec_item(v, ptr->idx);
}
-static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex)
+static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex)
{
BcStatus s = BC_STATUS_SUCCESS;
case BC_RESULT_CONSTANT:
{
- char **str = bc_vec_item(&p->consts, r->d.id.idx);
+ char **str = bc_vec_item(&G.prog.consts, r->d.id.idx);
size_t base_t, len = strlen(*str);
BcNum *base;
bc_num_init(&r->d.n, len);
hex = hex && len == 1;
- base = hex ? &p->hexb : &p->ib;
- base_t = hex ? BC_NUM_MAX_IBASE : p->ib_t;
+ base = hex ? &G.prog.hexb : &G.prog.ib;
+ base_t = hex ? BC_NUM_MAX_IBASE : G.prog.ib_t;
s = bc_num_parse(&r->d.n, *str, base, base_t);
if (s) {
{
BcVec *v;
- bc_program_search(p, r->d.id.name, &v, r->t == BC_RESULT_VAR);
+ v = bc_program_search(r->d.id.name, r->t == BC_RESULT_VAR);
if (r->t == BC_RESULT_ARRAY_ELEM) {
v = bc_vec_top(v);
case BC_RESULT_LAST:
{
- *num = &p->last;
+ *num = &G.prog.last;
break;
}
case BC_RESULT_ONE:
{
- *num = &p->one;
+ *num = &G.prog.one;
break;
}
}
return s;
}
-static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln,
+static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln,
BcResult **r, BcNum **rn, bool assign)
{
BcStatus s;
bool hex;
BcResultType lt, rt;
- if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK;
+ if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK;
- *r = bc_vec_item_rev(&p->results, 0);
- *l = bc_vec_item_rev(&p->results, 1);
+ *r = bc_vec_item_rev(&G.prog.results, 0);
+ *l = bc_vec_item_rev(&G.prog.results, 1);
lt = (*l)->t;
rt = (*r)->t;
hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE);
- s = bc_program_num(p, *l, ln, false);
+ s = bc_program_num(*l, ln, false);
if (s) return s;
- s = bc_program_num(p, *r, rn, hex);
+ s = bc_program_num(*r, rn, hex);
if (s) return s;
// We run this again under these conditions in case any vector has been
// reallocated out from under the BcNums or arrays we had.
if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) {
- s = bc_program_num(p, *l, ln, false);
+ s = bc_program_num(*l, ln, false);
if (s) return s;
}
return s;
}
-static void bc_program_binOpRetire(BcProgram *p, BcResult *r)
+static void bc_program_binOpRetire(BcResult *r)
{
r->t = BC_RESULT_TEMP;
- bc_vec_pop(&p->results);
- bc_vec_pop(&p->results);
- bc_vec_push(&p->results, r);
+ bc_vec_pop(&G.prog.results);
+ bc_vec_pop(&G.prog.results);
+ bc_vec_push(&G.prog.results, r);
}
-static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n)
+static BcStatus bc_program_prep(BcResult **r, BcNum **n)
{
BcStatus s;
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
- *r = bc_vec_top(&p->results);
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
+ *r = bc_vec_top(&G.prog.results);
- s = bc_program_num(p, *r, n, false);
+ s = bc_program_num(*r, n, false);
if (s) return s;
if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE;
return s;
}
-static void bc_program_retire(BcProgram *p, BcResult *r, BcResultType t)
+static void bc_program_retire(BcResult *r, BcResultType t)
{
r->t = t;
- bc_vec_pop(&p->results);
- bc_vec_push(&p->results, r);
+ bc_vec_pop(&G.prog.results);
+ bc_vec_push(&G.prog.results, r);
}
-static BcStatus bc_program_op(BcProgram *p, char inst)
+static BcStatus bc_program_op(char inst)
{
BcStatus s;
BcResult *opd1, *opd2, res;
BcNum *n1, *n2 = NULL;
- s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false);
+ s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
if (s) return s;
bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
- s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, p->scale);
+ s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale);
if (s) goto err;
- bc_program_binOpRetire(p, &res);
+ bc_program_binOpRetire(&res);
return s;
static BcStatus bc_program_read(void)
{
- BcProgram *p = &G.prog;
-
BcStatus s;
BcParse parse;
BcVec buf;
BcInstPtr ip;
size_t i;
- BcFunc *f = bc_vec_item(&p->fns, BC_PROG_READ);
+ BcFunc *f = bc_vec_item(&G.prog.fns, BC_PROG_READ);
- for (i = 0; i < p->stack.len; ++i) {
- BcInstPtr *ip_ptr = bc_vec_item(&p->stack, i);
+ for (i = 0; i < G.prog.stack.len; ++i) {
+ BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i);
if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ;
}
s = bc_read_line(&buf, "read> ");
if (s) goto io_err;
- common_parse_init(&parse, p, BC_PROG_READ);
+ common_parse_init(&parse, BC_PROG_READ);
bc_lex_file(&parse.l, bc_program_stdin_name);
s = bc_parse_text(&parse, buf.v);
ip.func = BC_PROG_READ;
ip.idx = 0;
- ip.len = p->results.len;
+ ip.len = G.prog.results.len;
// Update this pointer, just in case.
- f = bc_vec_item(&p->fns, BC_PROG_READ);
+ f = bc_vec_item(&G.prog.fns, BC_PROG_READ);
bc_vec_pushByte(&f->code, BC_INST_POP_EXEC);
- bc_vec_push(&p->stack, &ip);
+ bc_vec_push(&G.prog.stack, &ip);
exec_err:
bc_parse_free(&parse);
}
}
-static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx)
+static BcStatus bc_program_print(char inst, size_t idx)
{
BcStatus s = BC_STATUS_SUCCESS;
BcResult *r;
BcNum *num = NULL;
bool pop = inst != BC_INST_PRINT;
- if (!BC_PROG_STACK(&p->results, idx + 1)) return BC_STATUS_EXEC_STACK;
+ if (!BC_PROG_STACK(&G.prog.results, idx + 1)) return BC_STATUS_EXEC_STACK;
- r = bc_vec_item_rev(&p->results, idx);
- s = bc_program_num(p, r, &num, false);
+ r = bc_vec_item_rev(&G.prog.results, idx);
+ s = bc_program_num(r, &num, false);
if (s) return s;
if (BC_PROG_NUM(r, num)) {
- s = bc_num_print(num, &p->ob, p->ob_t, !pop, &p->nchars, p->len);
- if (!s) bc_num_copy(&p->last, num);
+ s = bc_num_print(num, &G.prog.ob, G.prog.ob_t, !pop, &G.prog.nchars, G.prog.len);
+ if (!s) bc_num_copy(&G.prog.last, num);
}
else {
idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx;
- str = *((char **) bc_vec_item(&p->strs, idx));
+ str = *((char **) bc_vec_item(&G.prog.strs, idx));
if (inst == BC_INST_PRINT_STR) {
for (i = 0, len = strlen(str); i < len; ++i) {
char c = str[i];
bb_putchar(c);
- if (c == '\n') p->nchars = SIZE_MAX;
- ++p->nchars;
+ if (c == '\n') G.prog.nchars = SIZE_MAX;
+ ++G.prog.nchars;
}
}
else {
- bc_program_printString(str, &p->nchars);
+ bc_program_printString(str, &G.prog.nchars);
if (inst == BC_INST_PRINT) bb_putchar('\n');
}
}
- if (!s && pop) bc_vec_pop(&p->results);
+ if (!s && pop) bc_vec_pop(&G.prog.results);
return s;
}
-static BcStatus bc_program_negate(BcProgram *p)
+static BcStatus bc_program_negate(void)
{
BcStatus s;
BcResult res, *ptr;
BcNum *num = NULL;
- s = bc_program_prep(p, &ptr, &num);
+ s = bc_program_prep(&ptr, &num);
if (s) return s;
bc_num_init(&res.d.n, num->len);
bc_num_copy(&res.d.n, num);
if (res.d.n.len) res.d.n.neg = !res.d.n.neg;
- bc_program_retire(p, &res, BC_RESULT_TEMP);
+ bc_program_retire(&res, BC_RESULT_TEMP);
return s;
}
-static BcStatus bc_program_logical(BcProgram *p, char inst)
+static BcStatus bc_program_logical(char inst)
{
BcStatus s;
BcResult *opd1, *opd2, res;
bool cond = 0;
ssize_t cmp;
- s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false);
+ s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
if (s) return s;
bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
if (inst == BC_INST_BOOL_AND)
- cond = bc_num_cmp(n1, &p->zero) && bc_num_cmp(n2, &p->zero);
+ cond = bc_num_cmp(n1, &G.prog.zero) && bc_num_cmp(n2, &G.prog.zero);
else if (inst == BC_INST_BOOL_OR)
- cond = bc_num_cmp(n1, &p->zero) || bc_num_cmp(n2, &p->zero);
+ cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero);
else {
cmp = bc_num_cmp(n1, n2);
(cond ? bc_num_one : bc_num_zero)(&res.d.n);
- bc_program_binOpRetire(p, &res);
+ bc_program_binOpRetire(&res);
return s;
}
#if ENABLE_DC
-static BcStatus bc_program_assignStr(BcProgram *p, BcResult *r, BcVec *v,
+static BcStatus bc_program_assignStr(BcResult *r, BcVec *v,
bool push)
{
BcNum n2;
res.t = BC_RESULT_STR;
if (!push) {
- if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK;
+ if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK;
bc_vec_pop(v);
- bc_vec_pop(&p->results);
+ bc_vec_pop(&G.prog.results);
}
- bc_vec_pop(&p->results);
+ bc_vec_pop(&G.prog.results);
- bc_vec_push(&p->results, &res);
+ bc_vec_push(&G.prog.results, &res);
bc_vec_push(v, &n2);
return BC_STATUS_SUCCESS;
}
#endif // ENABLE_DC
-static BcStatus bc_program_copyToVar(BcProgram *p, char *name, bool var)
+static BcStatus bc_program_copyToVar(char *name, bool var)
{
BcStatus s;
BcResult *ptr, r;
BcVec *v;
BcNum *n;
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
- ptr = bc_vec_top(&p->results);
+ ptr = bc_vec_top(&G.prog.results);
if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE;
- bc_program_search(p, name, &v, var);
+ v = bc_program_search(name, var);
#if ENABLE_DC
if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE;
- if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(p, ptr, v, true);
+ if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true);
#endif
- s = bc_program_num(p, ptr, &n, false);
+ s = bc_program_num(ptr, &n, false);
if (s) return s;
// Do this once more to make sure that pointers were not invalidated.
- bc_program_search(p, name, &v, var);
+ v = bc_program_search(name, var);
if (var) {
bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
}
bc_vec_push(v, &r.d);
- bc_vec_pop(&p->results);
+ bc_vec_pop(&G.prog.results);
return s;
}
-static BcStatus bc_program_assign(BcProgram *p, char inst)
+static BcStatus bc_program_assign(char inst)
{
BcStatus s;
BcResult *left, *right, res;
unsigned long val, max;
bool assign = inst == BC_INST_ASSIGN, ib, sc;
- s = bc_program_binOpPrep(p, &left, &l, &right, &r, assign);
+ s = bc_program_binOpPrep(&left, &l, &right, &r, assign);
if (s) return s;
ib = left->t == BC_RESULT_IBASE;
BcVec *v;
if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE;
- bc_program_search(p, left->d.id.name, &v, true);
+ v = bc_program_search(left->d.id.name, true);
- return bc_program_assignStr(p, right, v, false);
+ return bc_program_assignStr(right, v, false);
}
#endif
return BC_STATUS_PARSE_BAD_ASSIGN;
#if ENABLE_BC
- if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &p->zero))
+ if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
return BC_STATUS_MATH_DIVIDE_BY_ZERO;
if (assign)
bc_num_copy(l, r);
else
- s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, p->scale);
+ s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale);
if (s) return s;
#else
if (sc) {
max = BC_MAX_SCALE;
- ptr = &p->scale;
+ ptr = &G.prog.scale;
}
else {
if (val < BC_NUM_MIN_BASE) return s;
max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
- ptr = ib ? &p->ib_t : &p->ob_t;
+ ptr = ib ? &G.prog.ib_t : &G.prog.ob_t;
}
if (val > max) return s;
- if (!sc) bc_num_copy(ib ? &p->ib : &p->ob, l);
+ if (!sc) bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l);
*ptr = (size_t) val;
s = BC_STATUS_SUCCESS;
bc_num_init(&res.d.n, l->len);
bc_num_copy(&res.d.n, l);
- bc_program_binOpRetire(p, &res);
+ bc_program_binOpRetire(&res);
return s;
}
-static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn,
+#if !ENABLE_DC
+#define bc_program_pushVar(code, bgn, pop, copy) \
+ bc_program_pushVar(code, bgn)
+// for bc, 'pop' and 'copy' are always false
+#endif
+static BcStatus bc_program_pushVar(char *code, size_t *bgn,
bool pop, bool copy)
{
BcStatus s = BC_STATUS_SUCCESS;
BcResult r;
char *name = bc_program_name(code, bgn);
-#if ENABLE_DC // Exclude
- BcNum *num;
- BcVec *v;
-#else
- (void) pop, (void) copy;
-#endif
r.t = BC_RESULT_VAR;
r.d.id.name = name;
#if ENABLE_DC
- bc_program_search(p, name, &v, true);
- num = bc_vec_top(v);
+ {
+ BcVec *v = bc_program_search(name, true);
+ BcNum *num = bc_vec_top(v);
- if (pop || copy) {
+ if (pop || copy) {
+
+ if (!BC_PROG_STACK(v, 2 - copy)) {
+ free(name);
+ return BC_STATUS_EXEC_STACK;
+ }
- if (!BC_PROG_STACK(v, 2 - copy)) {
free(name);
- return BC_STATUS_EXEC_STACK;
- }
+ name = NULL;
- free(name);
- name = NULL;
+ if (!BC_PROG_STR(num)) {
- if (!BC_PROG_STR(num)) {
+ r.t = BC_RESULT_TEMP;
- r.t = BC_RESULT_TEMP;
+ bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
+ bc_num_copy(&r.d.n, num);
+ }
+ else {
+ r.t = BC_RESULT_STR;
+ r.d.id.idx = num->rdx;
+ }
- bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
- bc_num_copy(&r.d.n, num);
+ if (!copy) bc_vec_pop(v);
}
- else {
- r.t = BC_RESULT_STR;
- r.d.id.idx = num->rdx;
- }
-
- if (!copy) bc_vec_pop(v);
}
#endif // ENABLE_DC
- bc_vec_push(&p->results, &r);
+ bc_vec_push(&G.prog.results, &r);
return s;
}
-static BcStatus bc_program_pushArray(BcProgram *p, char *code, size_t *bgn,
+static BcStatus bc_program_pushArray(char *code, size_t *bgn,
char inst)
{
BcStatus s = BC_STATUS_SUCCESS;
if (inst == BC_INST_ARRAY) {
r.t = BC_RESULT_ARRAY;
- bc_vec_push(&p->results, &r);
+ bc_vec_push(&G.prog.results, &r);
}
else {
BcResult *operand;
unsigned long temp;
- s = bc_program_prep(p, &operand, &num);
+ s = bc_program_prep(&operand, &num);
if (s) goto err;
s = bc_num_ulong(num, &temp);
if (s) goto err;
}
r.d.id.idx = (size_t) temp;
- bc_program_retire(p, &r, BC_RESULT_ARRAY_ELEM);
+ bc_program_retire(&r, BC_RESULT_ARRAY_ELEM);
}
err:
}
#if ENABLE_BC
-static BcStatus bc_program_incdec(BcProgram *p, char inst)
+static BcStatus bc_program_incdec(char inst)
{
BcStatus s;
BcResult *ptr, res, copy;
BcNum *num = NULL;
char inst2 = inst;
- s = bc_program_prep(p, &ptr, &num);
+ s = bc_program_prep(&ptr, &num);
if (s) return s;
if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) {
BC_INST_ASSIGN_PLUS :
BC_INST_ASSIGN_MINUS;
- bc_vec_push(&p->results, &res);
- bc_program_assign(p, inst);
+ bc_vec_push(&G.prog.results, &res);
+ bc_program_assign(inst);
if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) {
- bc_vec_pop(&p->results);
- bc_vec_push(&p->results, ©);
+ bc_vec_pop(&G.prog.results);
+ bc_vec_push(&G.prog.results, ©);
}
return s;
}
-static BcStatus bc_program_call(BcProgram *p, char *code, size_t *idx)
+static BcStatus bc_program_call(char *code, size_t *idx)
{
BcStatus s = BC_STATUS_SUCCESS;
BcInstPtr ip;
size_t i, nparams = bc_program_index(code, idx);
BcFunc *func;
- BcVec *v;
BcId *a;
BcResultData param;
BcResult *arg;
ip.idx = 0;
ip.func = bc_program_index(code, idx);
- func = bc_vec_item(&p->fns, ip.func);
+ func = bc_vec_item(&G.prog.fns, ip.func);
if (func->code.len == 0) return BC_STATUS_EXEC_UNDEFINED_FUNC;
if (nparams != func->nparams) return BC_STATUS_EXEC_MISMATCHED_PARAMS;
- ip.len = p->results.len - nparams;
+ ip.len = G.prog.results.len - nparams;
for (i = 0; i < nparams; ++i) {
a = bc_vec_item(&func->autos, nparams - 1 - i);
- arg = bc_vec_top(&p->results);
+ arg = bc_vec_top(&G.prog.results);
if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR)
return BC_STATUS_EXEC_BAD_TYPE;
- s = bc_program_copyToVar(p, a->name, a->idx);
+ s = bc_program_copyToVar(a->name, a->idx);
if (s) return s;
}
for (; i < func->autos.len; ++i) {
+ BcVec *v;
a = bc_vec_item(&func->autos, i);
- bc_program_search(p, a->name, &v, a->idx);
+ v = bc_program_search(a->name, a->idx);
if (a->idx) {
bc_num_init(¶m.n, BC_NUM_DEF_SIZE);
}
}
- bc_vec_push(&p->stack, &ip);
+ bc_vec_push(&G.prog.stack, &ip);
return BC_STATUS_SUCCESS;
}
-static BcStatus bc_program_return(BcProgram *p, char inst)
+static BcStatus bc_program_return(char inst)
{
BcStatus s;
BcResult res;
BcFunc *f;
size_t i;
- BcInstPtr *ip = bc_vec_top(&p->stack);
+ BcInstPtr *ip = bc_vec_top(&G.prog.stack);
- if (!BC_PROG_STACK(&p->results, ip->len + inst == BC_INST_RET))
+ if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET))
return BC_STATUS_EXEC_STACK;
- f = bc_vec_item(&p->fns, ip->func);
+ f = bc_vec_item(&G.prog.fns, ip->func);
res.t = BC_RESULT_TEMP;
if (inst == BC_INST_RET) {
BcNum *num;
- BcResult *operand = bc_vec_top(&p->results);
+ BcResult *operand = bc_vec_top(&G.prog.results);
- s = bc_program_num(p, operand, &num, false);
+ s = bc_program_num(operand, &num, false);
if (s) return s;
bc_num_init(&res.d.n, num->len);
bc_num_copy(&res.d.n, num);
BcVec *v;
BcId *a = bc_vec_item(&f->autos, i);
- bc_program_search(p, a->name, &v, a->idx);
+ v = bc_program_search(a->name, a->idx);
bc_vec_pop(v);
}
- bc_vec_npop(&p->results, p->results.len - ip->len);
- bc_vec_push(&p->results, &res);
- bc_vec_pop(&p->stack);
+ bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len);
+ bc_vec_push(&G.prog.results, &res);
+ bc_vec_pop(&G.prog.stack);
return BC_STATUS_SUCCESS;
}
return len;
}
-static BcStatus bc_program_builtin(BcProgram *p, char inst)
+static BcStatus bc_program_builtin(char inst)
{
BcStatus s;
BcResult *opnd;
BcResult res;
bool len = inst == BC_INST_LENGTH;
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
- opnd = bc_vec_top(&p->results);
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
+ opnd = bc_vec_top(&G.prog.results);
- s = bc_program_num(p, opnd, &num, false);
+ s = bc_program_num(opnd, &num, false);
if (s) return s;
#if ENABLE_DC
bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
- if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, p->scale);
+ if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, G.prog.scale);
#if ENABLE_BC
else if (len != 0 && opnd->t == BC_RESULT_ARRAY) {
- s = bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
+ bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
}
#endif
#if ENABLE_DC
char **str;
size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx;
- str = bc_vec_item(&p->strs, idx);
- s = bc_num_ulong2num(&res.d.n, strlen(*str));
- if (s) goto err;
+ str = bc_vec_item(&G.prog.strs, idx);
+ bc_num_ulong2num(&res.d.n, strlen(*str));
}
#endif
else {
BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale;
- s = bc_num_ulong2num(&res.d.n, f(num));
- if (s) goto err;
+ bc_num_ulong2num(&res.d.n, f(num));
}
- bc_program_retire(p, &res, BC_RESULT_TEMP);
-
- return s;
+ bc_program_retire(&res, BC_RESULT_TEMP);
-err:
- bc_num_free(&res.d.n);
return s;
}
#if ENABLE_DC
-static BcStatus bc_program_divmod(BcProgram *p)
+static BcStatus bc_program_divmod(void)
{
BcStatus s;
BcResult *opd1, *opd2, res, res2;
BcNum *n1, *n2 = NULL;
- s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false);
+ s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
if (s) return s;
bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
bc_num_init(&res2.d.n, n2->len);
- s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, p->scale);
+ s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale);
if (s) goto err;
- bc_program_binOpRetire(p, &res2);
+ bc_program_binOpRetire(&res2);
res.t = BC_RESULT_TEMP;
- bc_vec_push(&p->results, &res);
+ bc_vec_push(&G.prog.results, &res);
return s;
return s;
}
-static BcStatus bc_program_modexp(BcProgram *p)
+static BcStatus bc_program_modexp(void)
{
BcStatus s;
BcResult *r1, *r2, *r3, res;
BcNum *n1, *n2, *n3;
- if (!BC_PROG_STACK(&p->results, 3)) return BC_STATUS_EXEC_STACK;
- s = bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, false);
+ if (!BC_PROG_STACK(&G.prog.results, 3)) return BC_STATUS_EXEC_STACK;
+ s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false);
if (s) return s;
- r1 = bc_vec_item_rev(&p->results, 2);
- s = bc_program_num(p, r1, &n1, false);
+ r1 = bc_vec_item_rev(&G.prog.results, 2);
+ s = bc_program_num(r1, &n1, false);
if (s) return s;
if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE;
if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) {
if (r1->t == r2->t) {
- s = bc_program_num(p, r2, &n2, false);
+ s = bc_program_num(r2, &n2, false);
if (s) return s;
}
if (r1->t == r3->t) {
- s = bc_program_num(p, r3, &n3, false);
+ s = bc_program_num(r3, &n3, false);
if (s) return s;
}
}
s = bc_num_modexp(n1, n2, n3, &res.d.n);
if (s) goto err;
- bc_vec_pop(&p->results);
- bc_program_binOpRetire(p, &res);
+ bc_vec_pop(&G.prog.results);
+ bc_program_binOpRetire(&res);
return s;
return s;
}
-static BcStatus bc_program_stackLen(BcProgram *p)
+static void bc_program_stackLen(void)
{
- BcStatus s;
BcResult res;
- size_t len = p->results.len;
+ size_t len = G.prog.results.len;
res.t = BC_RESULT_TEMP;
bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
- s = bc_num_ulong2num(&res.d.n, len);
- if (s) goto err;
- bc_vec_push(&p->results, &res);
-
- return s;
-
-err:
- bc_num_free(&res.d.n);
- return s;
+ bc_num_ulong2num(&res.d.n, len);
+ bc_vec_push(&G.prog.results, &res);
}
-static BcStatus bc_program_asciify(BcProgram *p)
+static BcStatus bc_program_asciify(void)
{
BcStatus s;
BcResult *r, res;
BcNum *num = NULL, n;
char *str, *str2, c;
- size_t len = p->strs.len, idx;
+ size_t len = G.prog.strs.len, idx;
unsigned long val;
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
- r = bc_vec_top(&p->results);
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
+ r = bc_vec_top(&G.prog.results);
- s = bc_program_num(p, r, &num, false);
+ s = bc_program_num(r, &num, false);
if (s) return s;
if (BC_PROG_NUM(r, num)) {
bc_num_copy(&n, num);
bc_num_truncate(&n, n.rdx);
- s = bc_num_mod(&n, &p->strmb, &n, 0);
+ s = bc_num_mod(&n, &G.prog.strmb, &n, 0);
if (s) goto num_err;
s = bc_num_ulong(&n, &val);
if (s) goto num_err;
}
else {
idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx;
- str2 = *((char **) bc_vec_item(&p->strs, idx));
+ str2 = *((char **) bc_vec_item(&G.prog.strs, idx));
c = str2[0];
}
str[1] = '\0';
str2 = xstrdup(str);
- bc_program_addFunc(p, str2, &idx);
+ bc_program_addFunc(str2, &idx);
if (idx != len + BC_PROG_REQ_FUNCS) {
- for (idx = 0; idx < p->strs.len; ++idx) {
- if (!strcmp(*((char **) bc_vec_item(&p->strs, idx)), str)) {
+ for (idx = 0; idx < G.prog.strs.len; ++idx) {
+ if (!strcmp(*((char **) bc_vec_item(&G.prog.strs, idx)), str)) {
len = idx;
break;
}
free(str);
}
else
- bc_vec_push(&p->strs, &str);
+ bc_vec_push(&G.prog.strs, &str);
res.t = BC_RESULT_STR;
res.d.id.idx = len;
- bc_vec_pop(&p->results);
- bc_vec_push(&p->results, &res);
+ bc_vec_pop(&G.prog.results);
+ bc_vec_push(&G.prog.results, &res);
return BC_STATUS_SUCCESS;
return s;
}
-static BcStatus bc_program_printStream(BcProgram *p)
+static BcStatus bc_program_printStream(void)
{
BcStatus s;
BcResult *r;
size_t idx;
char *str;
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
- r = bc_vec_top(&p->results);
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
+ r = bc_vec_top(&G.prog.results);
- s = bc_program_num(p, r, &n, false);
+ s = bc_program_num(r, &n, false);
if (s) return s;
if (BC_PROG_NUM(r, n))
- s = bc_num_stream(n, &p->strmb, &p->nchars, p->len);
+ s = bc_num_stream(n, &G.prog.strmb, &G.prog.nchars, G.prog.len);
else {
idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx;
- str = *((char **) bc_vec_item(&p->strs, idx));
+ str = *((char **) bc_vec_item(&G.prog.strs, idx));
printf("%s", str);
}
static BcStatus bc_program_nquit(void)
{
- BcProgram *p = &G.prog;
-
BcStatus s;
BcResult *opnd;
BcNum *num = NULL;
unsigned long val;
- s = bc_program_prep(p, &opnd, &num);
+ s = bc_program_prep(&opnd, &num);
if (s) return s;
s = bc_num_ulong(num, &val);
if (s) return s;
- bc_vec_pop(&p->results);
+ bc_vec_pop(&G.prog.results);
- if (p->stack.len < val)
+ if (G.prog.stack.len < val)
return BC_STATUS_EXEC_STACK;
- else if (p->stack.len == val)
+ else if (G.prog.stack.len == val)
return BC_STATUS_QUIT;
- bc_vec_npop(&p->stack, val);
+ bc_vec_npop(&G.prog.stack, val);
return s;
}
static BcStatus bc_program_execStr(char *code, size_t *bgn,
bool cond)
{
- BcProgram *p = &G.prog;
-
BcStatus s = BC_STATUS_SUCCESS;
BcResult *r;
char **str;
BcNum *n;
bool exec;
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
- r = bc_vec_top(&p->results);
+ r = bc_vec_top(&G.prog.results);
if (cond) {
- BcVec *v;
char *name, *then_name = bc_program_name(code, bgn), *else_name = NULL;
if (code[*bgn] == BC_PARSE_STREND)
}
if (exec) {
- bc_program_search(p, name, &v, true);
+ BcVec *v;
+ v = bc_program_search(name, true);
n = bc_vec_top(v);
}
if (r->t == BC_RESULT_STR)
sidx = r->d.id.idx;
else if (r->t == BC_RESULT_VAR) {
- s = bc_program_num(p, r, &n, false);
+ s = bc_program_num(r, &n, false);
if (s || !BC_PROG_STR(n)) goto exit;
sidx = n->rdx;
}
fidx = sidx + BC_PROG_REQ_FUNCS;
- str = bc_vec_item(&p->strs, sidx);
- f = bc_vec_item(&p->fns, fidx);
+ str = bc_vec_item(&G.prog.strs, sidx);
+ f = bc_vec_item(&G.prog.fns, fidx);
if (f->code.len == 0) {
- common_parse_init(&prs, p, fidx);
+ common_parse_init(&prs, fidx);
s = bc_parse_text(&prs, *str);
if (s) goto err;
s = common_parse_expr(&prs, BC_PARSE_NOCALL);
}
ip.idx = 0;
- ip.len = p->results.len;
+ ip.len = G.prog.results.len;
ip.func = fidx;
- bc_vec_pop(&p->results);
- bc_vec_push(&p->stack, &ip);
+ bc_vec_pop(&G.prog.results);
+ bc_vec_push(&G.prog.stack, &ip);
return BC_STATUS_SUCCESS;
err:
bc_parse_free(&prs);
- f = bc_vec_item(&p->fns, fidx);
+ f = bc_vec_item(&G.prog.fns, fidx);
bc_vec_npop(&f->code, f->code.len);
exit:
- bc_vec_pop(&p->results);
+ bc_vec_pop(&G.prog.results);
return s;
}
#endif // ENABLE_DC
-static BcStatus bc_program_pushGlobal(BcProgram *p, char inst)
+static void bc_program_pushGlobal(char inst)
{
- BcStatus s;
BcResult res;
unsigned long val;
res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
if (inst == BC_INST_IBASE)
- val = (unsigned long) p->ib_t;
+ val = (unsigned long) G.prog.ib_t;
else if (inst == BC_INST_SCALE)
- val = (unsigned long) p->scale;
+ val = (unsigned long) G.prog.scale;
else
- val = (unsigned long) p->ob_t;
+ val = (unsigned long) G.prog.ob_t;
bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
- s = bc_num_ulong2num(&res.d.n, val);
- if (s) goto err;
- bc_vec_push(&p->results, &res);
-
- return s;
-
-err:
- bc_num_free(&res.d.n);
- return s;
+ bc_num_ulong2num(&res.d.n, val);
+ bc_vec_push(&G.prog.results, &res);
}
-static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx)
+static void bc_program_addFunc(char *name, size_t *idx)
{
BcStatus s;
BcId entry, *entry_ptr;
BcFunc f;
entry.name = name;
- entry.idx = p->fns.len;
+ entry.idx = G.prog.fns.len;
- s = bc_map_insert(&p->fn_map, &entry, idx);
+ s = bc_map_insert(&G.prog.fn_map, &entry, idx);
if (s) free(name);
- entry_ptr = bc_vec_item(&p->fn_map, *idx);
+ entry_ptr = bc_vec_item(&G.prog.fn_map, *idx);
*idx = entry_ptr->idx;
if (s == BC_STATUS_VEC_ITEM_EXISTS) {
- BcFunc *func = bc_vec_item(&p->fns, entry_ptr->idx);
+ BcFunc *func = bc_vec_item(&G.prog.fns, entry_ptr->idx);
// We need to reset these, so the function can be repopulated.
func->nparams = 0;
}
else {
bc_func_init(&f);
- bc_vec_push(&p->fns, &f);
+ bc_vec_push(&G.prog.fns, &f);
}
}
-static BcStatus bc_program_reset(BcProgram *p, BcStatus s)
+static BcStatus bc_program_reset(BcStatus s)
{
BcFunc *f;
BcInstPtr *ip;
- bc_vec_npop(&p->stack, p->stack.len - 1);
- bc_vec_npop(&p->results, p->results.len);
+ bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1);
+ bc_vec_npop(&G.prog.results, G.prog.results.len);
- f = bc_vec_item(&p->fns, 0);
- ip = bc_vec_top(&p->stack);
+ f = bc_vec_item(&G.prog.fns, 0);
+ ip = bc_vec_top(&G.prog.stack);
ip->idx = f->code.len;
if (!s && G_interrupt && !G.tty) return BC_STATUS_QUIT;
static BcStatus bc_program_exec(void)
{
- BcProgram *p = &G.prog;
-
BcStatus s = BC_STATUS_SUCCESS;
size_t idx;
BcResult r, *ptr;
BcNum *num;
- BcInstPtr *ip = bc_vec_top(&p->stack);
- BcFunc *func = bc_vec_item(&p->fns, ip->func);
+ BcInstPtr *ip = bc_vec_top(&G.prog.stack);
+ BcFunc *func = bc_vec_item(&G.prog.fns, ip->func);
char *code = func->code.v;
bool cond = false;
#if ENABLE_BC
case BC_INST_JUMP_ZERO:
{
- s = bc_program_prep(p, &ptr, &num);
+ s = bc_program_prep(&ptr, &num);
if (s) return s;
- cond = !bc_num_cmp(num, &p->zero);
- bc_vec_pop(&p->results);
+ cond = !bc_num_cmp(num, &G.prog.zero);
+ bc_vec_pop(&G.prog.results);
}
// Fallthrough.
case BC_INST_JUMP:
case BC_INST_CALL:
{
- s = bc_program_call(p, code, &ip->idx);
+ s = bc_program_call(code, &ip->idx);
break;
}
case BC_INST_INC_POST:
case BC_INST_DEC_POST:
{
- s = bc_program_incdec(p, inst);
+ s = bc_program_incdec(inst);
break;
}
case BC_INST_RET:
case BC_INST_RET0:
{
- s = bc_program_return(p, inst);
+ s = bc_program_return(inst);
break;
}
case BC_INST_REL_LT:
case BC_INST_REL_GT:
{
- s = bc_program_logical(p, inst);
+ s = bc_program_logical(inst);
break;
}
case BC_INST_VAR:
{
- s = bc_program_pushVar(p, code, &ip->idx, false, false);
+ s = bc_program_pushVar(code, &ip->idx, false, false);
break;
}
case BC_INST_ARRAY_ELEM:
case BC_INST_ARRAY:
{
- s = bc_program_pushArray(p, code, &ip->idx, inst);
+ s = bc_program_pushArray(code, &ip->idx, inst);
break;
}
case BC_INST_LAST:
{
r.t = BC_RESULT_LAST;
- bc_vec_push(&p->results, &r);
+ bc_vec_push(&G.prog.results, &r);
break;
}
case BC_INST_SCALE:
case BC_INST_OBASE:
{
- s = bc_program_pushGlobal(p, inst);
+ bc_program_pushGlobal(inst);
break;
}
case BC_INST_LENGTH:
case BC_INST_SQRT:
{
- s = bc_program_builtin(p, inst);
+ s = bc_program_builtin(inst);
break;
}
{
r.t = BC_RESULT_CONSTANT;
r.d.id.idx = bc_program_index(code, &ip->idx);
- bc_vec_push(&p->results, &r);
+ bc_vec_push(&G.prog.results, &r);
break;
}
case BC_INST_POP:
{
- if (!BC_PROG_STACK(&p->results, 1))
+ if (!BC_PROG_STACK(&G.prog.results, 1))
s = BC_STATUS_EXEC_STACK;
else
- bc_vec_pop(&p->results);
+ bc_vec_pop(&G.prog.results);
break;
}
case BC_INST_POP_EXEC:
{
- bc_vec_pop(&p->stack);
+ bc_vec_pop(&G.prog.stack);
break;
}
case BC_INST_PRINT_POP:
case BC_INST_PRINT_STR:
{
- s = bc_program_print(p, inst, 0);
+ s = bc_program_print(inst, 0);
break;
}
{
r.t = BC_RESULT_STR;
r.d.id.idx = bc_program_index(code, &ip->idx);
- bc_vec_push(&p->results, &r);
+ bc_vec_push(&G.prog.results, &r);
break;
}
case BC_INST_PLUS:
case BC_INST_MINUS:
{
- s = bc_program_op(p, inst);
+ s = bc_program_op(inst);
break;
}
case BC_INST_BOOL_NOT:
{
- s = bc_program_prep(p, &ptr, &num);
+ s = bc_program_prep(&ptr, &num);
if (s) return s;
bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
- (!bc_num_cmp(num, &p->zero) ? bc_num_one : bc_num_zero)(&r.d.n);
- bc_program_retire(p, &r, BC_RESULT_TEMP);
+ (!bc_num_cmp(num, &G.prog.zero) ? bc_num_one : bc_num_zero)(&r.d.n);
+ bc_program_retire(&r, BC_RESULT_TEMP);
break;
}
case BC_INST_NEG:
{
- s = bc_program_negate(p);
+ s = bc_program_negate();
break;
}
#endif
case BC_INST_ASSIGN:
{
- s = bc_program_assign(p, inst);
+ s = bc_program_assign(inst);
break;
}
#if ENABLE_DC
case BC_INST_MODEXP:
{
- s = bc_program_modexp(p);
+ s = bc_program_modexp();
break;
}
case BC_INST_DIVMOD:
{
- s = bc_program_divmod(p);
+ s = bc_program_divmod();
break;
}
case BC_INST_PRINT_STACK:
{
- for (idx = 0; !s && idx < p->results.len; ++idx)
- s = bc_program_print(p, BC_INST_PRINT, idx);
+ for (idx = 0; !s && idx < G.prog.results.len; ++idx)
+ s = bc_program_print(BC_INST_PRINT, idx);
break;
}
case BC_INST_CLEAR_STACK:
{
- bc_vec_npop(&p->results, p->results.len);
+ bc_vec_npop(&G.prog.results, G.prog.results.len);
break;
}
case BC_INST_STACK_LEN:
{
- s = bc_program_stackLen(p);
+ bc_program_stackLen();
break;
}
case BC_INST_DUPLICATE:
{
- if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
- ptr = bc_vec_top(&p->results);
+ if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK;
+ ptr = bc_vec_top(&G.prog.results);
bc_result_copy(&r, ptr);
- bc_vec_push(&p->results, &r);
+ bc_vec_push(&G.prog.results, &r);
break;
}
{
BcResult *ptr2;
- if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK;
+ if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK;
- ptr = bc_vec_item_rev(&p->results, 0);
- ptr2 = bc_vec_item_rev(&p->results, 1);
+ 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));
case BC_INST_ASCIIFY:
{
- s = bc_program_asciify(p);
+ s = bc_program_asciify();
break;
}
case BC_INST_PRINT_STREAM:
{
- s = bc_program_printStream(p);
+ s = bc_program_printStream();
break;
}
case BC_INST_PUSH_VAR:
{
bool copy = inst == BC_INST_LOAD;
- s = bc_program_pushVar(p, code, &ip->idx, true, copy);
+ s = bc_program_pushVar(code, &ip->idx, true, copy);
break;
}
case BC_INST_PUSH_TO_VAR:
{
char *name = bc_program_name(code, &ip->idx);
- s = bc_program_copyToVar(p, name, true);
+ s = bc_program_copyToVar(name, true);
free(name);
break;
}
case BC_INST_QUIT:
{
- if (p->stack.len <= 2)
+ if (G.prog.stack.len <= 2)
s = BC_STATUS_QUIT;
else
- bc_vec_npop(&p->stack, 2);
+ bc_vec_npop(&G.prog.stack, 2);
break;
}
#endif // ENABLE_DC
}
- if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(p, s);
+ if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(s);
// If the stack has changed, pointers may be invalid.
- ip = bc_vec_top(&p->stack);
- func = bc_vec_item(&p->fns, ip->func);
+ ip = bc_vec_top(&G.prog.stack);
+ func = bc_vec_item(&G.prog.fns, ip->func);
code = func->code.v;
}
{
if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s;
- fprintf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
+ fprintf(stderr, bc_err_fmt, bc_err_msgs[s]);
fprintf(stderr, " %s", file);
fprintf(stderr, bc_err_line + 4 * !line, line);
static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
const char *msg)
{
- int p = (int) G_posix, w = (int) G_warn;
- const char *const fmt = p ? bc_err_fmt : bc_warn_fmt;
+ const char *fmt;
- if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
+ if (!(G.flags & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS;
+ if (s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
- fprintf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
+ fmt = G_posix ? bc_err_fmt : bc_warn_fmt;
+ fprintf(stderr, fmt, bc_err_msgs[s]);
if (msg) fprintf(stderr, " %s\n", msg);
fprintf(stderr, " %s", file);
fprintf(stderr, bc_err_line + 4 * !line, line);
- return s * (!G.ttyin && !!p);
+ if (G.ttyin || !G_posix)
+ s = BC_STATUS_SUCCESS;
+ return s;
}
static void bc_vm_envArgs(void)
{
+ static const char* const bc_args_env_name = "BC_ENV_ARGS";
+
BcVec v;
char *env_args = getenv(bc_args_env_name), *buf;
if (s == BC_STATUS_LIMITS) {
- bb_putchar('\n');
- printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE);
- printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM);
- printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE);
- printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING);
- printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME);
- printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM);
- printf("Max Exponent = %lu\n", BC_MAX_EXP);
- printf("Number of Vars = %lu\n", BC_MAX_VARS);
- bb_putchar('\n');
+ printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE);
+ printf("BC_DIM_MAX = %u\n", BC_MAX_DIM);
+ printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE);
+ printf("BC_STRING_MAX = %u\n", BC_MAX_STRING);
+ printf("BC_NAME_MAX = %u\n", BC_MAX_NAME);
+ printf("BC_NUM_MAX = %u\n", BC_MAX_NUM);
+ printf("MAX Exponent = %lu\n", BC_MAX_EXP);
+ printf("Number of vars = %lu\n", BC_MAX_VARS);
s = BC_STATUS_SUCCESS;
}
s = bc_program_exec();
if (!s && G.tty) fflush(stdout);
if (s && s != BC_STATUS_QUIT)
- s = bc_vm_error(bc_program_reset(&G.prog, s), G.prs.l.f, 0);
+ s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0);
}
return s;
BcInstPtr *ip;
G.prog.file = file;
- s = bc_read_file(file, &data);
- if (s) return bc_vm_error(s, file, 0);
+ data = bc_read_file(file);
+ if (!data) return bc_vm_error(BC_STATUS_BIN_FILE, file, 0);
bc_lex_file(&G.prs.l, file);
s = bc_vm_process(data);
static BcStatus bc_vm_stdin(void)
{
- BcStatus s = BC_STATUS_SUCCESS;
+ BcStatus s;
BcVec buf, buffer;
- char c;
size_t len, i, str = 0;
- bool comment = false, notend;
+ bool comment = false;
G.prog.file = bc_program_stdin_name;
bc_lex_file(&G.prs.l, bc_program_stdin_name);
// with a backslash to the parser. The reason for that is because the parser
// treats a backslash+newline combo as whitespace, per the bc spec. In that
// case, and for strings and comments, the parser will expect more stuff.
- for (s = bc_read_line(&buf, ">>> "); !s; s = bc_read_line(&buf, ">>> ")) {
+ while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) {
char *string = buf.v;
for (i = 0; i < len; ++i) {
- notend = len > i + 1;
- c = string[i];
+ bool notend = len > i + 1;
+ char c = string[i];
if (i - 1 > len || string[i - 1] != '\\') {
if (G.sbgn == G.send)
}
#if ENABLE_FEATURE_CLEAN_UP
-static void bc_program_free(BcProgram *p)
+static void bc_program_free()
{
- bc_num_free(&p->ib);
- bc_num_free(&p->ob);
- bc_num_free(&p->hexb);
+ bc_num_free(&G.prog.ib);
+ bc_num_free(&G.prog.ob);
+ bc_num_free(&G.prog.hexb);
# if ENABLE_DC
- bc_num_free(&p->strmb);
+ bc_num_free(&G.prog.strmb);
# endif
- bc_vec_free(&p->fns);
- bc_vec_free(&p->fn_map);
- bc_vec_free(&p->vars);
- bc_vec_free(&p->var_map);
- bc_vec_free(&p->arrs);
- bc_vec_free(&p->arr_map);
- bc_vec_free(&p->strs);
- bc_vec_free(&p->consts);
- bc_vec_free(&p->results);
- bc_vec_free(&p->stack);
- bc_num_free(&p->last);
- bc_num_free(&p->zero);
- bc_num_free(&p->one);
+ bc_vec_free(&G.prog.fns);
+ bc_vec_free(&G.prog.fn_map);
+ bc_vec_free(&G.prog.vars);
+ bc_vec_free(&G.prog.var_map);
+ bc_vec_free(&G.prog.arrs);
+ bc_vec_free(&G.prog.arr_map);
+ bc_vec_free(&G.prog.strs);
+ bc_vec_free(&G.prog.consts);
+ bc_vec_free(&G.prog.results);
+ bc_vec_free(&G.prog.stack);
+ bc_num_free(&G.prog.last);
+ bc_num_free(&G.prog.zero);
+ bc_num_free(&G.prog.one);
}
static void bc_vm_free(void)
{
bc_vec_free(&G.files);
- bc_program_free(&G.prog);
+ bc_program_free();
bc_parse_free(&G.prs);
free(G.env_args);
}
bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free);
bc_map_init(&G.prog.fn_map);
- bc_program_addFunc(&G.prog, xstrdup(bc_func_main), &idx);
- bc_program_addFunc(&G.prog, xstrdup(bc_func_read), &idx);
+ bc_program_addFunc(xstrdup("(main)"), &idx);
+ bc_program_addFunc(xstrdup("(read)"), &idx);
bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free);
bc_map_init(&G.prog.var_map);
bc_program_init(len);
if (IS_BC) {
- bc_parse_init(&G.prs, &G.prog, BC_PROG_MAIN);
+ bc_parse_init(&G.prs, BC_PROG_MAIN);
} else {
- dc_parse_init(&G.prs, &G.prog, BC_PROG_MAIN);
+ dc_parse_init(&G.prs, BC_PROG_MAIN);
}
}