bc: convert to "G trick" - this returns bc to zero bss increase
function old new delta bc_num_p 518 540 +22 bc_num_k 1010 1031 +21 bc_vm_process 312 327 +15 bc_program_exec 4401 4413 +12 bc_vm_posixError 194 205 +11 bc_num_a 480 491 +11 bc_program_reset 182 192 +10 bc_vm_sig 88 97 +9 bc_vm_error 148 156 +8 bc_parse_expr 2215 2222 +7 bc_num_compare 84 90 +6 dc_parse_parse 53 58 +5 dc_lex_token 670 675 +5 bc_read_line 359 364 +5 bc_parse_parse 471 476 +5 bc_num_cmp 294 299 +5 bc_num_subArrays 84 82 -2 bc_num_d 614 609 -5 dc_main 80 72 -8 bc_main 80 72 -8 bcg 40 - -40 bc_vm_run 2569 2382 -187 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 16/5 up/down: 157/-250) Total: -93 bytes text data bss dec hex filename 989425 485 7336 997246 f377e busybox_old 989372 485 7296 997153 f3721 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
5a9fef5b59
commit
6d9146ab56
292
miscutils/bc.c
292
miscutils/bc.c
@ -812,44 +812,39 @@ static BcStatus bc_program_exec(BcProgram *p);
|
|||||||
#define BC_MAX_EXP ((unsigned long) LONG_MAX)
|
#define BC_MAX_EXP ((unsigned long) LONG_MAX)
|
||||||
#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
|
#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
|
||||||
|
|
||||||
typedef struct BcVmExe {
|
struct globals {
|
||||||
BcParseInit init;
|
BcParseInit init;
|
||||||
BcParseExpr exp;
|
BcParseExpr exp;
|
||||||
char sbgn;
|
char sbgn;
|
||||||
char send;
|
char send;
|
||||||
} BcVmExe;
|
|
||||||
|
|
||||||
typedef struct BcVm {
|
|
||||||
|
|
||||||
BcParse prs;
|
BcParse prs;
|
||||||
BcProgram prog;
|
BcProgram prog;
|
||||||
|
|
||||||
uint32_t flags;
|
unsigned flags;
|
||||||
BcVec files;
|
BcVec files;
|
||||||
|
|
||||||
char *env_args;
|
char *env_args;
|
||||||
BcVmExe exe;
|
|
||||||
|
|
||||||
} BcVm;
|
unsigned sig; //counter?
|
||||||
|
unsigned sigc; //counter?
|
||||||
|
smallint signe; //flag
|
||||||
|
|
||||||
typedef struct BcGlobals {
|
smallint tty;
|
||||||
|
smallint ttyin;
|
||||||
unsigned long sig;
|
|
||||||
unsigned long sigc;
|
|
||||||
unsigned long signe;
|
|
||||||
|
|
||||||
long tty;
|
|
||||||
long ttyin;
|
|
||||||
long posix;
|
|
||||||
long warn;
|
|
||||||
long exreg;
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_BC_SIGNALS
|
#if ENABLE_FEATURE_BC_SIGNALS
|
||||||
const char *sig_msg;
|
const char *sig_msg;
|
||||||
#endif
|
#endif
|
||||||
const char *help;
|
} FIX_ALIASING;
|
||||||
|
#define G (*ptr_to_globals)
|
||||||
|
#define INIT_G() do { \
|
||||||
|
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
|
||||||
|
} while (0)
|
||||||
|
#define G_posix (ENABLE_BC && (G.flags & BC_FLAG_S))
|
||||||
|
#define G_warn (ENABLE_BC && (G.flags & BC_FLAG_W))
|
||||||
|
#define G_exreg (ENABLE_DC && (G.flags & BC_FLAG_X))
|
||||||
|
|
||||||
} BcGlobals;
|
|
||||||
|
|
||||||
#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
|
#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
|
||||||
|
|
||||||
@ -860,8 +855,6 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
|
|||||||
|
|
||||||
static void bc_vm_info(void);
|
static void bc_vm_info(void);
|
||||||
|
|
||||||
static BcGlobals bcg;
|
|
||||||
|
|
||||||
static const char* const bc_args_env_name = "BC_ENV_ARGS";
|
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_err_fmt[] = "\n%s error: %s\n";
|
||||||
@ -1356,7 +1349,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
|
|||||||
int i;
|
int i;
|
||||||
signed char c;
|
signed char c;
|
||||||
|
|
||||||
if (bcg.ttyin && !bcg.posix) {
|
if (G.ttyin && !G_posix) {
|
||||||
fputs(prompt, stderr);
|
fputs(prompt, stderr);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
@ -1373,11 +1366,11 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
|
|||||||
if (i == EOF) {
|
if (i == EOF) {
|
||||||
#if ENABLE_FEATURE_BC_SIGNALS
|
#if ENABLE_FEATURE_BC_SIGNALS
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
bcg.sigc = bcg.sig;
|
G.sigc = G.sig;
|
||||||
bcg.signe = 0;
|
G.signe = 0;
|
||||||
if (bcg.ttyin) {
|
if (G.ttyin) {
|
||||||
fputs(bc_program_ready_msg, stderr);
|
fputs(bc_program_ready_msg, stderr);
|
||||||
if (!bcg.posix) fputs(prompt, stderr);
|
if (!G_posix) fputs(prompt, stderr);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
clearerr(stdin);
|
clearerr(stdin);
|
||||||
@ -1478,20 +1471,20 @@ static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
|
|||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
for (i = 0; !bcg.signe && i < len; ++i) {
|
for (i = 0; !G.signe && i < len; ++i) {
|
||||||
for (a[i] -= b[i], j = 0; !bcg.signe && a[i + j] < 0;) {
|
for (a[i] -= b[i], j = 0; !G.signe && a[i + j] < 0;) {
|
||||||
a[i + j++] += 10;
|
a[i + j++] += 10;
|
||||||
a[i + j] -= 1;
|
a[i + j] -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
|
return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
|
static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (i = len - 1; !bcg.signe && i < len && !(c = a[i] - b[i]); --i);
|
for (i = len - 1; !G.signe && i < len && !(c = a[i] - b[i]); --i);
|
||||||
return BC_NUM_NEG(i + 1, c < 0);
|
return BC_NUM_NEG(i + 1, c < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1537,7 +1530,7 @@ static ssize_t bc_num_cmp(BcNum *a, BcNum *b)
|
|||||||
cmp = bc_num_compare(max_num, min_num, b_int + min);
|
cmp = bc_num_compare(max_num, min_num, b_int + min);
|
||||||
if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg);
|
if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg);
|
||||||
|
|
||||||
for (max_num -= diff, i = diff - 1; !bcg.signe && i < diff; --i) {
|
for (max_num -= diff, i = diff - 1; !G.signe && i < diff; --i) {
|
||||||
if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg);
|
if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1696,13 +1689,13 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
|
|||||||
ptr = ptr_b;
|
ptr = ptr_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (carry = 0, i = 0; !bcg.signe && i < min_rdx + min_int; ++i, ++c->len) {
|
for (carry = 0, i = 0; !G.signe && i < min_rdx + min_int; ++i, ++c->len) {
|
||||||
in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry;
|
in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry;
|
||||||
carry = in / 10;
|
carry = in / 10;
|
||||||
ptr_c[i] = (BcDig)(in % 10);
|
ptr_c[i] = (BcDig)(in % 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; !bcg.signe && i < max + min_rdx; ++i, ++c->len) {
|
for (; !G.signe && i < max + min_rdx; ++i, ++c->len) {
|
||||||
in = ((int) ptr[i]) + carry;
|
in = ((int) ptr[i]) + carry;
|
||||||
carry = in / 10;
|
carry = in / 10;
|
||||||
ptr_c[i] = (BcDig)(in % 10);
|
ptr_c[i] = (BcDig)(in % 10);
|
||||||
@ -1710,7 +1703,7 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
|
|||||||
|
|
||||||
if (carry != 0) c->num[c->len++] = (BcDig) carry;
|
if (carry != 0) c->num[c->len++] = (BcDig) carry;
|
||||||
|
|
||||||
return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
|
return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
|
static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
|
||||||
@ -1785,7 +1778,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b,
|
|||||||
BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
|
BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
|
||||||
bool aone = BC_NUM_ONE(a);
|
bool aone = BC_NUM_ONE(a);
|
||||||
|
|
||||||
if (bcg.signe) return BC_STATUS_EXEC_SIGNAL;
|
if (G.signe) return BC_STATUS_EXEC_SIGNAL;
|
||||||
if (a->len == 0 || b->len == 0) {
|
if (a->len == 0 || b->len == 0) {
|
||||||
bc_num_zero(c);
|
bc_num_zero(c);
|
||||||
return BC_STATUS_SUCCESS;
|
return BC_STATUS_SUCCESS;
|
||||||
@ -1803,9 +1796,9 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b,
|
|||||||
memset(c->num, 0, sizeof(BcDig) * c->cap);
|
memset(c->num, 0, sizeof(BcDig) * c->cap);
|
||||||
c->len = carry = len = 0;
|
c->len = carry = len = 0;
|
||||||
|
|
||||||
for (i = 0; !bcg.signe && i < b->len; ++i) {
|
for (i = 0; !G.signe && i < b->len; ++i) {
|
||||||
|
|
||||||
for (j = 0; !bcg.signe && j < a->len; ++j) {
|
for (j = 0; !G.signe && j < a->len; ++j) {
|
||||||
int in = (int) c->num[i + j];
|
int in = (int) c->num[i + j];
|
||||||
in += ((int) a->num[j]) * ((int) b->num[i]) + carry;
|
in += ((int) a->num[j]) * ((int) b->num[i]) + carry;
|
||||||
carry = in / 10;
|
carry = in / 10;
|
||||||
@ -1819,7 +1812,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b,
|
|||||||
|
|
||||||
c->len = len;
|
c->len = len;
|
||||||
|
|
||||||
return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
|
return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bc_num_init(&l1, max);
|
bc_num_init(&l1, max);
|
||||||
@ -1969,7 +1962,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
|
|||||||
c->len = cp.len;
|
c->len = cp.len;
|
||||||
p = b->num;
|
p = b->num;
|
||||||
|
|
||||||
for (i = end - 1; !bcg.signe && !s && i < end; --i) {
|
for (i = end - 1; !G.signe && !s && i < end; --i) {
|
||||||
n = cp.num + i;
|
n = cp.num + i;
|
||||||
for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
|
for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
|
||||||
s = bc_num_subArrays(n, p, len);
|
s = bc_num_subArrays(n, p, len);
|
||||||
@ -2069,20 +2062,20 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
|
|||||||
|
|
||||||
b->neg = neg;
|
b->neg = neg;
|
||||||
|
|
||||||
for (powrdx = a->rdx; !bcg.signe && !(pow & 1); pow >>= 1) {
|
for (powrdx = a->rdx; !G.signe && !(pow & 1); pow >>= 1) {
|
||||||
powrdx <<= 1;
|
powrdx <<= 1;
|
||||||
s = bc_num_mul(©, ©, ©, powrdx);
|
s = bc_num_mul(©, ©, ©, powrdx);
|
||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcg.signe) {
|
if (G.signe) {
|
||||||
s = BC_STATUS_EXEC_SIGNAL;
|
s = BC_STATUS_EXEC_SIGNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bc_num_copy(c, ©);
|
bc_num_copy(c, ©);
|
||||||
|
|
||||||
for (resrdx = powrdx, pow >>= 1; !bcg.signe && pow != 0; pow >>= 1) {
|
for (resrdx = powrdx, pow >>= 1; !G.signe && pow != 0; pow >>= 1) {
|
||||||
|
|
||||||
powrdx <<= 1;
|
powrdx <<= 1;
|
||||||
s = bc_num_mul(©, ©, ©, powrdx);
|
s = bc_num_mul(©, ©, ©, powrdx);
|
||||||
@ -2100,7 +2093,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
|
|||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcg.signe) {
|
if (G.signe) {
|
||||||
s = BC_STATUS_EXEC_SIGNAL;
|
s = BC_STATUS_EXEC_SIGNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -2657,7 +2650,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
|
|||||||
resrdx = scale + 2;
|
resrdx = scale + 2;
|
||||||
len = BC_NUM_INT(x0) + resrdx - 1;
|
len = BC_NUM_INT(x0) + resrdx - 1;
|
||||||
|
|
||||||
while (!bcg.signe && (cmp != 0 || digs < len)) {
|
while (!G.signe && (cmp != 0 || digs < len)) {
|
||||||
|
|
||||||
s = bc_num_div(a, x0, &f, resrdx);
|
s = bc_num_div(a, x0, &f, resrdx);
|
||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
@ -2685,7 +2678,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
|
|||||||
x1 = temp;
|
x1 = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcg.signe) {
|
if (G.signe) {
|
||||||
s = BC_STATUS_EXEC_SIGNAL;
|
s = BC_STATUS_EXEC_SIGNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -3461,7 +3454,7 @@ static BcStatus dc_lex_register(BcLex *l)
|
|||||||
if (isspace(l->buf[l->i - 1])) {
|
if (isspace(l->buf[l->i - 1])) {
|
||||||
bc_lex_whitespace(l);
|
bc_lex_whitespace(l);
|
||||||
++l->i;
|
++l->i;
|
||||||
if (!bcg.exreg)
|
if (!G_exreg)
|
||||||
s = BC_STATUS_LEX_EXTENDED_REG;
|
s = BC_STATUS_LEX_EXTENDED_REG;
|
||||||
else
|
else
|
||||||
s = bc_lex_name(l);
|
s = bc_lex_name(l);
|
||||||
@ -4782,7 +4775,7 @@ static BcStatus bc_parse_parse(BcParse *p)
|
|||||||
else
|
else
|
||||||
s = bc_parse_stmt(p);
|
s = bc_parse_stmt(p);
|
||||||
|
|
||||||
if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || bcg.signe)
|
if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G.signe)
|
||||||
s = bc_parse_reset(p, s);
|
s = bc_parse_reset(p, s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@ -4802,7 +4795,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
|
|||||||
paren_expr = rprn = done = get_token = assign = false;
|
paren_expr = rprn = done = get_token = assign = false;
|
||||||
bin_last = true;
|
bin_last = true;
|
||||||
|
|
||||||
for (; !bcg.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) {
|
for (; !G.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
|
|
||||||
case BC_LEX_OP_INC:
|
case BC_LEX_OP_INC:
|
||||||
@ -4996,7 +4989,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s) return s;
|
if (s) return s;
|
||||||
if (bcg.signe) return BC_STATUS_EXEC_SIGNAL;
|
if (G.signe) return BC_STATUS_EXEC_SIGNAL;
|
||||||
|
|
||||||
while (p->ops.len > ops_bgn) {
|
while (p->ops.len > ops_bgn) {
|
||||||
|
|
||||||
@ -5256,7 +5249,7 @@ static BcStatus dc_parse_parse(BcParse *p)
|
|||||||
else
|
else
|
||||||
s = dc_parse_expr(p, 0);
|
s = dc_parse_expr(p, 0);
|
||||||
|
|
||||||
if (s || bcg.signe) s = bc_parse_reset(p, s);
|
if (s || G.signe) s = bc_parse_reset(p, s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -6639,13 +6632,13 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s)
|
|||||||
ip = bc_vec_top(&p->stack);
|
ip = bc_vec_top(&p->stack);
|
||||||
ip->idx = f->code.len;
|
ip->idx = f->code.len;
|
||||||
|
|
||||||
if (!s && bcg.signe && !bcg.tty) return BC_STATUS_QUIT;
|
if (!s && G.signe && !G.tty) return BC_STATUS_QUIT;
|
||||||
|
|
||||||
bcg.sigc += bcg.signe;
|
G.sigc += G.signe;
|
||||||
bcg.signe = bcg.sig != bcg.sigc;
|
G.signe = G.sig != G.sigc;
|
||||||
|
|
||||||
if (!s || s == BC_STATUS_EXEC_SIGNAL) {
|
if (!s || s == BC_STATUS_EXEC_SIGNAL) {
|
||||||
if (bcg.ttyin) {
|
if (G.ttyin) {
|
||||||
fputs(bc_program_ready_msg, stderr);
|
fputs(bc_program_ready_msg, stderr);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
s = BC_STATUS_SUCCESS;
|
s = BC_STATUS_SUCCESS;
|
||||||
@ -6966,7 +6959,7 @@ static BcStatus bc_program_exec(BcProgram *p)
|
|||||||
#endif // ENABLE_DC
|
#endif // ENABLE_DC
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((s && s != BC_STATUS_QUIT) || bcg.signe) s = bc_program_reset(p, s);
|
if ((s && s != BC_STATUS_QUIT) || G.signe) s = bc_program_reset(p, s);
|
||||||
|
|
||||||
// If the stack has changed, pointers may be invalid.
|
// If the stack has changed, pointers may be invalid.
|
||||||
ip = bc_vec_top(&p->stack);
|
ip = bc_vec_top(&p->stack);
|
||||||
@ -6981,10 +6974,10 @@ static BcStatus bc_program_exec(BcProgram *p)
|
|||||||
static void bc_vm_sig(int sig)
|
static void bc_vm_sig(int sig)
|
||||||
{
|
{
|
||||||
int err = errno;
|
int err = errno;
|
||||||
size_t len = strlen(bcg.sig_msg);
|
size_t len = strlen(G.sig_msg);
|
||||||
if (sig == SIGINT && write(2, bcg.sig_msg, len) == (ssize_t) len) {
|
if (sig == SIGINT && write(2, G.sig_msg, len) == (ssize_t) len) {
|
||||||
bcg.signe = bcg.sig == bcg.sigc;
|
G.signe = G.sig == G.sigc;
|
||||||
bcg.sig += bcg.signe;
|
G.sig += G.signe;
|
||||||
}
|
}
|
||||||
errno = err;
|
errno = err;
|
||||||
}
|
}
|
||||||
@ -7007,14 +7000,14 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line)
|
|||||||
fprintf(stderr, " %s", file);
|
fprintf(stderr, " %s", file);
|
||||||
fprintf(stderr, bc_err_line + 4 * !line, line);
|
fprintf(stderr, bc_err_line + 4 * !line, line);
|
||||||
|
|
||||||
return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name));
|
return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_BC
|
#if ENABLE_BC
|
||||||
static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
|
static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
|
||||||
const char *msg)
|
const char *msg)
|
||||||
{
|
{
|
||||||
int p = (int) bcg.posix, w = (int) bcg.warn;
|
int p = (int) G_posix, w = (int) G_warn;
|
||||||
const char *const fmt = p ? bc_err_fmt : bc_warn_fmt;
|
const char *const fmt = p ? bc_err_fmt : bc_warn_fmt;
|
||||||
|
|
||||||
if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
|
if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
|
||||||
@ -7024,18 +7017,18 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
|
|||||||
fprintf(stderr, " %s", file);
|
fprintf(stderr, " %s", file);
|
||||||
fprintf(stderr, bc_err_line + 4 * !line, line);
|
fprintf(stderr, bc_err_line + 4 * !line, line);
|
||||||
|
|
||||||
return s * (!bcg.ttyin && !!p);
|
return s * (!G.ttyin && !!p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bc_vm_envArgs(BcVm *vm)
|
static void bc_vm_envArgs(void)
|
||||||
{
|
{
|
||||||
BcVec v;
|
BcVec v;
|
||||||
char *env_args = getenv(bc_args_env_name), *buf;
|
char *env_args = getenv(bc_args_env_name), *buf;
|
||||||
|
|
||||||
if (!env_args) return;
|
if (!env_args) return;
|
||||||
|
|
||||||
vm->env_args = xstrdup(env_args);
|
G.env_args = xstrdup(env_args);
|
||||||
buf = vm->env_args;
|
buf = G.env_args;
|
||||||
|
|
||||||
bc_vec_init(&v, sizeof(char *), NULL);
|
bc_vec_init(&v, sizeof(char *), NULL);
|
||||||
bc_vec_push(&v, &bc_args_env_name);
|
bc_vec_push(&v, &bc_args_env_name);
|
||||||
@ -7050,7 +7043,7 @@ static void bc_vm_envArgs(BcVm *vm)
|
|||||||
++buf;
|
++buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bc_args((int) v.len, (char **) v.v, &vm->flags, &vm->files);
|
bc_args((int) v.len, (char **) v.v, &G.flags, &G.files);
|
||||||
|
|
||||||
bc_vec_free(&v);
|
bc_vec_free(&v);
|
||||||
}
|
}
|
||||||
@ -7077,16 +7070,16 @@ static size_t bc_vm_envLen(const char *var)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BcStatus bc_vm_process(BcVm *vm, const char *text)
|
static BcStatus bc_vm_process(const char *text)
|
||||||
{
|
{
|
||||||
BcStatus s = bc_parse_text(&vm->prs, text);
|
BcStatus s = bc_parse_text(&G.prs, text);
|
||||||
|
|
||||||
s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line);
|
s = bc_vm_error(s, G.prs.l.f, G.prs.l.line);
|
||||||
if (s) return s;
|
if (s) return s;
|
||||||
|
|
||||||
while (vm->prs.l.t.t != BC_LEX_EOF) {
|
while (G.prs.l.t.t != BC_LEX_EOF) {
|
||||||
|
|
||||||
s = vm->prs.parse(&vm->prs);
|
s = G.prs.parse(&G.prs);
|
||||||
|
|
||||||
if (s == BC_STATUS_LIMITS) {
|
if (s == BC_STATUS_LIMITS) {
|
||||||
|
|
||||||
@ -7105,38 +7098,38 @@ static BcStatus bc_vm_process(BcVm *vm, const char *text)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (s == BC_STATUS_QUIT) return s;
|
if (s == BC_STATUS_QUIT) return s;
|
||||||
s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line);
|
s = bc_vm_error(s, G.prs.l.f, G.prs.l.line);
|
||||||
if (s) return s;
|
if (s) return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BC_PARSE_CAN_EXEC(&vm->prs)) {
|
if (BC_PARSE_CAN_EXEC(&G.prs)) {
|
||||||
s = bc_program_exec(&vm->prog);
|
s = bc_program_exec(&G.prog);
|
||||||
if (!s && bcg.tty) fflush(stdout);
|
if (!s && G.tty) fflush(stdout);
|
||||||
if (s && s != BC_STATUS_QUIT)
|
if (s && s != BC_STATUS_QUIT)
|
||||||
s = bc_vm_error(bc_program_reset(&vm->prog, s), vm->prs.l.f, 0);
|
s = bc_vm_error(bc_program_reset(&G.prog, s), G.prs.l.f, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BcStatus bc_vm_file(BcVm *vm, const char *file)
|
static BcStatus bc_vm_file(const char *file)
|
||||||
{
|
{
|
||||||
BcStatus s;
|
BcStatus s;
|
||||||
char *data;
|
char *data;
|
||||||
BcFunc *main_func;
|
BcFunc *main_func;
|
||||||
BcInstPtr *ip;
|
BcInstPtr *ip;
|
||||||
|
|
||||||
vm->prog.file = file;
|
G.prog.file = file;
|
||||||
s = bc_read_file(file, &data);
|
s = bc_read_file(file, &data);
|
||||||
if (s) return bc_vm_error(s, file, 0);
|
if (s) return bc_vm_error(s, file, 0);
|
||||||
|
|
||||||
bc_lex_file(&vm->prs.l, file);
|
bc_lex_file(&G.prs.l, file);
|
||||||
s = bc_vm_process(vm, data);
|
s = bc_vm_process(data);
|
||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
|
|
||||||
main_func = bc_vec_item(&vm->prog.fns, BC_PROG_MAIN);
|
main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN);
|
||||||
ip = bc_vec_item(&vm->prog.stack, 0);
|
ip = bc_vec_item(&G.prog.stack, 0);
|
||||||
|
|
||||||
if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE;
|
if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE;
|
||||||
|
|
||||||
@ -7145,7 +7138,7 @@ err:
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BcStatus bc_vm_stdin(BcVm *vm)
|
static BcStatus bc_vm_stdin(void)
|
||||||
{
|
{
|
||||||
BcStatus s = BC_STATUS_SUCCESS;
|
BcStatus s = BC_STATUS_SUCCESS;
|
||||||
BcVec buf, buffer;
|
BcVec buf, buffer;
|
||||||
@ -7153,8 +7146,8 @@ static BcStatus bc_vm_stdin(BcVm *vm)
|
|||||||
size_t len, i, str = 0;
|
size_t len, i, str = 0;
|
||||||
bool comment = false, notend;
|
bool comment = false, notend;
|
||||||
|
|
||||||
vm->prog.file = bc_program_stdin_name;
|
G.prog.file = bc_program_stdin_name;
|
||||||
bc_lex_file(&vm->prs.l, bc_program_stdin_name);
|
bc_lex_file(&G.prs.l, bc_program_stdin_name);
|
||||||
|
|
||||||
bc_vec_init(&buffer, sizeof(char), NULL);
|
bc_vec_init(&buffer, sizeof(char), NULL);
|
||||||
bc_vec_init(&buf, sizeof(char), NULL);
|
bc_vec_init(&buf, sizeof(char), NULL);
|
||||||
@ -7171,9 +7164,9 @@ static BcStatus bc_vm_stdin(BcVm *vm)
|
|||||||
len = buf.len - 1;
|
len = buf.len - 1;
|
||||||
|
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (str && buf.v[0] == vm->exe.send)
|
if (str && buf.v[0] == G.send)
|
||||||
str -= 1;
|
str -= 1;
|
||||||
else if (buf.v[0] == vm->exe.sbgn)
|
else if (buf.v[0] == G.sbgn)
|
||||||
str += 1;
|
str += 1;
|
||||||
}
|
}
|
||||||
else if (len > 1 || comment) {
|
else if (len > 1 || comment) {
|
||||||
@ -7184,11 +7177,11 @@ static BcStatus bc_vm_stdin(BcVm *vm)
|
|||||||
c = string[i];
|
c = string[i];
|
||||||
|
|
||||||
if (i - 1 > len || string[i - 1] != '\\') {
|
if (i - 1 > len || string[i - 1] != '\\') {
|
||||||
if (vm->exe.sbgn == vm->exe.send)
|
if (G.sbgn == G.send)
|
||||||
str ^= c == vm->exe.sbgn;
|
str ^= c == G.sbgn;
|
||||||
else if (c == vm->exe.send)
|
else if (c == G.send)
|
||||||
str -= 1;
|
str -= 1;
|
||||||
else if (c == vm->exe.sbgn)
|
else if (c == G.sbgn)
|
||||||
str += 1;
|
str += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7207,13 +7200,13 @@ static BcStatus bc_vm_stdin(BcVm *vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bc_vec_concat(&buffer, buf.v);
|
bc_vec_concat(&buffer, buf.v);
|
||||||
s = bc_vm_process(vm, buffer.v);
|
s = bc_vm_process(buffer.v);
|
||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
|
|
||||||
bc_vec_npop(&buffer, buffer.len);
|
bc_vec_npop(&buffer, buffer.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, vm->prs.l.f, 0);
|
if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, G.prs.l.f, 0);
|
||||||
|
|
||||||
// INPUT_EOF will always happen when stdin is
|
// INPUT_EOF will always happen when stdin is
|
||||||
// closed. It's not a problem in that case.
|
// closed. It's not a problem in that case.
|
||||||
@ -7221,11 +7214,11 @@ static BcStatus bc_vm_stdin(BcVm *vm)
|
|||||||
s = BC_STATUS_SUCCESS;
|
s = BC_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (str)
|
if (str)
|
||||||
s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, vm->prs.l.f,
|
s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f,
|
||||||
vm->prs.l.line);
|
G.prs.l.line);
|
||||||
else if (comment)
|
else if (comment)
|
||||||
s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, vm->prs.l.f,
|
s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, G.prs.l.f,
|
||||||
vm->prs.l.line);
|
G.prs.l.line);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
bc_vec_free(&buf);
|
bc_vec_free(&buf);
|
||||||
@ -7233,46 +7226,46 @@ err:
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BcStatus bc_vm_exec(BcVm *vm)
|
static BcStatus bc_vm_exec(void)
|
||||||
{
|
{
|
||||||
BcStatus s = BC_STATUS_SUCCESS;
|
BcStatus s = BC_STATUS_SUCCESS;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
#if ENABLE_BC
|
#if ENABLE_BC
|
||||||
if (vm->flags & BC_FLAG_L) {
|
if (G.flags & BC_FLAG_L) {
|
||||||
|
|
||||||
bc_lex_file(&vm->prs.l, bc_lib_name);
|
bc_lex_file(&G.prs.l, bc_lib_name);
|
||||||
s = bc_parse_text(&vm->prs, bc_lib);
|
s = bc_parse_text(&G.prs, bc_lib);
|
||||||
|
|
||||||
while (!s && vm->prs.l.t.t != BC_LEX_EOF) s = vm->prs.parse(&vm->prs);
|
while (!s && G.prs.l.t.t != BC_LEX_EOF) s = G.prs.parse(&G.prs);
|
||||||
|
|
||||||
if (s) return s;
|
if (s) return s;
|
||||||
s = bc_program_exec(&vm->prog);
|
s = bc_program_exec(&G.prog);
|
||||||
if (s) return s;
|
if (s) return s;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; !s && i < vm->files.len; ++i)
|
for (i = 0; !s && i < G.files.len; ++i)
|
||||||
s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i)));
|
s = bc_vm_file(*((char **) bc_vec_item(&G.files, i)));
|
||||||
if (s && s != BC_STATUS_QUIT) return s;
|
if (s && s != BC_STATUS_QUIT) return s;
|
||||||
|
|
||||||
if (IS_BC || !vm->files.len) s = bc_vm_stdin(vm);
|
if (IS_BC || !G.files.len) s = bc_vm_stdin();
|
||||||
if (!s && !BC_PARSE_CAN_EXEC(&vm->prs)) s = bc_vm_process(vm, "");
|
if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process("");
|
||||||
|
|
||||||
if (s == BC_STATUS_QUIT)
|
if (s == BC_STATUS_QUIT)
|
||||||
s = BC_STATUS_SUCCESS;
|
s = BC_STATUS_SUCCESS;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bc_vm_free(BcVm *vm)
|
static void bc_vm_free(void)
|
||||||
{
|
{
|
||||||
bc_vec_free(&vm->files);
|
bc_vec_free(&G.files);
|
||||||
bc_program_free(&vm->prog);
|
bc_program_free(&G.prog);
|
||||||
bc_parse_free(&vm->prs);
|
bc_parse_free(&G.prs);
|
||||||
free(vm->env_args);
|
free(G.env_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len)
|
static void bc_vm_init(const char *env_len)
|
||||||
{
|
{
|
||||||
size_t len = bc_vm_envLen(env_len);
|
size_t len = bc_vm_envLen(env_len);
|
||||||
#if ENABLE_FEATURE_BC_SIGNALS
|
#if ENABLE_FEATURE_BC_SIGNALS
|
||||||
@ -7284,47 +7277,32 @@ static void bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len)
|
|||||||
sigaction(SIGINT, &sa, NULL);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(vm, 0, sizeof(BcVm));
|
bc_vec_init(&G.files, sizeof(char *), NULL);
|
||||||
|
|
||||||
vm->exe = exe;
|
|
||||||
vm->flags = 0;
|
|
||||||
vm->env_args = NULL;
|
|
||||||
|
|
||||||
bc_vec_init(&vm->files, sizeof(char *), NULL);
|
|
||||||
|
|
||||||
#if ENABLE_BC
|
#if ENABLE_BC
|
||||||
vm->flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL);
|
G.flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL);
|
||||||
if (IS_BC) bc_vm_envArgs(vm);
|
if (IS_BC) bc_vm_envArgs();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bc_program_init(&vm->prog, len, exe.init, exe.exp);
|
bc_program_init(&G.prog, len, G.init, G.exp);
|
||||||
exe.init(&vm->prs, &vm->prog, BC_PROG_MAIN);
|
G.init(&G.prs, &G.prog, BC_PROG_MAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe,
|
static BcStatus bc_vm_run(int argc, char *argv[],
|
||||||
const char *env_len)
|
const char *env_len)
|
||||||
{
|
{
|
||||||
BcStatus st;
|
BcStatus st;
|
||||||
BcVm vm;
|
|
||||||
|
|
||||||
bc_vm_init(&vm, exe, env_len);
|
bc_vm_init(env_len);
|
||||||
bc_args(argc, argv, &vm.flags, &vm.files);
|
bc_args(argc, argv, &G.flags, &G.files);
|
||||||
|
|
||||||
bcg.ttyin = isatty(0);
|
G.ttyin = isatty(0);
|
||||||
bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1);
|
G.tty = G.ttyin || (G.flags & BC_FLAG_I) || isatty(1);
|
||||||
|
|
||||||
#if ENABLE_BC
|
if (G.ttyin && !(G.flags & BC_FLAG_Q)) bc_vm_info();
|
||||||
bcg.posix = vm.flags & BC_FLAG_S;
|
st = bc_vm_exec();
|
||||||
bcg.warn = vm.flags & BC_FLAG_W;
|
|
||||||
#endif
|
|
||||||
#if ENABLE_DC
|
|
||||||
bcg.exreg = vm.flags & BC_FLAG_X;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info();
|
bc_vm_free();
|
||||||
st = bc_vm_exec(&vm);
|
|
||||||
|
|
||||||
bc_vm_free(&vm);
|
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7332,17 +7310,15 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe,
|
|||||||
int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int bc_main(int argc, char **argv)
|
int bc_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
BcVmExe exec;
|
INIT_G();
|
||||||
|
|
||||||
# if ENABLE_FEATURE_BC_SIGNALS
|
# if ENABLE_FEATURE_BC_SIGNALS
|
||||||
bcg.sig_msg = "\ninterrupt (type \"quit\" to exit)\n";
|
G.sig_msg = "\ninterrupt (type \"quit\" to exit)\n";
|
||||||
# endif
|
# endif
|
||||||
|
G.init = bc_parse_init;
|
||||||
|
G.exp = bc_parse_expression;
|
||||||
|
G.sbgn = G.send = '"';
|
||||||
|
|
||||||
exec.init = bc_parse_init;
|
return bc_vm_run(argc, argv, "BC_LINE_LENGTH");
|
||||||
exec.exp = bc_parse_expression;
|
|
||||||
exec.sbgn = exec.send = '"';
|
|
||||||
|
|
||||||
return bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7350,17 +7326,15 @@ int bc_main(int argc, char **argv)
|
|||||||
int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int dc_main(int argc, char **argv)
|
int dc_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
BcVmExe exec;
|
INIT_G();
|
||||||
|
|
||||||
# if ENABLE_FEATURE_BC_SIGNALS
|
# if ENABLE_FEATURE_BC_SIGNALS
|
||||||
bcg.sig_msg = "\ninterrupt (type \"q\" to exit)\n";
|
G.sig_msg = "\ninterrupt (type \"q\" to exit)\n";
|
||||||
# endif
|
# endif
|
||||||
|
G.init = dc_parse_init;
|
||||||
|
G.exp = dc_parse_expr;
|
||||||
|
G.sbgn = '[';
|
||||||
|
G.send = ']';
|
||||||
|
|
||||||
exec.init = dc_parse_init;
|
return bc_vm_run(argc, argv, "DC_LINE_LENGTH");
|
||||||
exec.exp = dc_parse_expr;
|
|
||||||
exec.sbgn = '[';
|
|
||||||
exec.send = ']';
|
|
||||||
|
|
||||||
return bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user