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