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