2 * $OpenBSD: bcode.c,v 1.22 2004/02/11 20:44:31 otto Exp $
3 * $DragonFly: src/usr.bin/dc/bcode.c,v 1.1 2004/09/20 04:20:39 dillon Exp $
7 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <openssl/ssl.h>
34 /* #define DEBUGGING */
36 #define MAX_ARRAY_INDEX 2048
37 #define RECURSION_STACK_SIZE 100
39 #define NO_ELSE -2 /* -1 is EOF */
40 #define REG_ARRAY_SIZE_SMALL (UCHAR_MAX + 1)
41 #define REG_ARRAY_SIZE_BIG (UCHAR_MAX + 1 + USHRT_MAX + 1)
50 size_t reg_array_size;
52 volatile bool interrupted;
53 struct source readstack[RECURSION_STACK_SIZE];
56 static struct bmachine bmachine;
57 static void sighandler(int);
59 static __inline int readch(void);
60 static __inline int unreadch(void);
61 static __inline char *readline(void);
62 static __inline void src_free(void);
64 static __inline u_int max(u_int, u_int);
65 static u_long get_ulong(struct number *);
67 static __inline void push_number(struct number *);
68 static __inline void push_string(char *);
69 static __inline void push(struct value *);
70 static __inline struct value *tos(void);
71 static __inline struct number *pop_number(void);
72 static __inline char *pop_string(void);
73 static __inline void clear_stack(void);
74 static __inline void print_tos(void);
75 static void pop_print(void);
76 static void pop_printn(void);
77 static __inline void print_stack(void);
78 static __inline void dup(void);
79 static void swap(void);
80 static void drop(void);
82 static void get_scale(void);
83 static void set_scale(void);
84 static void get_obase(void);
85 static void set_obase(void);
86 static void get_ibase(void);
87 static void set_ibase(void);
88 static void stackdepth(void);
89 static void push_scale(void);
90 static u_int count_digits(const struct number *);
91 static void num_digits(void);
92 static void to_ascii(void);
93 static void push_line(void);
94 static void comment(void);
95 static void bexec(char *);
96 static void badd(void);
97 static void bsub(void);
98 static void bmul(void);
99 static void bdiv(void);
100 static void bmod(void);
101 static void bdivmod(void);
102 static void bexp(void);
103 static bool bsqrt_stop(const BIGNUM *, const BIGNUM *);
104 static void bsqrt(void);
105 static void not(void);
106 static void equal_numbers(void);
107 static void less_numbers(void);
108 static void lesseq_numbers(void);
109 static void equal(void);
110 static void not_equal(void);
111 static void less(void);
112 static void not_less(void);
113 static void greater(void);
114 static void not_greater(void);
115 static void not_compare(void);
116 static bool compare_numbers(enum bcode_compare, struct number *,
118 static void compare(enum bcode_compare);
119 static int readreg(void);
120 static void load(void);
121 static void store(void);
122 static void load_stack(void);
123 static void store_stack(void);
124 static void load_array(void);
125 static void store_array(void);
126 static void nop(void);
127 static void quit(void);
128 static void quitN(void);
129 static void skipN(void);
130 static void skip_until_mark(void);
131 static void parse_number(void);
132 static void unknown(void);
133 static void eval_string(char *);
134 static void eval_line(void);
135 static void eval_tos(void);
138 typedef void (*opcode_function)(void);
145 static opcode_function jump_table[UCHAR_MAX];
147 static const struct jump_entry jump_table_data[] = {
149 { '!', not_compare },
152 { '(', less_numbers },
156 { '.', parse_number },
158 { '0', parse_number },
159 { '1', parse_number },
160 { '2', parse_number },
161 { '3', parse_number },
162 { '4', parse_number },
163 { '5', parse_number },
164 { '6', parse_number },
165 { '7', parse_number },
166 { '8', parse_number },
167 { '9', parse_number },
168 { ':', store_array },
174 { 'A', parse_number },
175 { 'B', parse_number },
176 { 'C', parse_number },
177 { 'D', parse_number },
178 { 'E', parse_number },
179 { 'F', parse_number },
180 { 'G', equal_numbers },
191 { 'S', store_stack },
200 { '_', parse_number },
202 { 'c', clear_stack },
204 { 'f', print_stack },
217 { '{', lesseq_numbers },
221 #define JUMP_TABLE_DATA_SIZE \
222 (sizeof(jump_table_data)/sizeof(jump_table_data[0]))
225 sighandler(int ignored)
227 bmachine.interrupted = true;
231 init_bmachine(bool extended_registers)
235 bmachine.extended_regs = extended_registers;
236 bmachine.reg_array_size = bmachine.extended_regs ?
237 REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL;
239 bmachine.reg = malloc(bmachine.reg_array_size *
240 sizeof(bmachine.reg[0]));
241 if (bmachine.reg == NULL)
244 for (i = 0; i < UCHAR_MAX; i++)
245 jump_table[i] = unknown;
246 for (i = 0; i < JUMP_TABLE_DATA_SIZE; i++)
247 jump_table[jump_table_data[i].ch] = jump_table_data[i].f;
249 stack_init(&bmachine.stack);
251 for (i = 0; i < bmachine.reg_array_size; i++)
252 stack_init(&bmachine.reg[i]);
254 bmachine.obase = bmachine.ibase = 10;
256 bn_check(BN_zero(&zero));
257 signal(SIGINT, sighandler);
260 /* Reset the things needed before processing a (new) file */
262 reset_bmachine(struct source *src)
265 bmachine.readstack[0] = *src;
271 struct source *src = &bmachine.readstack[bmachine.readsp];
273 return src->vtable->readchar(src);
279 struct source *src = &bmachine.readstack[bmachine.readsp];
281 return src->vtable->unreadchar(src);
284 static __inline char *
287 struct source *src = &bmachine.readstack[bmachine.readsp];
289 return src->vtable->readline(src);
295 struct source *src = &bmachine.readstack[bmachine.readsp];
297 src->vtable->free(src);
302 pn(const char * str, const struct number *n)
304 char *p = BN_bn2dec(n->number);
306 err(1, "BN_bn2dec failed");
308 fprintf(stderr, " %s (%u)\n" , p, n->scale);
313 pbn(const char * str, const BIGNUM *n)
315 char *p = BN_bn2dec(n);
317 err(1, "BN_bn2dec failed");
319 fprintf(stderr, " %s\n", p);
325 static __inline u_int
326 max(u_int a, u_int b)
328 return a > b ? a : b;
331 static unsigned long factors[] = {
332 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
333 100000000, 1000000000
337 scale_number(BIGNUM *n, int s)
344 abs_scale = s > 0 ? s : -s;
346 if (abs_scale < sizeof(factors)/sizeof(factors[0])) {
348 bn_check(BN_mul_word(n, factors[abs_scale]));
350 BN_div_word(n, factors[abs_scale]);
362 bn_check(BN_set_word(a, 10));
363 bn_check(BN_set_word(p, abs_scale));
364 bn_check(BN_exp(a, a, p, ctx));
366 bn_check(BN_mul(n, n, a, ctx));
368 bn_check(BN_div(n, NULL, n, a, ctx));
376 split_number(const struct number *n, BIGNUM *i, BIGNUM *f)
380 bn_checkp(BN_copy(i, n->number));
382 if (n->scale == 0 && f != NULL)
384 else if (n->scale < sizeof(factors)/sizeof(factors[0])) {
385 rem = BN_div_word(i, factors[n->scale]);
399 bn_check(BN_set_word(a, 10));
400 bn_check(BN_set_word(p, n->scale));
401 bn_check(BN_exp(a, a, p, ctx));
402 bn_check(BN_div(i, f, n->number, a, ctx));
410 normalize(struct number *n, u_int s)
412 scale_number(n->number, s - n->scale);
417 get_ulong(struct number *n)
420 return BN_get_word(n->number);
424 negate(struct number *n)
426 bn_check(BN_sub(n->number, &zero, n->number));
430 push_number(struct number *n)
432 stack_pushnumber(&bmachine.stack, n);
436 push_string(char *string)
438 stack_pushstring(&bmachine.stack, string);
442 push(struct value *v)
444 stack_push(&bmachine.stack, v);
447 static __inline struct value *
450 return stack_tos(&bmachine.stack);
453 static __inline struct value *
456 return stack_pop(&bmachine.stack);
459 static __inline struct number *
462 return stack_popnumber(&bmachine.stack);
465 static __inline char *
468 return stack_popstring(&bmachine.stack);
474 stack_clear(&bmachine.stack);
480 stack_print(stdout, &bmachine.stack, "", bmachine.obase);
486 struct value *value = tos();
488 print_value(stdout, value, "", bmachine.obase);
492 warnx("stack empty");
498 struct value *value = pop();
501 switch (value->type) {
505 normalize(value->u.num, 0);
506 print_ascii(stdout, value->u.num);
510 fputs(value->u.string, stdout);
514 stack_free_value(value);
521 struct value *value = pop();
524 print_value(stdout, value, "", bmachine.obase);
526 stack_free_value(value);
533 stack_dup(&bmachine.stack);
539 stack_swap(&bmachine.stack);
545 struct value *v = pop();
556 bn_check(BN_set_word(n->number, bmachine.scale));
568 if (BN_cmp(n->number, &zero) < 0)
569 warnx("scale must be a nonnegative number");
571 scale = get_ulong(n);
572 if (scale != BN_MASK2)
573 bmachine.scale = scale;
575 warnx("scale too large");
587 bn_check(BN_set_word(n->number, bmachine.obase));
600 if (base != BN_MASK2 && base > 1)
601 bmachine.obase = base;
603 warnx("output base must be a number greater than 1");
614 bn_check(BN_set_word(n->number, bmachine.ibase));
627 if (base != BN_MASK2 && 2 <= base && base <= 16)
628 bmachine.ibase = base;
630 warnx("input base must be a number between 2 and 16 "
642 i = stack_size(&bmachine.stack);
644 bn_check(BN_set_word(n->number, i));
658 switch (value->type) {
662 scale = value->u.num->scale;
667 stack_free_value(value);
669 bn_check(BN_set_word(n->number, scale));
675 count_digits(const struct number *n)
677 struct number *int_part, *fract_part;
680 if (BN_is_zero(n->number))
683 int_part = new_number();
684 fract_part = new_number();
685 fract_part->scale = n->scale;
686 split_number(n, int_part->number, fract_part->number);
689 while (!BN_is_zero(int_part->number)) {
690 BN_div_word(int_part->number, 10);
693 free_number(int_part);
694 free_number(fract_part);
703 struct number *n = NULL;
707 switch (value->type) {
711 digits = count_digits(value->u.num);
713 bn_check(BN_set_word(n->number, digits));
716 digits = strlen(value->u.string);
718 bn_check(BN_set_word(n->number, digits));
721 stack_free_value(value);
736 switch (value->type) {
742 if (BN_num_bits(n->number) > 8)
743 bn_check(BN_mask_bits(n->number, 8));
744 str[0] = BN_get_word(n->number);
747 str[0] = value->u.string[0];
750 stack_free_value(value);
751 push_string(bstrdup(str));
761 if (index == 0xff && bmachine.extended_regs) {
764 if (ch1 == EOF || ch2 == EOF) {
765 warnx("unexpected eof");
768 index = (ch1 << 8) + ch2 + UCHAR_MAX + 1;
770 if (index < 0 || index >= bmachine.reg_array_size) {
771 warnx("internal error: reg num = %d", index);
781 struct value *v, copy;
786 v = stack_tos(&bmachine.reg[index]);
789 bn_check(BN_zero(n->number));
792 push(stack_dup_value(v, ©));
808 stack_set_tos(&bmachine.reg[index], val);
817 struct value *value, copy;
821 stack = &bmachine.reg[index];
823 if (stack_size(stack) > 0) {
824 value = stack_pop(stack);
827 push(stack_dup_value(value, ©));
829 warnx("stack register '%c' (0%o) is empty",
845 stack_push(&bmachine.reg[index], value);
853 struct number *inumber, *n;
856 struct value *v, copy;
860 inumber = pop_number();
863 index = get_ulong(inumber);
864 if (BN_cmp(inumber->number, &zero) < 0)
865 warnx("negative index");
866 else if (index == BN_MASK2 || index > MAX_ARRAY_INDEX)
867 warnx("index too big");
869 stack = &bmachine.reg[reg];
870 v = frame_retrieve(stack, index);
873 bn_check(BN_zero(n->number));
877 push(stack_dup_value(v, ©));
879 free_number(inumber);
887 struct number *inumber;
894 inumber = pop_number();
899 free_number(inumber);
902 index = get_ulong(inumber);
903 if (BN_cmp(inumber->number, &zero) < 0) {
904 warnx("negative index");
905 stack_free_value(value);
906 } else if (index == BN_MASK2 || index > MAX_ARRAY_INDEX) {
907 warnx("index too big");
908 stack_free_value(value);
910 stack = &bmachine.reg[reg];
911 frame_assign(stack, index, value);
913 free_number(inumber);
920 push_string(read_string(&bmachine.readstack[bmachine.readsp]));
939 struct number *a, *b;
953 r->scale = max(a->scale, b->scale);
954 if (r->scale > a->scale)
955 normalize(a, r->scale);
956 else if (r->scale > b->scale)
957 normalize(b, r->scale);
958 bn_check(BN_add(r->number, a->number, b->number));
967 struct number *a, *b;
982 r->scale = max(a->scale, b->scale);
983 if (r->scale > a->scale)
984 normalize(a, r->scale);
985 else if (r->scale > b->scale)
986 normalize(b, r->scale);
987 bn_check(BN_sub(r->number, b->number, a->number));
994 bmul_number(struct number *r, struct number *a, struct number *b)
998 /* Create copies of the scales, since r might be equal to a or b */
999 u_int ascale = a->scale;
1000 u_int bscale = b->scale;
1001 u_int rscale = ascale + bscale;
1005 bn_check(BN_mul(r->number, a->number, b->number, ctx));
1008 if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) {
1010 normalize(r, max(bmachine.scale, max(ascale, bscale)));
1018 struct number *a, *b;
1032 bmul_number(r, a, b);
1042 struct number *a, *b;
1058 r->scale = bmachine.scale;
1059 scale = max(a->scale, b->scale);
1061 if (BN_is_zero(a->number))
1062 warnx("divide by zero");
1064 normalize(a, scale);
1065 normalize(b, scale + r->scale);
1069 bn_check(BN_div(r->number, NULL, b->number, a->number, ctx));
1080 struct number *a, *b;
1096 scale = max(a->scale, b->scale);
1097 r->scale = max(b->scale, a->scale + bmachine.scale);
1099 if (BN_is_zero(a->number))
1100 warnx("remainder by zero");
1102 normalize(a, scale);
1103 normalize(b, scale + bmachine.scale);
1107 bn_check(BN_mod(r->number, b->number, a->number, ctx));
1118 struct number *a, *b;
1119 struct number *rdiv, *rmod;
1133 rdiv = new_number();
1134 rmod = new_number();
1135 rdiv->scale = bmachine.scale;
1136 rmod->scale = max(b->scale, a->scale + bmachine.scale);
1137 scale = max(a->scale, b->scale);
1139 if (BN_is_zero(a->number))
1140 warnx("divide by zero");
1142 normalize(a, scale);
1143 normalize(b, scale + bmachine.scale);
1147 bn_check(BN_div(rdiv->number, rmod->number,
1148 b->number, a->number, ctx));
1160 struct number *a, *p;
1176 warnx("Runtime warning: non-zero scale in exponent");
1180 if (BN_cmp(p->number, &zero) < 0) {
1183 scale = bmachine.scale;
1185 /* Posix bc says min(a.scale * b, max(a.scale, scale) */
1189 b = BN_get_word(p->number);
1190 m = max(a->scale, bmachine.scale);
1191 scale = a->scale * b;
1192 if (scale > m || b == BN_MASK2)
1196 if (BN_is_zero(p->number)) {
1198 bn_check(BN_one(r->number));
1199 normalize(r, scale);
1201 while (!BN_is_bit_set(p->number, 0)) {
1202 bmul_number(a, a, a);
1203 bn_check(BN_rshift1(p->number, p->number));
1207 normalize(r, scale);
1208 bn_check(BN_rshift1(p->number, p->number));
1210 while (!BN_is_zero(p->number)) {
1211 bmul_number(a, a, a);
1212 if (BN_is_bit_set(p->number, 0))
1213 bmul_number(r, r, a);
1214 bn_check(BN_rshift1(p->number, p->number));
1227 scale_number(one, r->scale);
1228 bn_check(BN_div(r->number, NULL, one, r->number, ctx));
1239 bsqrt_stop(const BIGNUM *x, const BIGNUM *y)
1246 bn_check(BN_sub(r, x, y));
1247 ret = BN_is_one(r) || BN_is_zero(r);
1265 if (BN_is_zero(n->number)) {
1268 } else if (BN_cmp(n->number, &zero) < 0)
1269 warnx("square root of negative number");
1271 scale = max(bmachine.scale, n->scale);
1272 normalize(n, 2*scale);
1273 x = BN_dup(n->number);
1275 bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
1281 bn_checkp(BN_copy(y, x));
1282 bn_check(BN_div(x, NULL, n->number, x, ctx));
1283 bn_check(BN_add(x, x, y));
1284 bn_check(BN_rshift1(x, x));
1285 if (bsqrt_stop(x, y))
1288 r = bmalloc(sizeof(*r));
1309 bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1));
1316 compare(BCODE_EQUAL);
1322 struct number *a, *b, *r;
1334 bn_check(BN_set_word(r->number,
1335 compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0));
1342 struct number *a, *b, *r;
1354 bn_check(BN_set_word(r->number,
1355 compare_numbers(BCODE_LESS, a, b) ? 1 : 0));
1360 lesseq_numbers(void)
1362 struct number *a, *b, *r;
1374 bn_check(BN_set_word(r->number,
1375 compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
1382 compare(BCODE_NOT_EQUAL);
1388 compare(BCODE_LESS);
1414 compare(BCODE_NOT_LESS);
1420 compare(BCODE_GREATER);
1426 compare(BCODE_NOT_GREATER);
1430 compare_numbers(enum bcode_compare type, struct number *a, struct number *b)
1435 scale = max(a->scale, b->scale);
1437 if (scale > a->scale)
1438 normalize(a, scale);
1439 else if (scale > scale)
1440 normalize(b, scale);
1442 cmp = BN_cmp(a->number, b->number);
1450 case BCODE_NOT_EQUAL:
1454 case BCODE_NOT_LESS:
1458 case BCODE_NOT_GREATER:
1465 compare(enum bcode_compare type)
1467 int index, elseindex;
1468 struct number *a, *b;
1472 elseindex = NO_ELSE;
1474 if (readch() == 'e')
1475 elseindex = readreg();
1488 ok = compare_numbers(type, a, b);
1490 if (!ok && elseindex != NO_ELSE)
1493 if (index >= 0 && (ok || (!ok && elseindex != NO_ELSE))) {
1494 v = stack_tos(&bmachine.reg[index]);
1496 warnx("register '%c' (0%o) is empty", index, index);
1500 warnx("register '%c' (0%o) is empty",
1504 warn("eval called with non-string argument");
1507 eval_string(bstrdup(v->u.string));
1523 if (bmachine.readsp < 2)
1541 if (i == BN_MASK2 || i == 0)
1542 warnx("Q command requires a number >= 1");
1543 else if (bmachine.readsp < i)
1544 warnx("Q command argument exceeded string execution depth");
1564 warnx("J command requires a number >= 0");
1565 else if (i > 0 && bmachine.readsp < i)
1566 warnx("J command argument exceeded string execution depth");
1577 skip_until_mark(void)
1587 errx(1, "mark not found");
1599 if (readch() == 'e')
1605 free(read_string(&bmachine.readstack[bmachine.readsp]));
1608 switch (ch = readch()) {
1613 if (readch() == 'e')
1633 push_number(readnumber(&bmachine.readstack[bmachine.readsp],
1640 int ch = bmachine.readstack[bmachine.readsp].lastchar;
1641 warnx("%c (0%o) is unimplemented", ch, ch);
1645 eval_string(char *p)
1649 if (bmachine.readsp > 0) {
1650 /* Check for tail call. Do not recurse in that case. */
1654 src_setstring(&bmachine.readstack[bmachine.readsp], p);
1659 if (bmachine.readsp == RECURSION_STACK_SIZE-1)
1660 errx(1, "recursion too deep");
1661 src_setstring(&bmachine.readstack[++bmachine.readsp], p);
1667 /* Always read from stdin */
1671 src_setstream(&in, stdin);
1672 p = (*in.vtable->readline)(&in);
1695 if (bmachine.readsp == 0)
1701 if (bmachine.interrupted) {
1702 if (bmachine.readsp > 0) {
1707 bmachine.interrupted = false;
1710 fprintf(stderr, "# %c\n", ch);
1711 stack_print(stderr, &bmachine.stack, "* ",
1713 fprintf(stderr, "%d =>\n", bmachine.readsp);
1716 if (0 <= ch && ch < UCHAR_MAX)
1717 (*jump_table[ch])();
1719 warnx("internal error: opcode %d", ch);
1722 stack_print(stderr, &bmachine.stack, "* ",
1724 fprintf(stderr, "%d ==\n", bmachine.readsp);