aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
Diffstat (limited to 'toys')
-rw-r--r--toys/pending/bc.c199
1 files changed, 74 insertions, 125 deletions
diff --git a/toys/pending/bc.c b/toys/pending/bc.c
index 685bc976..614cae70 100644
--- a/toys/pending/bc.c
+++ b/toys/pending/bc.c
@@ -132,9 +132,7 @@ typedef void (*BcVecFree)(void*);
typedef struct BcVec {
char *v;
- size_t len;
- size_t cap;
- size_t size;
+ size_t len, cap, size;
BcVecFree dtor;
} BcVec;
@@ -151,8 +149,6 @@ typedef struct BcNum {
#define BC_NUM_DEF_SIZE (16)
-#define BC_NUM_KARATSUBA_LEN (32)
-
// A crude, but always big enough, calculation of
// the size required for ibase and obase BcNum's.
#define BC_NUM_LONG_LOG10 ((CHAR_BIT * sizeof(unsigned long) + 1) / 2 + 1)
@@ -162,8 +158,6 @@ typedef struct BcNum {
#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
#define BC_NUM_INT(n) ((n)->len - (n)->rdx)
#define BC_NUM_CMP_ZERO(a) (BC_NUM_NEG((a)->len != 0, (a)->neg))
-#define BC_NUM_PREQ(a, b) ((a)->len + (b)->len + 1)
-#define BC_NUM_SHREQ(a) ((a)->len)
typedef BcStatus (*BcNumBinaryOp)(BcNum*, BcNum*, BcNum*, size_t);
typedef size_t (*BcNumBinaryOpReq)(BcNum*, BcNum*, size_t);
@@ -868,11 +862,11 @@ char bc_lib[] = {
61,45,97,10,114,101,116,117,114,110,40,97,42,114,47,49,41,10,125,10,0
};
-static void bc_vec_grow(BcVec *v, size_t n) {
- size_t cap = v->cap * 2;
- while (cap < v->len + n) cap *= 2;
- v->v = xrealloc(v->v, v->size * cap);
- v->cap = cap;
+static void bc_vec_grow(BcVec *v, unsigned long n) {
+ unsigned long old = v->cap;
+
+ while (v->cap < v->len + n) v->cap *= 2;
+ if (old != v->cap) v->v = xrealloc(v->v, v->size * v->cap);
}
void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor) {
@@ -899,7 +893,7 @@ void bc_vec_npop(BcVec *v, size_t n) {
}
void bc_vec_npush(BcVec *v, size_t n, void *data) {
- if (v->len + n > v->cap) bc_vec_grow(v, n);
+ bc_vec_grow(v, n);
memcpy(v->v + (v->size * v->len), data, v->size * n);
v->len += n;
}
@@ -933,7 +927,7 @@ static void bc_vec_pushAt(BcVec *v, void *data, size_t idx) {
char *ptr;
- if (v->len == v->cap) bc_vec_grow(v, 1);
+ bc_vec_grow(v, 1);
ptr = v->v + v->size * idx;
@@ -953,17 +947,14 @@ void bc_vec_string(BcVec *v, size_t len, char *str) {
}
void bc_vec_concat(BcVec *v, char *str) {
-
- size_t len;
+ unsigned long len;
if (!v->len) bc_vec_pushByte(v, '\0');
- len = v->len + strlen(str);
-
- if (v->cap < len) bc_vec_grow(v, len - v->len);
- strcat(v->v, str);
-
- v->len = len;
+ len = strlen(str);
+ bc_vec_grow(v, len+1);
+ strcpy(v->v+v->len, str);
+ v->len += len;
}
void bc_vec_empty(BcVec *v) {
@@ -1198,8 +1189,7 @@ ssize_t bc_num_cmp(BcNum *a, BcNum *b) {
if (a->neg) {
if (b->neg) neg = 1;
else return -1;
- }
- else if (b->neg) return 1;
+ } else if (b->neg) return 1;
a_int = BC_NUM_INT(a);
b_int = BC_NUM_INT(b);
@@ -1478,8 +1468,8 @@ static BcStatus bc_num_k(BcNum *a, BcNum *b, BcNum *c) {
return BC_STATUS_SUCCESS;
}
- if (a->len + b->len < BC_NUM_KARATSUBA_LEN ||
- a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN)
+ // check karatsuba length
+ if (a->len + b->len < 32 || a->len < 32 || b->len < 32)
{
size_t i, j, len;
unsigned int carry;
@@ -1841,41 +1831,6 @@ static unsigned long bc_num_parseChar(char c, size_t base_t) {
return c;
}
-static void bc_num_parseDecimal(BcNum *n, char *val) {
-
- size_t len, i;
- char *ptr;
- int zero = 1;
-
- for (i = 0; val[i] == '0'; ++i);
-
- val += i;
- len = strlen(val);
-
- if (len) {
- for (i = 0; zero && i < len; ++i) zero = (val[i] == '0') || val[i] == '.';
- bc_num_expand(n, len);
- }
-
- ptr = strchr(val, '.');
-
- // Explicitly test for NULL here to produce either a 0 or 1.
- n->rdx = (size_t) ((ptr != NULL) * ((val + len) - (ptr + 1)));
-
- if (!zero) {
- for (i = len - 1; i < len; ++n->len, --i) {
-
- char c = val[i];
-
- if (c == '.') n->len -= 1;
- else {
- if (isupper(c)) c = '9';
- n->num[n->len] = c - '0';
- }
- }
- }
-}
-
static BcStatus bc_num_parseBase(BcNum *n, char *val,
BcNum *base, size_t base_t)
{
@@ -2130,27 +2085,34 @@ BcStatus bc_num_parse(BcNum *n, char *val,
BcStatus s = BC_STATUS_SUCCESS;
if (letter) bc_num_ulong2num(n, bc_num_parseChar(val[0], 'Z'+11));
- else if (base_t == 10) bc_num_parseDecimal(n, val);
- else s = bc_num_parseBase(n, val, base, base_t);
+ else if (base_t == 10) {
+ size_t len, i;
+ char *ptr;
+ int zero = 1;
- return s;
-}
+ while (*val == '0') val++;
-BcStatus bc_num_print(BcNum *n, BcNum *base,
- size_t base_t, int newline)
-{
- BcStatus s = BC_STATUS_SUCCESS;
+ len = strlen(val);
+ if (len) {
+ for (i = 0; zero && i < len; ++i) zero = (val[i] == '0') || val[i] == '.';
+ bc_num_expand(n, len);
+ }
+ ptr = strchr(val, '.');
+ n->rdx = ptr ? (val + len) - (ptr + 1) : 0;
- bc_num_printNewline();
+ if (!zero) {
+ for (i = len - 1; i < len; ++n->len, --i) {
- if (!n->len) bc_num_printHex(0, 1, 0);
- else if (base_t == 10) bc_num_printDecimal(n);
- else s = bc_num_printBase(n, base, base_t);
+ char c = val[i];
- if (!s && newline) {
- putchar('\n');
- TT.nchars = 0;
- }
+ if (c == '.') n->len -= 1;
+ else {
+ if (isupper(c)) c = '9';
+ n->num[n->len] = c - '0';
+ }
+ }
+ }
+ } else s = bc_num_parseBase(n, val, base, base_t);
return s;
}
@@ -2204,7 +2166,7 @@ size_t bc_num_mulReq(BcNum *a, BcNum *b, size_t scale) {
}
size_t bc_num_powReq(BcNum *a, BcNum *b, size_t scale) {
- return BC_NUM_PREQ(a, b);
+ return a->len + b->len + 1;
}
BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
@@ -2230,7 +2192,7 @@ BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
}
BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
- return bc_num_binary(a, b, c, scale, bc_num_p, BC_NUM_PREQ(a, b));
+ return bc_num_binary(a, b, c, scale, bc_num_p, a->len + b->len + 1);
}
BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale) {
@@ -2609,10 +2571,6 @@ void bc_lex_init(BcLex *l) {
bc_vec_init(&l->str, sizeof(char), NULL);
}
-void bc_lex_free(BcLex *l) {
- bc_vec_free(&l->str);
-}
-
void bc_lex_file(BcLex *l, char *file) {
l->line = 1;
TT.file = file;
@@ -3066,7 +3024,7 @@ void bc_parse_free(BcParse *p) {
bc_vec_free(&p->exits);
bc_vec_free(&p->conds);
bc_vec_free(&p->ops);
- bc_lex_free(&p->l);
+ bc_vec_free(&p->l.str);
}
void bc_parse_init(BcParse *p, BcProgram *prog, size_t func)
@@ -4858,10 +4816,18 @@ static BcStatus bc_program_print(BcProgram *p, uchar inst, size_t idx) {
if (s) return s;
if (BC_PROG_NUM(r, n)) {
- s = bc_num_print(n, &p->ob, p->ob_t, !pop);
+ bc_num_printNewline();
+
+ if (!n->len) bc_num_printHex(0, 1, 0);
+ else if (p->ob_t == 10) bc_num_printDecimal(n);
+ else s = bc_num_printBase(n, &p->ob, p->ob_t);
+
+ if (!s && !pop) {
+ putchar('\n');
+ TT.nchars = 0;
+ }
if (!s) bc_num_copy(&p->last, n);
- }
- else {
+ } else {
size_t i = (r->t == BC_RESULT_STR) ? r->d.id.len : n->rdx;
@@ -5008,11 +4974,8 @@ static BcStatus bc_program_copyToVar(BcProgram *p, char *name,
if (var) bc_num_createCopy(&r.d.n, n);
else {
-
- BcVec *v = (BcVec*) n, *rv = &r.d.v;
-
- bc_array_init(rv, 1);
- bc_array_copy(rv, v);
+ bc_array_init(&r.d.v, 1);
+ bc_array_copy(&r.d.v, (BcVec *)n);
}
bc_vec_push(vec, &r.d);
@@ -5757,8 +5720,8 @@ static BcStatus bc_vm_stdin(void) {
bc_vec_pushByte(&buffer, '\0');
// This loop is complex because the vm tries not to send any lines that end
- // 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
+ // with a backslash to the parser, which
+ // 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.
while (!done && (s = bc_read_line(&buf, ">>> ")) != BC_STATUS_ERROR &&
buf.len > 1 && !TT.sig && s != BC_STATUS_SIGNAL)
@@ -5821,37 +5784,9 @@ err:
return s;
}
-static BcStatus bc_vm_load(char *name, char *text) {
-
- BcStatus s;
-
- bc_lex_file(&BC_VM->prs.l, name);
- s = bc_parse_text(&BC_VM->prs, text);
-
- while (!s && BC_VM->prs.l.t != BC_LEX_EOF) s = bc_parse_parse(&BC_VM->prs);
-
- return s;
-}
-
-static BcStatus bc_vm_exec(void) {
-
- BcStatus s = BC_STATUS_SUCCESS;
- size_t i;
-
- if (toys.optflags & FLAG_l) {
- s = bc_vm_load(bc_lib_name, bc_lib);
- if (s) return s;
- }
-
- for (i = 0; !s && i < toys.optc; ++i) s = bc_vm_file(toys.optargs[i]);
- if (s && s != BC_STATUS_QUIT) return s;
-
- return bc_vm_stdin();
-}
-
void bc_main(void)
{
- BcStatus s;
+ BcStatus s = 0;
char *ss;
struct sigaction sa;
@@ -5882,7 +5817,21 @@ void bc_main(void)
if (FLAG(i) && !(toys.optflags & FLAG_q)) bc_vm_info();
- s = bc_vm_exec();
+ // load -l library (if any)
+ if (FLAG(l)) {
+ bc_lex_file(&BC_VM->prs.l, bc_lib_name);
+ s = bc_parse_text(&BC_VM->prs, bc_lib);
+
+ while (!s && BC_VM->prs.l.t != BC_LEX_EOF) s = bc_parse_parse(&BC_VM->prs);
+ }
+
+ // parse command line argument files, then stdin
+ if (!s) {
+ int i;
+
+ for (i = 0; !s && i < toys.optc; ++i) s = bc_vm_file(toys.optargs[i]);
+ if (!s || s != BC_STATUS_QUIT) s = bc_vm_stdin();
+ }
if (CFG_TOYBOX_FREE) {
bc_program_free(&BC_VM->prog);
@@ -5890,5 +5839,5 @@ void bc_main(void)
free(TT.vm);
}
- toys.exitval = (int) (s != BC_STATUS_ERROR ? BC_STATUS_SUCCESS : s);
+ toys.exitval = s == BC_STATUS_ERROR;
}