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