bcode.c revision 1.2 1 /* $NetBSD: bcode.c,v 1.2 2017/04/10 16:37:48 christos Exp $ */
2 /* $OpenBSD: bcode.c,v 1.51 2017/02/26 11:29:55 otto Exp $ */
3
4 /*
5 * Copyright (c) 2003, Otto Moerbeek <otto (at) drijf.net>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include <sys/cdefs.h>
20 __RCSID("$NetBSD: bcode.c,v 1.2 2017/04/10 16:37:48 christos Exp $");
21
22 #include <err.h>
23 #include <limits.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "extern.h"
30
31 /* #define DEBUGGING */
32
33 #define MAX_ARRAY_INDEX 2048
34 #define READSTACK_SIZE 8
35
36 #define NO_ELSE -2 /* -1 is EOF */
37 #define REG_ARRAY_SIZE_SMALL (UCHAR_MAX + 1)
38 #define REG_ARRAY_SIZE_BIG (UCHAR_MAX + 1 + USHRT_MAX + 1)
39
40 struct bmachine {
41 struct stack stack;
42 u_int scale;
43 u_int obase;
44 u_int ibase;
45 size_t readsp;
46 bool extended_regs;
47 size_t reg_array_size;
48 struct stack *reg;
49 volatile sig_atomic_t interrupted;
50 struct source *readstack;
51 size_t readstack_sz;
52 };
53
54 static struct bmachine bmachine;
55 static void sighandler(int);
56
57 static __inline int readch(void);
58 static __inline void unreadch(void);
59 static __inline char *readline(void);
60 static __inline void src_free(void);
61
62 static __inline u_int max(u_int, u_int);
63 static u_long get_ulong(struct number *);
64
65 static __inline void push_number(struct number *);
66 static __inline void push_string(char *);
67 static __inline void push(struct value *);
68 static __inline struct value *tos(void);
69 static __inline struct number *pop_number(void);
70 static __inline char *pop_string(void);
71 static __inline void clear_stack(void);
72 static __inline void print_tos(void);
73 static void print_err(void);
74 static void pop_print(void);
75 static void pop_printn(void);
76 static __inline void print_stack(void);
77 static __inline void dup(void);
78 static void swap(void);
79 static void drop(void);
80
81 static void get_scale(void);
82 static void set_scale(void);
83 static void get_obase(void);
84 static void set_obase(void);
85 static void get_ibase(void);
86 static void set_ibase(void);
87 static void stackdepth(void);
88 static void push_scale(void);
89 static u_int count_digits(const struct number *);
90 static void num_digits(void);
91 static void to_ascii(void);
92 static void push_line(void);
93 static void comment(void);
94 static void badd(void);
95 static void bsub(void);
96 static void bmul(void);
97 static void bdiv(void);
98 static void bmod(void);
99 static void bdivmod(void);
100 static void bexp(void);
101 static bool bsqrt_stop(const BIGNUM *, const BIGNUM *, u_int *);
102 static void bsqrt(void);
103 static void not(void);
104 static void equal_numbers(void);
105 static void less_numbers(void);
106 static void lesseq_numbers(void);
107 static void equal(void);
108 static void not_equal(void);
109 static void less(void);
110 static void not_less(void);
111 static void greater(void);
112 static void not_greater(void);
113 static void not_compare(void);
114 static bool compare_numbers(enum bcode_compare, struct number *,
115 struct number *);
116 static void compare(enum bcode_compare);
117 static int readreg(void);
118 static void load(void);
119 static void store(void);
120 static void load_stack(void);
121 static void store_stack(void);
122 static void load_array(void);
123 static void store_array(void);
124 static void nop(void);
125 static void quit(void);
126 static void quitN(void);
127 static void skipN(void);
128 static void skip_until_mark(void);
129 static void parse_number(void);
130 static void unknown(void);
131 static void eval_string(char *);
132 static void eval_line(void);
133 static void eval_tos(void);
134
135
136 typedef void (*opcode_function)(void);
137
138 struct jump_entry {
139 u_char ch;
140 opcode_function f;
141 };
142
143 static opcode_function jump_table[UCHAR_MAX];
144
145 static const struct jump_entry jump_table_data[] = {
146 { ' ', nop },
147 { '!', not_compare },
148 { '#', comment },
149 { '%', bmod },
150 { '(', less_numbers },
151 { '*', bmul },
152 { '+', badd },
153 { '-', bsub },
154 { '.', parse_number },
155 { '/', bdiv },
156 { '0', parse_number },
157 { '1', parse_number },
158 { '2', parse_number },
159 { '3', parse_number },
160 { '4', parse_number },
161 { '5', parse_number },
162 { '6', parse_number },
163 { '7', parse_number },
164 { '8', parse_number },
165 { '9', parse_number },
166 { ':', store_array },
167 { ';', load_array },
168 { '<', less },
169 { '=', equal },
170 { '>', greater },
171 { '?', eval_line },
172 { 'A', parse_number },
173 { 'B', parse_number },
174 { 'C', parse_number },
175 { 'D', parse_number },
176 { 'E', parse_number },
177 { 'F', parse_number },
178 { 'G', equal_numbers },
179 { 'I', get_ibase },
180 { 'J', skipN },
181 { 'K', get_scale },
182 { 'L', load_stack },
183 { 'M', nop },
184 { 'N', not },
185 { 'O', get_obase },
186 { 'P', pop_print },
187 { 'Q', quitN },
188 { 'R', drop },
189 { 'S', store_stack },
190 { 'X', push_scale },
191 { 'Z', num_digits },
192 { '[', push_line },
193 { '\f', nop },
194 { '\n', nop },
195 { '\r', nop },
196 { '\t', nop },
197 { '^', bexp },
198 { '_', parse_number },
199 { 'a', to_ascii },
200 { 'c', clear_stack },
201 { 'd', dup },
202 { 'e', print_err },
203 { 'f', print_stack },
204 { 'i', set_ibase },
205 { 'k', set_scale },
206 { 'l', load },
207 { 'n', pop_printn },
208 { 'o', set_obase },
209 { 'p', print_tos },
210 { 'q', quit },
211 { 'r', swap },
212 { 's', store },
213 { 'v', bsqrt },
214 { 'x', eval_tos },
215 { 'z', stackdepth },
216 { '{', lesseq_numbers },
217 { '~', bdivmod }
218 };
219
220 #define JUMP_TABLE_DATA_SIZE \
221 (sizeof(jump_table_data)/sizeof(jump_table_data[0]))
222
223 /* ARGSUSED */
224 static void
225 sighandler(int ignored)
226 {
227 bmachine.interrupted = true;
228 }
229
230 void
231 init_bmachine(bool extended_registers)
232 {
233 size_t i;
234
235 bmachine.extended_regs = extended_registers;
236 bmachine.reg_array_size = bmachine.extended_regs ?
237 REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL;
238
239 bmachine.reg = calloc(bmachine.reg_array_size,
240 sizeof(bmachine.reg[0]));
241 if (bmachine.reg == NULL)
242 err(1, NULL);
243
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;
248
249 stack_init(&bmachine.stack);
250
251 for (i = 0; i < bmachine.reg_array_size; i++)
252 stack_init(&bmachine.reg[i]);
253
254 bmachine.readstack_sz = READSTACK_SIZE;
255 bmachine.readstack = calloc(sizeof(struct source),
256 bmachine.readstack_sz);
257 if (bmachine.readstack == NULL)
258 err(1, NULL);
259 bmachine.obase = bmachine.ibase = 10;
260 (void)signal(SIGINT, sighandler);
261 }
262
263 u_int
264 bmachine_scale(void)
265 {
266 return bmachine.scale;
267 }
268
269 /* Reset the things needed before processing a (new) file */
270 void
271 reset_bmachine(struct source *src)
272 {
273 bmachine.readsp = 0;
274 bmachine.readstack[0] = *src;
275 }
276
277 static __inline int
278 readch(void)
279 {
280 struct source *src = &bmachine.readstack[bmachine.readsp];
281
282 return src->vtable->readchar(src);
283 }
284
285 static __inline void
286 unreadch(void)
287 {
288 struct source *src = &bmachine.readstack[bmachine.readsp];
289
290 src->vtable->unreadchar(src);
291 }
292
293 static __inline char *
294 readline(void)
295 {
296 struct source *src = &bmachine.readstack[bmachine.readsp];
297
298 return src->vtable->readline(src);
299 }
300
301 static __inline void
302 src_free(void)
303 {
304 struct source *src = &bmachine.readstack[bmachine.readsp];
305
306 src->vtable->free(src);
307 }
308
309 #ifdef DEBUGGING
310 void
311 pn(const char *str, const struct number *n)
312 {
313 char *p = BN_bn2dec(n->number);
314 if (p == NULL)
315 err(1, "BN_bn2dec failed");
316 (void)fputs(str, stderr);
317 (void)fprintf(stderr, " %s (%u)\n" , p, n->scale);
318 OPENSSL_free(p);
319 }
320
321 void
322 pbn(const char *str, const BIGNUM *n)
323 {
324 char *p = BN_bn2dec(n);
325 if (p == NULL)
326 err(1, "BN_bn2dec failed");
327 (void)fputs(str, stderr);
328 (void)fprintf(stderr, " %s\n", p);
329 OPENSSL_free(p);
330 }
331
332 #endif
333
334 static __inline u_int
335 max(u_int a, u_int b)
336 {
337 return a > b ? a : b;
338 }
339
340 static unsigned long factors[] = {
341 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
342 100000000, 1000000000
343 };
344
345 void
346 scale_number(BIGNUM *n, int s)
347 {
348 size_t abs_scale;
349
350 if (s == 0)
351 return;
352
353 abs_scale = (size_t)(s > 0 ? s : -s);
354
355 if (abs_scale < sizeof(factors)/sizeof(factors[0])) {
356 if (s > 0)
357 bn_check(BN_mul_word(n, factors[abs_scale]));
358 else
359 (void)BN_div_word(n, factors[abs_scale]);
360 } else {
361 BIGNUM *a, *p;
362 BN_CTX *ctx;
363
364 a = BN_new();
365 bn_checkp(a);
366 p = BN_new();
367 bn_checkp(p);
368 ctx = BN_CTX_new();
369 bn_checkp(ctx);
370
371 bn_check(BN_set_word(a, 10));
372 bn_check(BN_set_word(p, abs_scale));
373 bn_check(BN_exp(a, a, p, ctx));
374 if (s > 0)
375 bn_check(BN_mul(n, n, a, ctx));
376 else
377 bn_check(BN_div(n, NULL, n, a, ctx));
378 BN_CTX_free(ctx);
379 BN_free(a);
380 BN_free(p);
381 }
382 }
383
384 void
385 split_number(const struct number *n, BIGNUM *i, BIGNUM *f)
386 {
387 u_long rem;
388
389 bn_checkp(BN_copy(i, n->number));
390
391 if (n->scale == 0 && f != NULL)
392 bn_check(BN_set_word(f, 0));
393 else if (n->scale < sizeof(factors)/sizeof(factors[0])) {
394 rem = BN_div_word(i, factors[n->scale]);
395 if (f != NULL)
396 bn_check(BN_set_word(f, rem));
397 } else {
398 BIGNUM *a, *p;
399 BN_CTX *ctx;
400
401 a = BN_new();
402 bn_checkp(a);
403 p = BN_new();
404 bn_checkp(p);
405 ctx = BN_CTX_new();
406 bn_checkp(ctx);
407
408 bn_check(BN_set_word(a, 10));
409 bn_check(BN_set_word(p, n->scale));
410 bn_check(BN_exp(a, a, p, ctx));
411 bn_check(BN_div(i, f, n->number, a, ctx));
412 BN_CTX_free(ctx);
413 BN_free(a);
414 BN_free(p);
415 }
416 }
417
418 void
419 normalize(struct number *n, u_int s)
420 {
421 scale_number(n->number, (int)(s - n->scale));
422 n->scale = s;
423 }
424
425 static u_long
426 get_ulong(struct number *n)
427 {
428 normalize(n, 0);
429 return BN_get_word(n->number);
430 }
431
432 void
433 negate(struct number *n)
434 {
435 BN_set_negative(n->number, !BN_is_negative(n->number));
436 }
437
438 static __inline void
439 push_number(struct number *n)
440 {
441 stack_pushnumber(&bmachine.stack, n);
442 }
443
444 static __inline void
445 push_string(char *string)
446 {
447 stack_pushstring(&bmachine.stack, string);
448 }
449
450 static __inline void
451 push(struct value *v)
452 {
453 stack_push(&bmachine.stack, v);
454 }
455
456 static __inline struct value *
457 tos(void)
458 {
459 return stack_tos(&bmachine.stack);
460 }
461
462 static __inline struct value *
463 pop(void)
464 {
465 return stack_pop(&bmachine.stack);
466 }
467
468 static __inline struct number *
469 pop_number(void)
470 {
471 return stack_popnumber(&bmachine.stack);
472 }
473
474 static __inline char *
475 pop_string(void)
476 {
477 return stack_popstring(&bmachine.stack);
478 }
479
480 static __inline void
481 clear_stack(void)
482 {
483 stack_clear(&bmachine.stack);
484 }
485
486 static __inline void
487 print_stack(void)
488 {
489 stack_print(stdout, &bmachine.stack, "", bmachine.obase);
490 }
491
492 static __inline void
493 print_tos(void)
494 {
495 struct value *value = tos();
496 if (value != NULL) {
497 print_value(stdout, value, "", bmachine.obase);
498 (void)putchar('\n');
499 }
500 else
501 warnx("stack empty");
502 }
503
504 static void
505 print_err(void)
506 {
507 struct value *value = tos();
508 if (value != NULL) {
509 print_value(stderr, value, "", bmachine.obase);
510 (void)putc('\n', stderr);
511 }
512 else
513 warnx("stack empty");
514 }
515
516 static void
517 pop_print(void)
518 {
519 struct value *value = pop();
520
521 if (value != NULL) {
522 switch (value->type) {
523 case BCODE_NONE:
524 break;
525 case BCODE_NUMBER:
526 normalize(value->u.num, 0);
527 print_ascii(stdout, value->u.num);
528 (void)fflush(stdout);
529 break;
530 case BCODE_STRING:
531 (void)fputs(value->u.string, stdout);
532 (void)fflush(stdout);
533 break;
534 }
535 stack_free_value(value);
536 }
537 }
538
539 static void
540 pop_printn(void)
541 {
542 struct value *value = pop();
543
544 if (value != NULL) {
545 print_value(stdout, value, "", bmachine.obase);
546 (void)fflush(stdout);
547 stack_free_value(value);
548 }
549 }
550
551 static __inline void
552 dup(void)
553 {
554 stack_dup(&bmachine.stack);
555 }
556
557 static void
558 swap(void)
559 {
560 stack_swap(&bmachine.stack);
561 }
562
563 static void
564 drop(void)
565 {
566 struct value *v = pop();
567 if (v != NULL)
568 stack_free_value(v);
569 }
570
571 static void
572 get_scale(void)
573 {
574 struct number *n;
575
576 n = new_number();
577 bn_check(BN_set_word(n->number, bmachine.scale));
578 push_number(n);
579 }
580
581 static void
582 set_scale(void)
583 {
584 struct number *n;
585 u_long scale;
586
587 n = pop_number();
588 if (n != NULL) {
589 if (BN_is_negative(n->number))
590 warnx("scale must be a nonnegative number");
591 else {
592 scale = get_ulong(n);
593 if (scale != BN_MASK2 && scale <= UINT_MAX)
594 bmachine.scale = (u_int)scale;
595 else
596 warnx("scale too large");
597 }
598 free_number(n);
599 }
600 }
601
602 static void
603 get_obase(void)
604 {
605 struct number *n;
606
607 n = new_number();
608 bn_check(BN_set_word(n->number, bmachine.obase));
609 push_number(n);
610 }
611
612 static void
613 set_obase(void)
614 {
615 struct number *n;
616 u_long base;
617
618 n = pop_number();
619 if (n != NULL) {
620 base = get_ulong(n);
621 if (base != BN_MASK2 && base > 1 && base <= UINT_MAX)
622 bmachine.obase = (u_int)base;
623 else
624 warnx("output base must be a number greater than 1");
625 free_number(n);
626 }
627 }
628
629 static void
630 get_ibase(void)
631 {
632 struct number *n;
633
634 n = new_number();
635 bn_check(BN_set_word(n->number, bmachine.ibase));
636 push_number(n);
637 }
638
639 static void
640 set_ibase(void)
641 {
642 struct number *n;
643 u_long base;
644
645 n = pop_number();
646 if (n != NULL) {
647 base = get_ulong(n);
648 if (base != BN_MASK2 && 2 <= base && base <= 16)
649 bmachine.ibase = (u_int)base;
650 else
651 warnx("input base must be a number between 2 and 16 "
652 "(inclusive)");
653 free_number(n);
654 }
655 }
656
657 static void
658 stackdepth(void)
659 {
660 size_t i;
661 struct number *n;
662
663 i = stack_size(&bmachine.stack);
664 n = new_number();
665 bn_check(BN_set_word(n->number, i));
666 push_number(n);
667 }
668
669 static void
670 push_scale(void)
671 {
672 struct value *value;
673 u_int scale = 0;
674 struct number *n;
675
676
677 value = pop();
678 if (value != NULL) {
679 switch (value->type) {
680 case BCODE_NONE:
681 return;
682 case BCODE_NUMBER:
683 scale = value->u.num->scale;
684 break;
685 case BCODE_STRING:
686 break;
687 }
688 stack_free_value(value);
689 n = new_number();
690 bn_check(BN_set_word(n->number, scale));
691 push_number(n);
692 }
693 }
694
695 static u_int
696 count_digits(const struct number *n)
697 {
698 struct number *int_part, *fract_part;
699 u_int i;
700
701 if (BN_is_zero(n->number))
702 return n->scale ? n->scale : 1;
703
704 int_part = new_number();
705 fract_part = new_number();
706 fract_part->scale = n->scale;
707 split_number(n, int_part->number, fract_part->number);
708
709 i = 0;
710 while (!BN_is_zero(int_part->number)) {
711 (void)BN_div_word(int_part->number, 10);
712 i++;
713 }
714 free_number(int_part);
715 free_number(fract_part);
716 return i + n->scale;
717 }
718
719 static void
720 num_digits(void)
721 {
722 struct value *value;
723 size_t digits;
724 struct number *n = NULL;
725
726 value = pop();
727 if (value != NULL) {
728 switch (value->type) {
729 case BCODE_NONE:
730 return;
731 case BCODE_NUMBER:
732 digits = count_digits(value->u.num);
733 n = new_number();
734 bn_check(BN_set_word(n->number, digits));
735 break;
736 case BCODE_STRING:
737 digits = strlen(value->u.string);
738 n = new_number();
739 bn_check(BN_set_word(n->number, digits));
740 break;
741 }
742 stack_free_value(value);
743 push_number(n);
744 }
745 }
746
747 static void
748 to_ascii(void)
749 {
750 char str[2];
751 struct value *value;
752 struct number *n;
753
754 value = pop();
755 if (value != NULL) {
756 str[1] = '\0';
757 switch (value->type) {
758 case BCODE_NONE:
759 return;
760 case BCODE_NUMBER:
761 n = value->u.num;
762 normalize(n, 0);
763 if (BN_num_bits(n->number) > 8)
764 bn_check(BN_mask_bits(n->number, 8));
765 str[0] = (char)BN_get_word(n->number);
766 break;
767 case BCODE_STRING:
768 str[0] = value->u.string[0];
769 break;
770 }
771 stack_free_value(value);
772 push_string(bstrdup(str));
773 }
774 }
775
776 static int
777 readreg(void)
778 {
779 int idx, ch1, ch2;
780
781 idx = readch();
782 if (idx == 0xff && bmachine.extended_regs) {
783 ch1 = readch();
784 ch2 = readch();
785 if (ch1 == EOF || ch2 == EOF) {
786 warnx("unexpected eof");
787 idx = -1;
788 } else
789 idx = (ch1 << 8) + ch2 + UCHAR_MAX + 1;
790 }
791 if (idx < 0 || (size_t)idx >= bmachine.reg_array_size) {
792 warnx("internal error: reg num = %d", idx);
793 idx = -1;
794 }
795 return idx;
796 }
797
798 static void
799 load(void)
800 {
801 int idx;
802 struct value *v, copy;
803 struct number *n;
804
805 idx = readreg();
806 if (idx >= 0) {
807 v = stack_tos(&bmachine.reg[idx]);
808 if (v == NULL) {
809 n = new_number();
810 bn_check(BN_set_word(n->number, 0));
811 push_number(n);
812 } else
813 push(stack_dup_value(v, ©));
814 }
815 }
816
817 static void
818 store(void)
819 {
820 int idx;
821 struct value *val;
822
823 idx = readreg();
824 if (idx >= 0) {
825 val = pop();
826 if (val == NULL) {
827 return;
828 }
829 stack_set_tos(&bmachine.reg[idx], val);
830 }
831 }
832
833 static void
834 load_stack(void)
835 {
836 int idx;
837 struct stack *stack;
838 struct value *value;
839
840 idx = readreg();
841 if (idx >= 0) {
842 stack = &bmachine.reg[idx];
843 value = NULL;
844 if (stack_size(stack) > 0) {
845 value = stack_pop(stack);
846 }
847 if (value != NULL)
848 push(value);
849 else
850 warnx("stack register '%c' (0%o) is empty",
851 idx, idx);
852 }
853 }
854
855 static void
856 store_stack(void)
857 {
858 int idx;
859 struct value *value;
860
861 idx = readreg();
862 if (idx >= 0) {
863 value = pop();
864 if (value == NULL)
865 return;
866 stack_push(&bmachine.reg[idx], value);
867 }
868 }
869
870 static void
871 load_array(void)
872 {
873 int reg;
874 struct number *inumber, *n;
875 u_long idx;
876 struct stack *stack;
877 struct value *v, copy;
878
879 reg = readreg();
880 if (reg >= 0) {
881 inumber = pop_number();
882 if (inumber == NULL)
883 return;
884 idx = get_ulong(inumber);
885 if (BN_is_negative(inumber->number))
886 warnx("negative idx");
887 else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX)
888 warnx("idx too big");
889 else {
890 stack = &bmachine.reg[reg];
891 v = frame_retrieve(stack, idx);
892 if (v == NULL || v->type == BCODE_NONE) {
893 n = new_number();
894 bn_check(BN_set_word(n->number, 0));
895 push_number(n);
896 }
897 else
898 push(stack_dup_value(v, ©));
899 }
900 free_number(inumber);
901 }
902 }
903
904 static void
905 store_array(void)
906 {
907 int reg;
908 struct number *inumber;
909 u_long idx;
910 struct value *value;
911 struct stack *stack;
912
913 reg = readreg();
914 if (reg >= 0) {
915 inumber = pop_number();
916 if (inumber == NULL)
917 return;
918 value = pop();
919 if (value == NULL) {
920 free_number(inumber);
921 return;
922 }
923 idx = get_ulong(inumber);
924 if (BN_is_negative(inumber->number)) {
925 warnx("negative idx");
926 stack_free_value(value);
927 } else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) {
928 warnx("idx too big");
929 stack_free_value(value);
930 } else {
931 stack = &bmachine.reg[reg];
932 frame_assign(stack, idx, value);
933 }
934 free_number(inumber);
935 }
936 }
937
938 static void
939 push_line(void)
940 {
941 push_string(read_string(&bmachine.readstack[bmachine.readsp]));
942 }
943
944 static void
945 comment(void)
946 {
947 free(readline());
948 }
949
950 static void
951 badd(void)
952 {
953 struct number *a, *b;
954 struct number *r;
955
956 a = pop_number();
957 if (a == NULL)
958 return;
959 b = pop_number();
960 if (b == NULL) {
961 push_number(a);
962 return;
963 }
964
965 r = new_number();
966 r->scale = max(a->scale, b->scale);
967 if (r->scale > a->scale)
968 normalize(a, r->scale);
969 else if (r->scale > b->scale)
970 normalize(b, r->scale);
971 bn_check(BN_add(r->number, a->number, b->number));
972 push_number(r);
973 free_number(a);
974 free_number(b);
975 }
976
977 static void
978 bsub(void)
979 {
980 struct number *a, *b;
981 struct number *r;
982
983 a = pop_number();
984 if (a == NULL)
985 return;
986 b = pop_number();
987 if (b == NULL) {
988 push_number(a);
989 return;
990 }
991
992 r = new_number();
993
994 r->scale = max(a->scale, b->scale);
995 if (r->scale > a->scale)
996 normalize(a, r->scale);
997 else if (r->scale > b->scale)
998 normalize(b, r->scale);
999 bn_check(BN_sub(r->number, b->number, a->number));
1000 push_number(r);
1001 free_number(a);
1002 free_number(b);
1003 }
1004
1005 void
1006 bmul_number(struct number *r, struct number *a, struct number *b, u_int scale)
1007 {
1008 BN_CTX *ctx;
1009
1010 /* Create copies of the scales, since r might be equal to a or b */
1011 u_int ascale = a->scale;
1012 u_int bscale = b->scale;
1013 u_int rscale = ascale + bscale;
1014
1015 ctx = BN_CTX_new();
1016 bn_checkp(ctx);
1017 bn_check(BN_mul(r->number, a->number, b->number, ctx));
1018 BN_CTX_free(ctx);
1019
1020 r->scale = rscale;
1021 if (rscale > bmachine.scale && rscale > ascale && rscale > bscale)
1022 normalize(r, max(scale, max(ascale, bscale)));
1023 }
1024
1025 static void
1026 bmul(void)
1027 {
1028 struct number *a, *b;
1029 struct number *r;
1030
1031 a = pop_number();
1032 if (a == NULL)
1033 return;
1034 b = pop_number();
1035 if (b == NULL) {
1036 push_number(a);
1037 return;
1038 }
1039
1040 r = new_number();
1041 bmul_number(r, a, b, bmachine.scale);
1042
1043 push_number(r);
1044 free_number(a);
1045 free_number(b);
1046 }
1047
1048 static void
1049 bdiv(void)
1050 {
1051 struct number *a, *b;
1052 struct number *r;
1053 u_int scale;
1054 BN_CTX *ctx;
1055
1056 a = pop_number();
1057 if (a == NULL)
1058 return;
1059 b = pop_number();
1060 if (b == NULL) {
1061 push_number(a);
1062 return;
1063 }
1064
1065 r = new_number();
1066 r->scale = bmachine.scale;
1067 scale = max(a->scale, b->scale);
1068
1069 if (BN_is_zero(a->number))
1070 warnx("divide by zero");
1071 else {
1072 normalize(a, scale);
1073 normalize(b, scale + r->scale);
1074
1075 ctx = BN_CTX_new();
1076 bn_checkp(ctx);
1077 bn_check(BN_div(r->number, NULL, b->number, a->number, ctx));
1078 BN_CTX_free(ctx);
1079 }
1080 push_number(r);
1081 free_number(a);
1082 free_number(b);
1083 }
1084
1085 static void
1086 bmod(void)
1087 {
1088 struct number *a, *b;
1089 struct number *r;
1090 u_int scale;
1091 BN_CTX *ctx;
1092
1093 a = pop_number();
1094 if (a == NULL)
1095 return;
1096 b = pop_number();
1097 if (b == NULL) {
1098 push_number(a);
1099 return;
1100 }
1101
1102 r = new_number();
1103 scale = max(a->scale, b->scale);
1104 r->scale = max(b->scale, a->scale + bmachine.scale);
1105
1106 if (BN_is_zero(a->number))
1107 warnx("remainder by zero");
1108 else {
1109 normalize(a, scale);
1110 normalize(b, scale + bmachine.scale);
1111
1112 ctx = BN_CTX_new();
1113 bn_checkp(ctx);
1114 bn_check(BN_mod(r->number, b->number, a->number, ctx));
1115 BN_CTX_free(ctx);
1116 }
1117 push_number(r);
1118 free_number(a);
1119 free_number(b);
1120 }
1121
1122 static void
1123 bdivmod(void)
1124 {
1125 struct number *a, *b;
1126 struct number *rdiv, *rmod;
1127 u_int scale;
1128 BN_CTX *ctx;
1129
1130 a = pop_number();
1131 if (a == NULL)
1132 return;
1133 b = pop_number();
1134 if (b == NULL) {
1135 push_number(a);
1136 return;
1137 }
1138
1139 rdiv = new_number();
1140 rmod = new_number();
1141 rdiv->scale = bmachine.scale;
1142 rmod->scale = max(b->scale, a->scale + bmachine.scale);
1143 scale = max(a->scale, b->scale);
1144
1145 if (BN_is_zero(a->number))
1146 warnx("divide by zero");
1147 else {
1148 normalize(a, scale);
1149 normalize(b, scale + bmachine.scale);
1150
1151 ctx = BN_CTX_new();
1152 bn_checkp(ctx);
1153 bn_check(BN_div(rdiv->number, rmod->number,
1154 b->number, a->number, ctx));
1155 BN_CTX_free(ctx);
1156 }
1157 push_number(rdiv);
1158 push_number(rmod);
1159 free_number(a);
1160 free_number(b);
1161 }
1162
1163 static void
1164 bexp(void)
1165 {
1166 struct number *a, *p;
1167 struct number *r;
1168 bool neg;
1169 u_int rscale;
1170
1171 p = pop_number();
1172 if (p == NULL)
1173 return;
1174 a = pop_number();
1175 if (a == NULL) {
1176 push_number(p);
1177 return;
1178 }
1179
1180 if (p->scale != 0) {
1181 BIGNUM *i, *f;
1182 i = BN_new();
1183 bn_checkp(i);
1184 f = BN_new();
1185 bn_checkp(f);
1186 split_number(p, i, f);
1187 if (!BN_is_zero(f))
1188 warnx("Runtime warning: non-zero fractional part in exponent");
1189 BN_free(i);
1190 BN_free(f);
1191 }
1192
1193 normalize(p, 0);
1194
1195 neg = false;
1196 if (BN_is_negative(p->number)) {
1197 neg = true;
1198 negate(p);
1199 rscale = bmachine.scale;
1200 } else {
1201 /* Posix bc says min(a.scale * b, max(a.scale, scale) */
1202 u_long b;
1203 u_int m;
1204
1205 b = BN_get_word(p->number);
1206 m = max(a->scale, bmachine.scale);
1207 rscale = a->scale * (u_int)b;
1208 if (rscale > m || (a->scale > 0 && (b == BN_MASK2 ||
1209 b > UINT_MAX)))
1210 rscale = m;
1211 }
1212
1213 if (BN_is_zero(p->number)) {
1214 r = new_number();
1215 bn_check(BN_one(r->number));
1216 normalize(r, rscale);
1217 } else {
1218 u_int ascale, mscale;
1219
1220 ascale = a->scale;
1221 while (!BN_is_bit_set(p->number, 0)) {
1222 ascale *= 2;
1223 bmul_number(a, a, a, ascale);
1224 bn_check(BN_rshift1(p->number, p->number));
1225 }
1226
1227 r = dup_number(a);
1228 bn_check(BN_rshift1(p->number, p->number));
1229
1230 mscale = ascale;
1231 while (!BN_is_zero(p->number)) {
1232 ascale *= 2;
1233 bmul_number(a, a, a, ascale);
1234 if (BN_is_bit_set(p->number, 0)) {
1235 mscale += ascale;
1236 bmul_number(r, r, a, mscale);
1237 }
1238 bn_check(BN_rshift1(p->number, p->number));
1239 }
1240
1241 if (neg) {
1242 BN_CTX *ctx;
1243 BIGNUM *one;
1244
1245 one = BN_new();
1246 bn_checkp(one);
1247 bn_check(BN_one(one));
1248 ctx = BN_CTX_new();
1249 bn_checkp(ctx);
1250 scale_number(one, (int)(r->scale + rscale));
1251
1252 if (BN_is_zero(r->number))
1253 warnx("divide by zero");
1254 else
1255 bn_check(BN_div(r->number, NULL, one,
1256 r->number, ctx));
1257 BN_free(one);
1258 BN_CTX_free(ctx);
1259 r->scale = rscale;
1260 } else
1261 normalize(r, rscale);
1262 }
1263 push_number(r);
1264 free_number(a);
1265 free_number(p);
1266 }
1267
1268 static bool
1269 bsqrt_stop(const BIGNUM *x, const BIGNUM *y, u_int *onecount)
1270 {
1271 BIGNUM *r;
1272 bool ret;
1273
1274 r = BN_new();
1275 bn_checkp(r);
1276 bn_check(BN_sub(r, x, y));
1277 if (BN_is_one(r))
1278 (*onecount)++;
1279 ret = BN_is_zero(r);
1280 BN_free(r);
1281 return ret || *onecount > 1;
1282 }
1283
1284 static void
1285 bsqrt(void)
1286 {
1287 struct number *n;
1288 struct number *r;
1289 BIGNUM *x, *y;
1290 u_int scale, onecount;
1291 BN_CTX *ctx;
1292
1293 onecount = 0;
1294 n = pop_number();
1295 if (n == NULL)
1296 return;
1297 if (BN_is_zero(n->number)) {
1298 r = new_number();
1299 push_number(r);
1300 } else if (BN_is_negative(n->number))
1301 warnx("square root of negative number");
1302 else {
1303 scale = max(bmachine.scale, n->scale);
1304 normalize(n, 2*scale);
1305 x = BN_dup(n->number);
1306 bn_checkp(x);
1307 bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
1308 y = BN_new();
1309 bn_checkp(y);
1310 ctx = BN_CTX_new();
1311 bn_checkp(ctx);
1312 for (;;) {
1313 bn_checkp(BN_copy(y, x));
1314 bn_check(BN_div(x, NULL, n->number, x, ctx));
1315 bn_check(BN_add(x, x, y));
1316 bn_check(BN_rshift1(x, x));
1317 if (bsqrt_stop(x, y, &onecount))
1318 break;
1319 }
1320 r = bmalloc(sizeof(*r));
1321 r->scale = scale;
1322 r->number = y;
1323 BN_free(x);
1324 BN_CTX_free(ctx);
1325 push_number(r);
1326 }
1327
1328 free_number(n);
1329 }
1330
1331 static void
1332 not(void)
1333 {
1334 struct number *a;
1335
1336 a = pop_number();
1337 if (a == NULL)
1338 return;
1339 a->scale = 0;
1340 bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1));
1341 push_number(a);
1342 }
1343
1344 static void
1345 equal(void)
1346 {
1347 compare(BCODE_EQUAL);
1348 }
1349
1350 static void
1351 equal_numbers(void)
1352 {
1353 struct number *a, *b, *r;
1354
1355 a = pop_number();
1356 if (a == NULL)
1357 return;
1358 b = pop_number();
1359 if (b == NULL) {
1360 push_number(a);
1361 return;
1362 }
1363 r = new_number();
1364 bn_check(BN_set_word(r->number,
1365 compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0));
1366 push_number(r);
1367 }
1368
1369 static void
1370 less_numbers(void)
1371 {
1372 struct number *a, *b, *r;
1373
1374 a = pop_number();
1375 if (a == NULL)
1376 return;
1377 b = pop_number();
1378 if (b == NULL) {
1379 push_number(a);
1380 return;
1381 }
1382 r = new_number();
1383 bn_check(BN_set_word(r->number,
1384 compare_numbers(BCODE_LESS, a, b) ? 1 : 0));
1385 push_number(r);
1386 }
1387
1388 static void
1389 lesseq_numbers(void)
1390 {
1391 struct number *a, *b, *r;
1392
1393 a = pop_number();
1394 if (a == NULL)
1395 return;
1396 b = pop_number();
1397 if (b == NULL) {
1398 push_number(a);
1399 return;
1400 }
1401 r = new_number();
1402 bn_check(BN_set_word(r->number,
1403 compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
1404 push_number(r);
1405 }
1406
1407 static void
1408 not_equal(void)
1409 {
1410 compare(BCODE_NOT_EQUAL);
1411 }
1412
1413 static void
1414 less(void)
1415 {
1416 compare(BCODE_LESS);
1417 }
1418
1419 static void
1420 not_compare(void)
1421 {
1422 switch (readch()) {
1423 case '<':
1424 not_less();
1425 break;
1426 case '>':
1427 not_greater();
1428 break;
1429 case '=':
1430 not_equal();
1431 break;
1432 default:
1433 unreadch();
1434 (void)fprintf(stderr, "! command is deprecated\n");
1435 break;
1436 }
1437 }
1438
1439 static void
1440 not_less(void)
1441 {
1442 compare(BCODE_NOT_LESS);
1443 }
1444
1445 static void
1446 greater(void)
1447 {
1448 compare(BCODE_GREATER);
1449 }
1450
1451 static void
1452 not_greater(void)
1453 {
1454 compare(BCODE_NOT_GREATER);
1455 }
1456
1457 static bool
1458 compare_numbers(enum bcode_compare type, struct number *a, struct number *b)
1459 {
1460 u_int scale;
1461 int cmp;
1462
1463 scale = max(a->scale, b->scale);
1464
1465 if (scale > a->scale)
1466 normalize(a, scale);
1467 else if (scale > b->scale)
1468 normalize(b, scale);
1469
1470 cmp = BN_cmp(a->number, b->number);
1471
1472 free_number(a);
1473 free_number(b);
1474
1475 switch (type) {
1476 case BCODE_EQUAL:
1477 return cmp == 0;
1478 case BCODE_NOT_EQUAL:
1479 return cmp != 0;
1480 case BCODE_LESS:
1481 return cmp < 0;
1482 case BCODE_NOT_LESS:
1483 return cmp >= 0;
1484 case BCODE_GREATER:
1485 return cmp > 0;
1486 case BCODE_NOT_GREATER:
1487 return cmp <= 0;
1488 }
1489 return false;
1490 }
1491
1492 static void
1493 compare(enum bcode_compare type)
1494 {
1495 int idx, elseidx;
1496 struct number *a, *b;
1497 bool ok;
1498 struct value *v;
1499
1500 elseidx = NO_ELSE;
1501 idx = readreg();
1502 if (readch() == 'e')
1503 elseidx = readreg();
1504 else
1505 unreadch();
1506
1507 a = pop_number();
1508 if (a == NULL)
1509 return;
1510 b = pop_number();
1511 if (b == NULL) {
1512 push_number(a);
1513 return;
1514 }
1515
1516 ok = compare_numbers(type, a, b);
1517
1518 if (!ok && elseidx != NO_ELSE)
1519 idx = elseidx;
1520
1521 if (idx >= 0 && (ok || (!ok && elseidx != NO_ELSE))) {
1522 v = stack_tos(&bmachine.reg[idx]);
1523 if (v == NULL)
1524 warnx("register '%c' (0%o) is empty", idx, idx);
1525 else {
1526 switch(v->type) {
1527 case BCODE_NONE:
1528 warnx("register '%c' (0%o) is empty", idx, idx);
1529 break;
1530 case BCODE_NUMBER:
1531 warn("eval called with non-string argument");
1532 break;
1533 case BCODE_STRING:
1534 eval_string(bstrdup(v->u.string));
1535 break;
1536 }
1537 }
1538 }
1539 }
1540
1541
1542 static void
1543 nop(void)
1544 {
1545 }
1546
1547 static void
1548 quit(void)
1549 {
1550 if (bmachine.readsp < 2)
1551 exit(0);
1552 src_free();
1553 bmachine.readsp--;
1554 src_free();
1555 bmachine.readsp--;
1556 }
1557
1558 static void
1559 quitN(void)
1560 {
1561 struct number *n;
1562 u_long i;
1563
1564 n = pop_number();
1565 if (n == NULL)
1566 return;
1567 i = get_ulong(n);
1568 free_number(n);
1569 if (i == BN_MASK2 || i == 0)
1570 warnx("Q command requires a number >= 1");
1571 else if (bmachine.readsp < i)
1572 warnx("Q command argument exceeded string execution depth");
1573 else {
1574 while (i-- > 0) {
1575 src_free();
1576 bmachine.readsp--;
1577 }
1578 }
1579 }
1580
1581 static void
1582 skipN(void)
1583 {
1584 struct number *n;
1585 u_long i;
1586
1587 n = pop_number();
1588 if (n == NULL)
1589 return;
1590 i = get_ulong(n);
1591 if (i == BN_MASK2)
1592 warnx("J command requires a number >= 0");
1593 else if (i > 0 && bmachine.readsp < i)
1594 warnx("J command argument exceeded string execution depth");
1595 else {
1596 while (i-- > 0) {
1597 src_free();
1598 bmachine.readsp--;
1599 }
1600 skip_until_mark();
1601 }
1602 }
1603
1604 static void
1605 skip_until_mark(void)
1606 {
1607 int ch;
1608
1609 for (;;) {
1610 ch = readch();
1611 switch (ch) {
1612 case 'M':
1613 return;
1614 case EOF:
1615 errx(1, "mark not found");
1616 return;
1617 case 'l':
1618 case 'L':
1619 case 's':
1620 case 'S':
1621 case ':':
1622 case ';':
1623 case '<':
1624 case '>':
1625 case '=':
1626 (void)readreg();
1627 if (readch() == 'e')
1628 (void)readreg();
1629 else
1630 unreadch();
1631 break;
1632 case '[':
1633 free(read_string(&bmachine.readstack[bmachine.readsp]));
1634 break;
1635 case '!':
1636 switch (ch = readch()) {
1637 case '<':
1638 case '>':
1639 case '=':
1640 (void)readreg();
1641 if (readch() == 'e')
1642 (void)readreg();
1643 else
1644 unreadch();
1645 break;
1646 default:
1647 free(readline());
1648 break;
1649 }
1650 break;
1651 default:
1652 break;
1653 }
1654 }
1655 }
1656
1657 static void
1658 parse_number(void)
1659 {
1660 unreadch();
1661 push_number(readnumber(&bmachine.readstack[bmachine.readsp],
1662 bmachine.ibase));
1663 }
1664
1665 static void
1666 unknown(void)
1667 {
1668 int ch = bmachine.readstack[bmachine.readsp].lastchar;
1669 warnx("%c (0%o) is unimplemented", ch, ch);
1670 }
1671
1672 static void
1673 eval_string(char *p)
1674 {
1675 int ch;
1676
1677 if (bmachine.readsp > 0) {
1678 /* Check for tail call. Do not recurse in that case. */
1679 ch = readch();
1680 if (ch == EOF) {
1681 src_free();
1682 src_setstring(&bmachine.readstack[bmachine.readsp], p);
1683 return;
1684 } else
1685 unreadch();
1686 }
1687 if (bmachine.readsp == bmachine.readstack_sz - 1) {
1688 size_t newsz = bmachine.readstack_sz * 2;
1689 struct source *stack = bmachine.readstack;
1690 int ret = reallocarr(&stack, newsz, sizeof(struct source));
1691 if (ret)
1692 errc(1, ret, "recursion too deep");
1693 bmachine.readstack_sz = newsz;
1694 bmachine.readstack = stack;
1695 }
1696 src_setstring(&bmachine.readstack[++bmachine.readsp], p);
1697 }
1698
1699 static void
1700 eval_line(void)
1701 {
1702 /* Always read from stdin */
1703 struct source in;
1704 char *p;
1705
1706 clearerr(stdin);
1707 src_setstream(&in, stdin);
1708 p = (*in.vtable->readline)(&in);
1709 eval_string(p);
1710 }
1711
1712 static void
1713 eval_tos(void)
1714 {
1715 char *p;
1716
1717 p = pop_string();
1718 if (p != NULL)
1719 eval_string(p);
1720 }
1721
1722 void
1723 eval(void)
1724 {
1725 int ch;
1726
1727 for (;;) {
1728 ch = readch();
1729 if (ch == EOF) {
1730 if (bmachine.readsp == 0)
1731 return;
1732 src_free();
1733 bmachine.readsp--;
1734 continue;
1735 }
1736 if (bmachine.interrupted) {
1737 if (bmachine.readsp > 0) {
1738 src_free();
1739 bmachine.readsp--;
1740 continue;
1741 } else
1742 bmachine.interrupted = false;
1743 }
1744 #ifdef DEBUGGING
1745 (void)fprintf(stderr, "# %c\n", ch);
1746 stack_print(stderr, &bmachine.stack, "* ",
1747 bmachine.obase);
1748 (void)fprintf(stderr, "%zd =>\n", bmachine.readsp);
1749 #endif
1750
1751 if (0 <= ch && ch < UCHAR_MAX)
1752 (*jump_table[ch])();
1753 else
1754 warnx("internal error: opcode %d", ch);
1755
1756 #ifdef DEBUGGING
1757 stack_print(stderr, &bmachine.stack, "* ",
1758 bmachine.obase);
1759 (void)fprintf(stderr, "%zd ==\n", bmachine.readsp);
1760 #endif
1761 }
1762 }
1763