1265533Sdelphij/* $OpenBSD: bcode.c,v 1.45 2012/11/07 11:06:14 otto Exp $ */ 2202719Sgabor 3202719Sgabor/* 4202719Sgabor * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 5202719Sgabor * 6202719Sgabor * Permission to use, copy, modify, and distribute this software for any 7202719Sgabor * purpose with or without fee is hereby granted, provided that the above 8202719Sgabor * copyright notice and this permission notice appear in all copies. 9202719Sgabor * 10202719Sgabor * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11202719Sgabor * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12202719Sgabor * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13202719Sgabor * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14202719Sgabor * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15202719Sgabor * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16202719Sgabor * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17202719Sgabor */ 18202719Sgabor 19202719Sgabor#include <sys/cdefs.h> 20202719Sgabor__FBSDID("$FreeBSD$"); 21202719Sgabor 22202719Sgabor#include <err.h> 23202719Sgabor#include <limits.h> 24202719Sgabor#include <openssl/ssl.h> 25202719Sgabor#include <signal.h> 26202719Sgabor#include <stdio.h> 27202719Sgabor#include <stdlib.h> 28202719Sgabor#include <string.h> 29202719Sgabor 30202719Sgabor#include "extern.h" 31202719Sgabor 32265533Sdelphij/* #define DEBUGGING */ 33202719Sgabor 34202719Sgabor#define MAX_ARRAY_INDEX 2048 35202719Sgabor#define READSTACK_SIZE 8 36202719Sgabor 37202719Sgabor#define NO_ELSE -2 /* -1 is EOF */ 38202719Sgabor#define REG_ARRAY_SIZE_SMALL (UCHAR_MAX + 1) 39202719Sgabor#define REG_ARRAY_SIZE_BIG (UCHAR_MAX + 1 + USHRT_MAX + 1) 40202719Sgabor 41202719Sgaborstruct bmachine { 42203443Sgabor struct source *readstack; 43203443Sgabor struct stack *reg; 44202719Sgabor struct stack stack; 45202719Sgabor u_int scale; 46202719Sgabor u_int obase; 47202719Sgabor u_int ibase; 48202719Sgabor size_t readsp; 49202719Sgabor size_t reg_array_size; 50202719Sgabor size_t readstack_sz; 51203443Sgabor bool extended_regs; 52202719Sgabor}; 53202719Sgabor 54202719Sgaborstatic struct bmachine bmachine; 55202719Sgabor 56202719Sgaborstatic __inline int readch(void); 57202719Sgaborstatic __inline void unreadch(void); 58202719Sgaborstatic __inline char *readline(void); 59202719Sgaborstatic __inline void src_free(void); 60202719Sgabor 61202719Sgaborstatic __inline u_int max(u_int, u_int); 62202719Sgaborstatic u_long get_ulong(struct number *); 63202719Sgabor 64202719Sgaborstatic __inline void push_number(struct number *); 65202719Sgaborstatic __inline void push_string(char *); 66202719Sgaborstatic __inline void push(struct value *); 67202719Sgaborstatic __inline struct value *tos(void); 68202719Sgaborstatic __inline struct number *pop_number(void); 69202719Sgaborstatic __inline char *pop_string(void); 70202719Sgaborstatic __inline void clear_stack(void); 71202719Sgaborstatic __inline void print_tos(void); 72202719Sgaborstatic void pop_print(void); 73202719Sgaborstatic void pop_printn(void); 74202719Sgaborstatic __inline void print_stack(void); 75202719Sgaborstatic __inline void dup(void); 76202719Sgaborstatic void swap(void); 77202719Sgaborstatic void drop(void); 78202719Sgabor 79202719Sgaborstatic void get_scale(void); 80202719Sgaborstatic void set_scale(void); 81202719Sgaborstatic void get_obase(void); 82202719Sgaborstatic void set_obase(void); 83202719Sgaborstatic void get_ibase(void); 84202719Sgaborstatic void set_ibase(void); 85202719Sgaborstatic void stackdepth(void); 86202719Sgaborstatic void push_scale(void); 87202719Sgaborstatic u_int count_digits(const struct number *); 88202719Sgaborstatic void num_digits(void); 89202719Sgaborstatic void to_ascii(void); 90202719Sgaborstatic void push_line(void); 91202719Sgaborstatic void comment(void); 92202719Sgaborstatic void bexec(char *); 93202719Sgaborstatic void badd(void); 94202719Sgaborstatic void bsub(void); 95202719Sgaborstatic void bmul(void); 96202719Sgaborstatic void bdiv(void); 97202719Sgaborstatic void bmod(void); 98202719Sgaborstatic void bdivmod(void); 99202719Sgaborstatic void bexp(void); 100202719Sgaborstatic bool bsqrt_stop(const BIGNUM *, const BIGNUM *, u_int *); 101202719Sgaborstatic void bsqrt(void); 102202719Sgaborstatic void not(void); 103202719Sgaborstatic void equal_numbers(void); 104202719Sgaborstatic void less_numbers(void); 105202719Sgaborstatic void lesseq_numbers(void); 106202719Sgaborstatic void equal(void); 107202719Sgaborstatic void not_equal(void); 108202719Sgaborstatic void less(void); 109202719Sgaborstatic void not_less(void); 110202719Sgaborstatic void greater(void); 111202719Sgaborstatic void not_greater(void); 112202719Sgaborstatic void not_compare(void); 113202719Sgaborstatic bool compare_numbers(enum bcode_compare, struct number *, 114202719Sgabor struct number *); 115202719Sgaborstatic void compare(enum bcode_compare); 116202719Sgaborstatic int readreg(void); 117202719Sgaborstatic void load(void); 118202719Sgaborstatic void store(void); 119202719Sgaborstatic void load_stack(void); 120202719Sgaborstatic void store_stack(void); 121202719Sgaborstatic void load_array(void); 122202719Sgaborstatic void store_array(void); 123202719Sgaborstatic void nop(void); 124202719Sgaborstatic void quit(void); 125202719Sgaborstatic void quitN(void); 126202719Sgaborstatic void skipN(void); 127202719Sgaborstatic void skip_until_mark(void); 128202719Sgaborstatic void parse_number(void); 129202719Sgaborstatic void unknown(void); 130202719Sgaborstatic void eval_string(char *); 131202719Sgaborstatic void eval_line(void); 132202719Sgaborstatic void eval_tos(void); 133202719Sgabor 134202719Sgabor 135202719Sgabortypedef void (*opcode_function)(void); 136202719Sgabor 137202719Sgaborstruct jump_entry { 138202719Sgabor u_char ch; 139202719Sgabor opcode_function f; 140202719Sgabor}; 141202719Sgabor 142202719Sgaborstatic opcode_function jump_table[UCHAR_MAX]; 143202719Sgabor 144202719Sgaborstatic const struct jump_entry jump_table_data[] = { 145202719Sgabor { ' ', nop }, 146202719Sgabor { '!', not_compare }, 147202719Sgabor { '#', comment }, 148202719Sgabor { '%', bmod }, 149202719Sgabor { '(', less_numbers }, 150202719Sgabor { '*', bmul }, 151202719Sgabor { '+', badd }, 152202719Sgabor { '-', bsub }, 153202719Sgabor { '.', parse_number }, 154202719Sgabor { '/', bdiv }, 155202719Sgabor { '0', parse_number }, 156202719Sgabor { '1', parse_number }, 157202719Sgabor { '2', parse_number }, 158202719Sgabor { '3', parse_number }, 159202719Sgabor { '4', parse_number }, 160202719Sgabor { '5', parse_number }, 161202719Sgabor { '6', parse_number }, 162202719Sgabor { '7', parse_number }, 163202719Sgabor { '8', parse_number }, 164202719Sgabor { '9', parse_number }, 165202719Sgabor { ':', store_array }, 166202719Sgabor { ';', load_array }, 167202719Sgabor { '<', less }, 168202719Sgabor { '=', equal }, 169202719Sgabor { '>', greater }, 170202719Sgabor { '?', eval_line }, 171202719Sgabor { 'A', parse_number }, 172202719Sgabor { 'B', parse_number }, 173202719Sgabor { 'C', parse_number }, 174202719Sgabor { 'D', parse_number }, 175202719Sgabor { 'E', parse_number }, 176202719Sgabor { 'F', parse_number }, 177202719Sgabor { 'G', equal_numbers }, 178202719Sgabor { 'I', get_ibase }, 179202719Sgabor { 'J', skipN }, 180202719Sgabor { 'K', get_scale }, 181202719Sgabor { 'L', load_stack }, 182202719Sgabor { 'M', nop }, 183202719Sgabor { 'N', not }, 184202719Sgabor { 'O', get_obase }, 185202719Sgabor { 'P', pop_print }, 186202719Sgabor { 'Q', quitN }, 187202719Sgabor { 'R', drop }, 188202719Sgabor { 'S', store_stack }, 189202719Sgabor { 'X', push_scale }, 190202719Sgabor { 'Z', num_digits }, 191202719Sgabor { '[', push_line }, 192202719Sgabor { '\f', nop }, 193202719Sgabor { '\n', nop }, 194202719Sgabor { '\r', nop }, 195202719Sgabor { '\t', nop }, 196202719Sgabor { '^', bexp }, 197202719Sgabor { '_', parse_number }, 198202719Sgabor { 'a', to_ascii }, 199202719Sgabor { 'c', clear_stack }, 200202719Sgabor { 'd', dup }, 201202719Sgabor { 'f', print_stack }, 202202719Sgabor { 'i', set_ibase }, 203202719Sgabor { 'k', set_scale }, 204202719Sgabor { 'l', load }, 205202719Sgabor { 'n', pop_printn }, 206202719Sgabor { 'o', set_obase }, 207202719Sgabor { 'p', print_tos }, 208202719Sgabor { 'q', quit }, 209202719Sgabor { 'r', swap }, 210202719Sgabor { 's', store }, 211202719Sgabor { 'v', bsqrt }, 212202719Sgabor { 'x', eval_tos }, 213202719Sgabor { 'z', stackdepth }, 214202719Sgabor { '{', lesseq_numbers }, 215202719Sgabor { '~', bdivmod } 216202719Sgabor}; 217202719Sgabor 218202719Sgabor#define JUMP_TABLE_DATA_SIZE \ 219202719Sgabor (sizeof(jump_table_data)/sizeof(jump_table_data[0])) 220202719Sgabor 221202719Sgaborvoid 222202719Sgaborinit_bmachine(bool extended_registers) 223202719Sgabor{ 224203443Sgabor unsigned int i; 225202719Sgabor 226202719Sgabor bmachine.extended_regs = extended_registers; 227202719Sgabor bmachine.reg_array_size = bmachine.extended_regs ? 228202719Sgabor REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL; 229202719Sgabor 230202719Sgabor bmachine.reg = calloc(bmachine.reg_array_size, 231202719Sgabor sizeof(bmachine.reg[0])); 232202719Sgabor if (bmachine.reg == NULL) 233202719Sgabor err(1, NULL); 234202719Sgabor 235202719Sgabor for (i = 0; i < UCHAR_MAX; i++) 236202719Sgabor jump_table[i] = unknown; 237202719Sgabor for (i = 0; i < JUMP_TABLE_DATA_SIZE; i++) 238202719Sgabor jump_table[jump_table_data[i].ch] = jump_table_data[i].f; 239202719Sgabor 240202719Sgabor stack_init(&bmachine.stack); 241202719Sgabor 242202719Sgabor for (i = 0; i < bmachine.reg_array_size; i++) 243202719Sgabor stack_init(&bmachine.reg[i]); 244202719Sgabor 245202719Sgabor bmachine.readstack_sz = READSTACK_SIZE; 246202719Sgabor bmachine.readstack = calloc(sizeof(struct source), 247202719Sgabor bmachine.readstack_sz); 248202719Sgabor if (bmachine.readstack == NULL) 249202719Sgabor err(1, NULL); 250202719Sgabor bmachine.obase = bmachine.ibase = 10; 251202719Sgabor} 252202719Sgabor 253244861Skevlou_int 254244861Skevlobmachine_scale(void) 255244861Skevlo{ 256265533Sdelphij return bmachine.scale; 257244861Skevlo} 258244861Skevlo 259202719Sgabor/* Reset the things needed before processing a (new) file */ 260202719Sgaborvoid 261202719Sgaborreset_bmachine(struct source *src) 262202719Sgabor{ 263202719Sgabor 264202719Sgabor bmachine.readsp = 0; 265202719Sgabor bmachine.readstack[0] = *src; 266202719Sgabor} 267202719Sgabor 268202719Sgaborstatic __inline int 269202719Sgaborreadch(void) 270202719Sgabor{ 271203443Sgabor struct source *src = &bmachine.readstack[bmachine.readsp]; 272202719Sgabor 273202719Sgabor return (src->vtable->readchar(src)); 274202719Sgabor} 275202719Sgabor 276202719Sgaborstatic __inline void 277202719Sgaborunreadch(void) 278202719Sgabor{ 279203443Sgabor struct source *src = &bmachine.readstack[bmachine.readsp]; 280202719Sgabor 281202719Sgabor src->vtable->unreadchar(src); 282202719Sgabor} 283202719Sgabor 284202719Sgaborstatic __inline char * 285202719Sgaborreadline(void) 286202719Sgabor{ 287203443Sgabor struct source *src = &bmachine.readstack[bmachine.readsp]; 288202719Sgabor 289202719Sgabor return (src->vtable->readline(src)); 290202719Sgabor} 291202719Sgabor 292202719Sgaborstatic __inline void 293202719Sgaborsrc_free(void) 294202719Sgabor{ 295203443Sgabor struct source *src = &bmachine.readstack[bmachine.readsp]; 296202719Sgabor 297202719Sgabor src->vtable->free(src); 298202719Sgabor} 299202719Sgabor 300202719Sgabor#ifdef DEBUGGING 301202719Sgaborvoid 302202719Sgaborpn(const char *str, const struct number *n) 303202719Sgabor{ 304203443Sgabor char *p = BN_bn2dec(n->number); 305202719Sgabor 306202719Sgabor if (p == NULL) 307202719Sgabor err(1, "BN_bn2dec failed"); 308202719Sgabor fputs(str, stderr); 309202719Sgabor fprintf(stderr, " %s (%u)\n" , p, n->scale); 310202719Sgabor OPENSSL_free(p); 311202719Sgabor} 312202719Sgabor 313202719Sgaborvoid 314202719Sgaborpbn(const char *str, const BIGNUM *n) 315202719Sgabor{ 316203443Sgabor char *p = BN_bn2dec(n); 317202719Sgabor 318202719Sgabor if (p == NULL) 319202719Sgabor err(1, "BN_bn2dec failed"); 320202719Sgabor fputs(str, stderr); 321202719Sgabor fprintf(stderr, " %s\n", p); 322202719Sgabor OPENSSL_free(p); 323202719Sgabor} 324202719Sgabor 325202719Sgabor#endif 326202719Sgabor 327202719Sgaborstatic __inline u_int 328202719Sgabormax(u_int a, u_int b) 329202719Sgabor{ 330202719Sgabor 331202719Sgabor return (a > b ? a : b); 332202719Sgabor} 333202719Sgabor 334202719Sgaborstatic unsigned long factors[] = { 335202719Sgabor 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 336202719Sgabor 100000000, 1000000000 337202719Sgabor}; 338202719Sgabor 339202719Sgaborvoid 340202719Sgaborscale_number(BIGNUM *n, int s) 341202719Sgabor{ 342203443Sgabor unsigned int abs_scale; 343202719Sgabor 344202719Sgabor if (s == 0) 345202719Sgabor return; 346202719Sgabor 347202719Sgabor abs_scale = s > 0 ? s : -s; 348202719Sgabor 349202719Sgabor if (abs_scale < sizeof(factors)/sizeof(factors[0])) { 350202719Sgabor if (s > 0) 351202719Sgabor bn_check(BN_mul_word(n, factors[abs_scale])); 352202719Sgabor else 353202719Sgabor BN_div_word(n, factors[abs_scale]); 354202719Sgabor } else { 355203443Sgabor BIGNUM *a, *p; 356203443Sgabor BN_CTX *ctx; 357202719Sgabor 358202719Sgabor a = BN_new(); 359202719Sgabor bn_checkp(a); 360202719Sgabor p = BN_new(); 361202719Sgabor bn_checkp(p); 362202719Sgabor ctx = BN_CTX_new(); 363202719Sgabor bn_checkp(ctx); 364202719Sgabor 365202719Sgabor bn_check(BN_set_word(a, 10)); 366202719Sgabor bn_check(BN_set_word(p, abs_scale)); 367202719Sgabor bn_check(BN_exp(a, a, p, ctx)); 368202719Sgabor if (s > 0) 369202719Sgabor bn_check(BN_mul(n, n, a, ctx)); 370202719Sgabor else 371202719Sgabor bn_check(BN_div(n, NULL, n, a, ctx)); 372202719Sgabor BN_CTX_free(ctx); 373202719Sgabor BN_free(a); 374202719Sgabor BN_free(p); 375202719Sgabor } 376202719Sgabor} 377202719Sgabor 378202719Sgaborvoid 379202719Sgaborsplit_number(const struct number *n, BIGNUM *i, BIGNUM *f) 380202719Sgabor{ 381203443Sgabor u_long rem; 382202719Sgabor 383202719Sgabor bn_checkp(BN_copy(i, n->number)); 384202719Sgabor 385202719Sgabor if (n->scale == 0 && f != NULL) 386202719Sgabor bn_check(BN_zero(f)); 387202719Sgabor else if (n->scale < sizeof(factors)/sizeof(factors[0])) { 388202719Sgabor rem = BN_div_word(i, factors[n->scale]); 389202719Sgabor if (f != NULL) 390202719Sgabor bn_check(BN_set_word(f, rem)); 391202719Sgabor } else { 392202719Sgabor BIGNUM *a, *p; 393202719Sgabor BN_CTX *ctx; 394202719Sgabor 395202719Sgabor a = BN_new(); 396202719Sgabor bn_checkp(a); 397202719Sgabor p = BN_new(); 398202719Sgabor bn_checkp(p); 399202719Sgabor ctx = BN_CTX_new(); 400202719Sgabor bn_checkp(ctx); 401202719Sgabor 402202719Sgabor bn_check(BN_set_word(a, 10)); 403202719Sgabor bn_check(BN_set_word(p, n->scale)); 404202719Sgabor bn_check(BN_exp(a, a, p, ctx)); 405202719Sgabor bn_check(BN_div(i, f, n->number, a, ctx)); 406202719Sgabor BN_CTX_free(ctx); 407202719Sgabor BN_free(a); 408202719Sgabor BN_free(p); 409202719Sgabor } 410202719Sgabor} 411202719Sgabor 412244861Skevlovoid 413202719Sgabornormalize(struct number *n, u_int s) 414202719Sgabor{ 415202719Sgabor 416202719Sgabor scale_number(n->number, s - n->scale); 417202719Sgabor n->scale = s; 418202719Sgabor} 419202719Sgabor 420202719Sgaborstatic u_long 421202719Sgaborget_ulong(struct number *n) 422202719Sgabor{ 423202719Sgabor 424202719Sgabor normalize(n, 0); 425202719Sgabor return (BN_get_word(n->number)); 426202719Sgabor} 427202719Sgabor 428202719Sgaborvoid 429202719Sgabornegate(struct number *n) 430202719Sgabor{ 431244861Skevlo BN_set_negative(n->number, !BN_is_negative(n->number)); 432202719Sgabor} 433202719Sgabor 434202719Sgaborstatic __inline void 435202719Sgaborpush_number(struct number *n) 436202719Sgabor{ 437202719Sgabor 438202719Sgabor stack_pushnumber(&bmachine.stack, n); 439202719Sgabor} 440202719Sgabor 441202719Sgaborstatic __inline void 442202719Sgaborpush_string(char *string) 443202719Sgabor{ 444202719Sgabor 445202719Sgabor stack_pushstring(&bmachine.stack, string); 446202719Sgabor} 447202719Sgabor 448202719Sgaborstatic __inline void 449202719Sgaborpush(struct value *v) 450202719Sgabor{ 451202719Sgabor 452202719Sgabor stack_push(&bmachine.stack, v); 453202719Sgabor} 454202719Sgabor 455202719Sgaborstatic __inline struct value * 456202719Sgabortos(void) 457202719Sgabor{ 458202719Sgabor 459202719Sgabor return (stack_tos(&bmachine.stack)); 460202719Sgabor} 461202719Sgabor 462202719Sgaborstatic __inline struct value * 463202719Sgaborpop(void) 464202719Sgabor{ 465202719Sgabor 466202719Sgabor return (stack_pop(&bmachine.stack)); 467202719Sgabor} 468202719Sgabor 469202719Sgaborstatic __inline struct number * 470202719Sgaborpop_number(void) 471202719Sgabor{ 472202719Sgabor 473202719Sgabor return (stack_popnumber(&bmachine.stack)); 474202719Sgabor} 475202719Sgabor 476202719Sgaborstatic __inline char * 477202719Sgaborpop_string(void) 478202719Sgabor{ 479202719Sgabor 480202719Sgabor return (stack_popstring(&bmachine.stack)); 481202719Sgabor} 482202719Sgabor 483202719Sgaborstatic __inline void 484202719Sgaborclear_stack(void) 485202719Sgabor{ 486202719Sgabor 487202719Sgabor stack_clear(&bmachine.stack); 488202719Sgabor} 489202719Sgabor 490202719Sgaborstatic __inline void 491202719Sgaborprint_stack(void) 492202719Sgabor{ 493202719Sgabor 494202719Sgabor stack_print(stdout, &bmachine.stack, "", bmachine.obase); 495202719Sgabor} 496202719Sgabor 497202719Sgaborstatic __inline void 498202719Sgaborprint_tos(void) 499202719Sgabor{ 500203443Sgabor struct value *value = tos(); 501202719Sgabor 502202719Sgabor if (value != NULL) { 503202719Sgabor print_value(stdout, value, "", bmachine.obase); 504202719Sgabor putchar('\n'); 505202719Sgabor } 506202719Sgabor else 507202719Sgabor warnx("stack empty"); 508202719Sgabor} 509202719Sgabor 510202719Sgaborstatic void 511202719Sgaborpop_print(void) 512202719Sgabor{ 513203443Sgabor struct value *value = pop(); 514202719Sgabor 515202719Sgabor if (value != NULL) { 516202719Sgabor switch (value->type) { 517202719Sgabor case BCODE_NONE: 518202719Sgabor break; 519202719Sgabor case BCODE_NUMBER: 520202719Sgabor normalize(value->u.num, 0); 521202719Sgabor print_ascii(stdout, value->u.num); 522202719Sgabor fflush(stdout); 523202719Sgabor break; 524202719Sgabor case BCODE_STRING: 525202719Sgabor fputs(value->u.string, stdout); 526202719Sgabor fflush(stdout); 527202719Sgabor break; 528202719Sgabor } 529202719Sgabor stack_free_value(value); 530202719Sgabor } 531202719Sgabor} 532202719Sgabor 533202719Sgaborstatic void 534202719Sgaborpop_printn(void) 535202719Sgabor{ 536203443Sgabor struct value *value = pop(); 537202719Sgabor 538202719Sgabor if (value != NULL) { 539202719Sgabor print_value(stdout, value, "", bmachine.obase); 540202719Sgabor fflush(stdout); 541202719Sgabor stack_free_value(value); 542202719Sgabor } 543202719Sgabor} 544202719Sgabor 545202719Sgaborstatic __inline void 546202719Sgabordup(void) 547202719Sgabor{ 548202719Sgabor 549202719Sgabor stack_dup(&bmachine.stack); 550202719Sgabor} 551202719Sgabor 552202719Sgaborstatic void 553202719Sgaborswap(void) 554202719Sgabor{ 555202719Sgabor 556202719Sgabor stack_swap(&bmachine.stack); 557202719Sgabor} 558202719Sgabor 559202719Sgaborstatic void 560202719Sgabordrop(void) 561202719Sgabor{ 562203443Sgabor struct value *v = pop(); 563202719Sgabor if (v != NULL) 564202719Sgabor stack_free_value(v); 565202719Sgabor} 566202719Sgabor 567202719Sgaborstatic void 568202719Sgaborget_scale(void) 569202719Sgabor{ 570203443Sgabor struct number *n; 571202719Sgabor 572202719Sgabor n = new_number(); 573202719Sgabor bn_check(BN_set_word(n->number, bmachine.scale)); 574202719Sgabor push_number(n); 575202719Sgabor} 576202719Sgabor 577202719Sgaborstatic void 578202719Sgaborset_scale(void) 579202719Sgabor{ 580203443Sgabor struct number *n; 581203443Sgabor u_long scale; 582202719Sgabor 583202719Sgabor n = pop_number(); 584202719Sgabor if (n != NULL) { 585244861Skevlo if (BN_is_negative(n->number)) 586202719Sgabor warnx("scale must be a nonnegative number"); 587202719Sgabor else { 588202719Sgabor scale = get_ulong(n); 589202719Sgabor if (scale != BN_MASK2 && scale <= UINT_MAX) 590202719Sgabor bmachine.scale = (u_int)scale; 591202719Sgabor else 592202719Sgabor warnx("scale too large"); 593202719Sgabor } 594202719Sgabor free_number(n); 595202719Sgabor } 596202719Sgabor} 597202719Sgabor 598202719Sgaborstatic void 599202719Sgaborget_obase(void) 600202719Sgabor{ 601203443Sgabor struct number *n; 602202719Sgabor 603202719Sgabor n = new_number(); 604202719Sgabor bn_check(BN_set_word(n->number, bmachine.obase)); 605202719Sgabor push_number(n); 606202719Sgabor} 607202719Sgabor 608202719Sgaborstatic void 609202719Sgaborset_obase(void) 610202719Sgabor{ 611203443Sgabor struct number *n; 612203443Sgabor u_long base; 613202719Sgabor 614202719Sgabor n = pop_number(); 615202719Sgabor if (n != NULL) { 616202719Sgabor base = get_ulong(n); 617202719Sgabor if (base != BN_MASK2 && base > 1 && base <= UINT_MAX) 618202719Sgabor bmachine.obase = (u_int)base; 619202719Sgabor else 620202719Sgabor warnx("output base must be a number greater than 1"); 621202719Sgabor free_number(n); 622202719Sgabor } 623202719Sgabor} 624202719Sgabor 625202719Sgaborstatic void 626202719Sgaborget_ibase(void) 627202719Sgabor{ 628203443Sgabor struct number *n; 629202719Sgabor 630202719Sgabor n = new_number(); 631202719Sgabor bn_check(BN_set_word(n->number, bmachine.ibase)); 632202719Sgabor push_number(n); 633202719Sgabor} 634202719Sgabor 635202719Sgaborstatic void 636202719Sgaborset_ibase(void) 637202719Sgabor{ 638203443Sgabor struct number *n; 639203443Sgabor u_long base; 640202719Sgabor 641202719Sgabor n = pop_number(); 642202719Sgabor if (n != NULL) { 643202719Sgabor base = get_ulong(n); 644202719Sgabor if (base != BN_MASK2 && 2 <= base && base <= 16) 645202719Sgabor bmachine.ibase = (u_int)base; 646202719Sgabor else 647202719Sgabor warnx("input base must be a number between 2 and 16 " 648202719Sgabor "(inclusive)"); 649202719Sgabor free_number(n); 650202719Sgabor } 651202719Sgabor} 652202719Sgabor 653202719Sgaborstatic void 654202719Sgaborstackdepth(void) 655202719Sgabor{ 656203443Sgabor struct number *n; 657203443Sgabor size_t i; 658202719Sgabor 659202719Sgabor i = stack_size(&bmachine.stack); 660202719Sgabor n = new_number(); 661202719Sgabor bn_check(BN_set_word(n->number, i)); 662202719Sgabor push_number(n); 663202719Sgabor} 664202719Sgabor 665202719Sgaborstatic void 666202719Sgaborpush_scale(void) 667202719Sgabor{ 668203443Sgabor struct number *n; 669203443Sgabor struct value *value; 670203443Sgabor u_int scale = 0; 671202719Sgabor 672202719Sgabor value = pop(); 673202719Sgabor if (value != NULL) { 674202719Sgabor switch (value->type) { 675202719Sgabor case BCODE_NONE: 676202719Sgabor return; 677202719Sgabor case BCODE_NUMBER: 678202719Sgabor scale = value->u.num->scale; 679202719Sgabor break; 680202719Sgabor case BCODE_STRING: 681202719Sgabor break; 682202719Sgabor } 683202719Sgabor stack_free_value(value); 684202719Sgabor n = new_number(); 685202719Sgabor bn_check(BN_set_word(n->number, scale)); 686202719Sgabor push_number(n); 687202719Sgabor } 688202719Sgabor} 689202719Sgabor 690202719Sgaborstatic u_int 691202719Sgaborcount_digits(const struct number *n) 692202719Sgabor{ 693203443Sgabor struct number *int_part, *fract_part; 694203443Sgabor u_int i; 695202719Sgabor 696202719Sgabor if (BN_is_zero(n->number)) 697265533Sdelphij return n->scale ? n->scale : 1; 698202719Sgabor 699202719Sgabor int_part = new_number(); 700202719Sgabor fract_part = new_number(); 701202719Sgabor fract_part->scale = n->scale; 702202719Sgabor split_number(n, int_part->number, fract_part->number); 703202719Sgabor 704202719Sgabor i = 0; 705202719Sgabor while (!BN_is_zero(int_part->number)) { 706202719Sgabor BN_div_word(int_part->number, 10); 707202719Sgabor i++; 708202719Sgabor } 709202719Sgabor free_number(int_part); 710202719Sgabor free_number(fract_part); 711202719Sgabor return (i + n->scale); 712202719Sgabor} 713202719Sgabor 714202719Sgaborstatic void 715202719Sgabornum_digits(void) 716202719Sgabor{ 717203443Sgabor struct number *n = NULL; 718203443Sgabor struct value *value; 719203443Sgabor size_t digits; 720202719Sgabor 721202719Sgabor value = pop(); 722202719Sgabor if (value != NULL) { 723202719Sgabor switch (value->type) { 724202719Sgabor case BCODE_NONE: 725202719Sgabor return; 726202719Sgabor case BCODE_NUMBER: 727202719Sgabor digits = count_digits(value->u.num); 728202719Sgabor n = new_number(); 729202719Sgabor bn_check(BN_set_word(n->number, digits)); 730202719Sgabor break; 731202719Sgabor case BCODE_STRING: 732202719Sgabor digits = strlen(value->u.string); 733202719Sgabor n = new_number(); 734202719Sgabor bn_check(BN_set_word(n->number, digits)); 735202719Sgabor break; 736202719Sgabor } 737202719Sgabor stack_free_value(value); 738202719Sgabor push_number(n); 739202719Sgabor } 740202719Sgabor} 741202719Sgabor 742202719Sgaborstatic void 743202719Sgaborto_ascii(void) 744202719Sgabor{ 745203443Sgabor struct number *n; 746203443Sgabor struct value *value; 747203443Sgabor char str[2]; 748202719Sgabor 749202719Sgabor value = pop(); 750202719Sgabor if (value != NULL) { 751202719Sgabor str[1] = '\0'; 752202719Sgabor switch (value->type) { 753202719Sgabor case BCODE_NONE: 754202719Sgabor return; 755202719Sgabor case BCODE_NUMBER: 756202719Sgabor n = value->u.num; 757202719Sgabor normalize(n, 0); 758202719Sgabor if (BN_num_bits(n->number) > 8) 759202719Sgabor bn_check(BN_mask_bits(n->number, 8)); 760202719Sgabor str[0] = (char)BN_get_word(n->number); 761202719Sgabor break; 762202719Sgabor case BCODE_STRING: 763202719Sgabor str[0] = value->u.string[0]; 764202719Sgabor break; 765202719Sgabor } 766202719Sgabor stack_free_value(value); 767202719Sgabor push_string(bstrdup(str)); 768202719Sgabor } 769202719Sgabor} 770202719Sgabor 771202719Sgaborstatic int 772202719Sgaborreadreg(void) 773202719Sgabor{ 774203443Sgabor int ch1, ch2, idx; 775202719Sgabor 776202719Sgabor idx = readch(); 777202719Sgabor if (idx == 0xff && bmachine.extended_regs) { 778202719Sgabor ch1 = readch(); 779202719Sgabor ch2 = readch(); 780202719Sgabor if (ch1 == EOF || ch2 == EOF) { 781202719Sgabor warnx("unexpected eof"); 782202719Sgabor idx = -1; 783202719Sgabor } else 784202719Sgabor idx = (ch1 << 8) + ch2 + UCHAR_MAX + 1; 785202719Sgabor } 786202719Sgabor if (idx < 0 || (unsigned)idx >= bmachine.reg_array_size) { 787202719Sgabor warnx("internal error: reg num = %d", idx); 788202719Sgabor idx = -1; 789202719Sgabor } 790202719Sgabor return (idx); 791202719Sgabor} 792202719Sgabor 793202719Sgaborstatic void 794202719Sgaborload(void) 795202719Sgabor{ 796203443Sgabor struct number *n; 797203443Sgabor struct value *v; 798203443Sgabor struct value copy; 799203443Sgabor int idx; 800202719Sgabor 801202719Sgabor idx = readreg(); 802202719Sgabor if (idx >= 0) { 803202719Sgabor v = stack_tos(&bmachine.reg[idx]); 804202719Sgabor if (v == NULL) { 805202719Sgabor n = new_number(); 806202719Sgabor bn_check(BN_zero(n->number)); 807202719Sgabor push_number(n); 808202719Sgabor } else 809202719Sgabor push(stack_dup_value(v, ©)); 810202719Sgabor } 811202719Sgabor} 812202719Sgabor 813202719Sgaborstatic void 814202719Sgaborstore(void) 815202719Sgabor{ 816203443Sgabor struct value *val; 817203443Sgabor int idx; 818202719Sgabor 819202719Sgabor idx = readreg(); 820202719Sgabor if (idx >= 0) { 821202719Sgabor val = pop(); 822202719Sgabor if (val == NULL) { 823202719Sgabor return; 824202719Sgabor } 825202719Sgabor stack_set_tos(&bmachine.reg[idx], val); 826202719Sgabor } 827202719Sgabor} 828202719Sgabor 829202719Sgaborstatic void 830202719Sgaborload_stack(void) 831202719Sgabor{ 832203443Sgabor struct stack *stack; 833203443Sgabor struct value *value; 834203443Sgabor int idx; 835202719Sgabor 836202719Sgabor idx = readreg(); 837202719Sgabor if (idx >= 0) { 838202719Sgabor stack = &bmachine.reg[idx]; 839202719Sgabor value = NULL; 840202719Sgabor if (stack_size(stack) > 0) { 841202719Sgabor value = stack_pop(stack); 842202719Sgabor } 843202719Sgabor if (value != NULL) 844202719Sgabor push(value); 845202719Sgabor else 846202719Sgabor warnx("stack register '%c' (0%o) is empty", 847202719Sgabor idx, idx); 848202719Sgabor } 849202719Sgabor} 850202719Sgabor 851202719Sgaborstatic void 852202719Sgaborstore_stack(void) 853202719Sgabor{ 854203443Sgabor struct value *value; 855203443Sgabor int idx; 856202719Sgabor 857202719Sgabor idx = readreg(); 858202719Sgabor if (idx >= 0) { 859202719Sgabor value = pop(); 860202719Sgabor if (value == NULL) 861202719Sgabor return; 862202719Sgabor stack_push(&bmachine.reg[idx], value); 863202719Sgabor } 864202719Sgabor} 865202719Sgabor 866202719Sgaborstatic void 867202719Sgaborload_array(void) 868202719Sgabor{ 869203443Sgabor struct number *inumber, *n; 870203443Sgabor struct stack *stack; 871203443Sgabor struct value *v; 872203443Sgabor struct value copy; 873203443Sgabor u_long idx; 874203443Sgabor int reg; 875202719Sgabor 876202719Sgabor reg = readreg(); 877202719Sgabor if (reg >= 0) { 878202719Sgabor inumber = pop_number(); 879202719Sgabor if (inumber == NULL) 880202719Sgabor return; 881202719Sgabor idx = get_ulong(inumber); 882244861Skevlo if (BN_is_negative(inumber->number)) 883202719Sgabor warnx("negative idx"); 884202719Sgabor else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) 885202719Sgabor warnx("idx too big"); 886202719Sgabor else { 887202719Sgabor stack = &bmachine.reg[reg]; 888202719Sgabor v = frame_retrieve(stack, idx); 889202719Sgabor if (v == NULL || v->type == BCODE_NONE) { 890202719Sgabor n = new_number(); 891202719Sgabor bn_check(BN_zero(n->number)); 892202719Sgabor push_number(n); 893202719Sgabor } 894202719Sgabor else 895202719Sgabor push(stack_dup_value(v, ©)); 896202719Sgabor } 897202719Sgabor free_number(inumber); 898202719Sgabor } 899202719Sgabor} 900202719Sgabor 901202719Sgaborstatic void 902202719Sgaborstore_array(void) 903202719Sgabor{ 904203443Sgabor struct number *inumber; 905203443Sgabor struct value *value; 906203443Sgabor struct stack *stack; 907203443Sgabor u_long idx; 908203443Sgabor int reg; 909202719Sgabor 910202719Sgabor reg = readreg(); 911202719Sgabor if (reg >= 0) { 912202719Sgabor inumber = pop_number(); 913202719Sgabor if (inumber == NULL) 914202719Sgabor return; 915202719Sgabor value = pop(); 916202719Sgabor if (value == NULL) { 917202719Sgabor free_number(inumber); 918202719Sgabor return; 919202719Sgabor } 920202719Sgabor idx = get_ulong(inumber); 921244861Skevlo if (BN_is_negative(inumber->number)) { 922202719Sgabor warnx("negative idx"); 923202719Sgabor stack_free_value(value); 924202719Sgabor } else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) { 925202719Sgabor warnx("idx too big"); 926202719Sgabor stack_free_value(value); 927202719Sgabor } else { 928202719Sgabor stack = &bmachine.reg[reg]; 929202719Sgabor frame_assign(stack, idx, value); 930202719Sgabor } 931202719Sgabor free_number(inumber); 932202719Sgabor } 933202719Sgabor} 934202719Sgabor 935202719Sgaborstatic void 936202719Sgaborpush_line(void) 937202719Sgabor{ 938202719Sgabor 939202719Sgabor push_string(read_string(&bmachine.readstack[bmachine.readsp])); 940202719Sgabor} 941202719Sgabor 942202719Sgaborstatic void 943202719Sgaborcomment(void) 944202719Sgabor{ 945202719Sgabor 946202719Sgabor free(readline()); 947202719Sgabor} 948202719Sgabor 949202719Sgaborstatic void 950202719Sgaborbexec(char *line) 951202719Sgabor{ 952202719Sgabor 953202719Sgabor system(line); 954202719Sgabor free(line); 955202719Sgabor} 956202719Sgabor 957202719Sgaborstatic void 958202719Sgaborbadd(void) 959202719Sgabor{ 960203443Sgabor struct number *a, *b, *r; 961202719Sgabor 962202719Sgabor a = pop_number(); 963202719Sgabor if (a == NULL) { 964202719Sgabor return; 965202719Sgabor } 966202719Sgabor b = pop_number(); 967202719Sgabor if (b == NULL) { 968202719Sgabor push_number(a); 969202719Sgabor return; 970202719Sgabor } 971202719Sgabor 972202719Sgabor r = new_number(); 973202719Sgabor r->scale = max(a->scale, b->scale); 974202719Sgabor if (r->scale > a->scale) 975202719Sgabor normalize(a, r->scale); 976202719Sgabor else if (r->scale > b->scale) 977202719Sgabor normalize(b, r->scale); 978202719Sgabor bn_check(BN_add(r->number, a->number, b->number)); 979202719Sgabor push_number(r); 980202719Sgabor free_number(a); 981202719Sgabor free_number(b); 982202719Sgabor} 983202719Sgabor 984202719Sgaborstatic void 985202719Sgaborbsub(void) 986202719Sgabor{ 987203443Sgabor struct number *a, *b, *r; 988202719Sgabor 989202719Sgabor a = pop_number(); 990202719Sgabor if (a == NULL) { 991202719Sgabor return; 992202719Sgabor } 993202719Sgabor b = pop_number(); 994202719Sgabor if (b == NULL) { 995202719Sgabor push_number(a); 996202719Sgabor return; 997202719Sgabor } 998202719Sgabor 999202719Sgabor r = new_number(); 1000202719Sgabor 1001202719Sgabor r->scale = max(a->scale, b->scale); 1002202719Sgabor if (r->scale > a->scale) 1003202719Sgabor normalize(a, r->scale); 1004202719Sgabor else if (r->scale > b->scale) 1005202719Sgabor normalize(b, r->scale); 1006202719Sgabor bn_check(BN_sub(r->number, b->number, a->number)); 1007202719Sgabor push_number(r); 1008202719Sgabor free_number(a); 1009202719Sgabor free_number(b); 1010202719Sgabor} 1011202719Sgabor 1012202719Sgaborvoid 1013244861Skevlobmul_number(struct number *r, struct number *a, struct number *b, u_int scale) 1014202719Sgabor{ 1015203443Sgabor BN_CTX *ctx; 1016202719Sgabor 1017202719Sgabor /* Create copies of the scales, since r might be equal to a or b */ 1018202719Sgabor u_int ascale = a->scale; 1019202719Sgabor u_int bscale = b->scale; 1020202719Sgabor u_int rscale = ascale + bscale; 1021202719Sgabor 1022202719Sgabor ctx = BN_CTX_new(); 1023202719Sgabor bn_checkp(ctx); 1024202719Sgabor bn_check(BN_mul(r->number, a->number, b->number, ctx)); 1025202719Sgabor BN_CTX_free(ctx); 1026202719Sgabor 1027244861Skevlo r->scale = rscale; 1028244861Skevlo if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) 1029244861Skevlo normalize(r, max(scale, max(ascale, bscale))); 1030202719Sgabor} 1031202719Sgabor 1032202719Sgaborstatic void 1033202719Sgaborbmul(void) 1034202719Sgabor{ 1035203443Sgabor struct number *a, *b, *r; 1036202719Sgabor 1037202719Sgabor a = pop_number(); 1038202719Sgabor if (a == NULL) { 1039202719Sgabor return; 1040202719Sgabor } 1041202719Sgabor b = pop_number(); 1042202719Sgabor if (b == NULL) { 1043202719Sgabor push_number(a); 1044202719Sgabor return; 1045202719Sgabor } 1046202719Sgabor 1047202719Sgabor r = new_number(); 1048244861Skevlo bmul_number(r, a, b, bmachine.scale); 1049202719Sgabor 1050202719Sgabor push_number(r); 1051202719Sgabor free_number(a); 1052202719Sgabor free_number(b); 1053202719Sgabor} 1054202719Sgabor 1055202719Sgaborstatic void 1056202719Sgaborbdiv(void) 1057202719Sgabor{ 1058203443Sgabor struct number *a, *b, *r; 1059203443Sgabor BN_CTX *ctx; 1060203443Sgabor u_int scale; 1061202719Sgabor 1062202719Sgabor a = pop_number(); 1063202719Sgabor if (a == NULL) { 1064202719Sgabor return; 1065202719Sgabor } 1066202719Sgabor b = pop_number(); 1067202719Sgabor if (b == NULL) { 1068202719Sgabor push_number(a); 1069202719Sgabor return; 1070202719Sgabor } 1071202719Sgabor 1072202719Sgabor r = new_number(); 1073202719Sgabor r->scale = bmachine.scale; 1074202719Sgabor scale = max(a->scale, b->scale); 1075202719Sgabor 1076202719Sgabor if (BN_is_zero(a->number)) 1077202719Sgabor warnx("divide by zero"); 1078202719Sgabor else { 1079202719Sgabor normalize(a, scale); 1080202719Sgabor normalize(b, scale + r->scale); 1081202719Sgabor 1082202719Sgabor ctx = BN_CTX_new(); 1083202719Sgabor bn_checkp(ctx); 1084202719Sgabor bn_check(BN_div(r->number, NULL, b->number, a->number, ctx)); 1085202719Sgabor BN_CTX_free(ctx); 1086202719Sgabor } 1087202719Sgabor push_number(r); 1088202719Sgabor free_number(a); 1089202719Sgabor free_number(b); 1090202719Sgabor} 1091202719Sgabor 1092202719Sgaborstatic void 1093202719Sgaborbmod(void) 1094202719Sgabor{ 1095203443Sgabor struct number *a, *b, *r; 1096203443Sgabor BN_CTX *ctx; 1097203443Sgabor u_int scale; 1098202719Sgabor 1099202719Sgabor a = pop_number(); 1100202719Sgabor if (a == NULL) { 1101202719Sgabor return; 1102202719Sgabor } 1103202719Sgabor b = pop_number(); 1104202719Sgabor if (b == NULL) { 1105202719Sgabor push_number(a); 1106202719Sgabor return; 1107202719Sgabor } 1108202719Sgabor 1109202719Sgabor r = new_number(); 1110202719Sgabor scale = max(a->scale, b->scale); 1111202719Sgabor r->scale = max(b->scale, a->scale + bmachine.scale); 1112202719Sgabor 1113202719Sgabor if (BN_is_zero(a->number)) 1114202719Sgabor warnx("remainder by zero"); 1115202719Sgabor else { 1116202719Sgabor normalize(a, scale); 1117202719Sgabor normalize(b, scale + bmachine.scale); 1118202719Sgabor 1119202719Sgabor ctx = BN_CTX_new(); 1120202719Sgabor bn_checkp(ctx); 1121202719Sgabor bn_check(BN_mod(r->number, b->number, a->number, ctx)); 1122202719Sgabor BN_CTX_free(ctx); 1123202719Sgabor } 1124202719Sgabor push_number(r); 1125202719Sgabor free_number(a); 1126202719Sgabor free_number(b); 1127202719Sgabor} 1128202719Sgabor 1129202719Sgaborstatic void 1130202719Sgaborbdivmod(void) 1131202719Sgabor{ 1132203443Sgabor struct number *a, *b, *rdiv, *rmod; 1133203443Sgabor BN_CTX *ctx; 1134203443Sgabor u_int scale; 1135202719Sgabor 1136202719Sgabor a = pop_number(); 1137202719Sgabor if (a == NULL) { 1138202719Sgabor return; 1139202719Sgabor } 1140202719Sgabor b = pop_number(); 1141202719Sgabor if (b == NULL) { 1142202719Sgabor push_number(a); 1143202719Sgabor return; 1144202719Sgabor } 1145202719Sgabor 1146202719Sgabor rdiv = new_number(); 1147202719Sgabor rmod = new_number(); 1148202719Sgabor rdiv->scale = bmachine.scale; 1149202719Sgabor rmod->scale = max(b->scale, a->scale + bmachine.scale); 1150202719Sgabor scale = max(a->scale, b->scale); 1151202719Sgabor 1152202719Sgabor if (BN_is_zero(a->number)) 1153202719Sgabor warnx("divide by zero"); 1154202719Sgabor else { 1155202719Sgabor normalize(a, scale); 1156202719Sgabor normalize(b, scale + bmachine.scale); 1157202719Sgabor 1158202719Sgabor ctx = BN_CTX_new(); 1159202719Sgabor bn_checkp(ctx); 1160202719Sgabor bn_check(BN_div(rdiv->number, rmod->number, 1161202719Sgabor b->number, a->number, ctx)); 1162202719Sgabor BN_CTX_free(ctx); 1163202719Sgabor } 1164202719Sgabor push_number(rdiv); 1165202719Sgabor push_number(rmod); 1166202719Sgabor free_number(a); 1167202719Sgabor free_number(b); 1168202719Sgabor} 1169202719Sgabor 1170202719Sgaborstatic void 1171202719Sgaborbexp(void) 1172202719Sgabor{ 1173265533Sdelphij struct number *a, *p; 1174265533Sdelphij struct number *r; 1175265533Sdelphij bool neg; 1176265533Sdelphij u_int rscale; 1177202719Sgabor 1178202719Sgabor p = pop_number(); 1179202719Sgabor if (p == NULL) { 1180202719Sgabor return; 1181202719Sgabor } 1182202719Sgabor a = pop_number(); 1183202719Sgabor if (a == NULL) { 1184202719Sgabor push_number(p); 1185202719Sgabor return; 1186202719Sgabor } 1187202719Sgabor 1188244861Skevlo if (p->scale != 0) { 1189244861Skevlo BIGNUM *i, *f; 1190244861Skevlo i = BN_new(); 1191244861Skevlo bn_checkp(i); 1192244861Skevlo f = BN_new(); 1193244861Skevlo bn_checkp(f); 1194244861Skevlo split_number(p, i, f); 1195244861Skevlo if (!BN_is_zero(f)) 1196265533Sdelphij warnx("Runtime warning: non-zero fractional part in exponent"); 1197244861Skevlo BN_free(i); 1198244861Skevlo BN_free(f); 1199244861Skevlo } 1200244861Skevlo 1201202719Sgabor normalize(p, 0); 1202202719Sgabor 1203202719Sgabor neg = false; 1204244861Skevlo if (BN_is_negative(p->number)) { 1205202719Sgabor neg = true; 1206202719Sgabor negate(p); 1207244861Skevlo rscale = bmachine.scale; 1208202719Sgabor } else { 1209202719Sgabor /* Posix bc says min(a.scale * b, max(a.scale, scale) */ 1210203443Sgabor u_long b; 1211203443Sgabor u_int m; 1212202719Sgabor 1213202719Sgabor b = BN_get_word(p->number); 1214202719Sgabor m = max(a->scale, bmachine.scale); 1215244861Skevlo rscale = a->scale * (u_int)b; 1216244861Skevlo if (rscale > m || (a->scale > 0 && (b == BN_MASK2 || 1217202719Sgabor b > UINT_MAX))) 1218244861Skevlo rscale = m; 1219202719Sgabor } 1220202719Sgabor 1221202719Sgabor if (BN_is_zero(p->number)) { 1222202719Sgabor r = new_number(); 1223202719Sgabor bn_check(BN_one(r->number)); 1224244861Skevlo normalize(r, rscale); 1225202719Sgabor } else { 1226244861Skevlo u_int ascale, mscale; 1227244861Skevlo 1228244861Skevlo ascale = a->scale; 1229202719Sgabor while (!BN_is_bit_set(p->number, 0)) { 1230244861Skevlo ascale *= 2; 1231244861Skevlo bmul_number(a, a, a, ascale); 1232202719Sgabor bn_check(BN_rshift1(p->number, p->number)); 1233202719Sgabor } 1234202719Sgabor 1235202719Sgabor r = dup_number(a); 1236202719Sgabor bn_check(BN_rshift1(p->number, p->number)); 1237202719Sgabor 1238244861Skevlo mscale = ascale; 1239202719Sgabor while (!BN_is_zero(p->number)) { 1240244861Skevlo ascale *= 2; 1241244861Skevlo bmul_number(a, a, a, ascale); 1242244861Skevlo if (BN_is_bit_set(p->number, 0)) { 1243244861Skevlo mscale += ascale; 1244244861Skevlo bmul_number(r, r, a, mscale); 1245244861Skevlo } 1246202719Sgabor bn_check(BN_rshift1(p->number, p->number)); 1247202719Sgabor } 1248202719Sgabor 1249202719Sgabor if (neg) { 1250203443Sgabor BN_CTX *ctx; 1251203443Sgabor BIGNUM *one; 1252202719Sgabor 1253202719Sgabor one = BN_new(); 1254202719Sgabor bn_checkp(one); 1255202719Sgabor bn_check(BN_one(one)); 1256202719Sgabor ctx = BN_CTX_new(); 1257202719Sgabor bn_checkp(ctx); 1258244861Skevlo scale_number(one, r->scale + rscale); 1259244861Skevlo 1260244861Skevlo if (BN_is_zero(r->number)) 1261244861Skevlo warnx("divide by zero"); 1262244861Skevlo else 1263244861Skevlo bn_check(BN_div(r->number, NULL, one, 1264244861Skevlo r->number, ctx)); 1265202719Sgabor BN_free(one); 1266202719Sgabor BN_CTX_free(ctx); 1267244861Skevlo r->scale = rscale; 1268202719Sgabor } else 1269244861Skevlo normalize(r, rscale); 1270202719Sgabor } 1271202719Sgabor push_number(r); 1272202719Sgabor free_number(a); 1273202719Sgabor free_number(p); 1274202719Sgabor} 1275202719Sgabor 1276202719Sgaborstatic bool 1277202719Sgaborbsqrt_stop(const BIGNUM *x, const BIGNUM *y, u_int *onecount) 1278202719Sgabor{ 1279203443Sgabor BIGNUM *r; 1280203443Sgabor bool ret; 1281202719Sgabor 1282202719Sgabor r = BN_new(); 1283202719Sgabor bn_checkp(r); 1284202719Sgabor bn_check(BN_sub(r, x, y)); 1285202719Sgabor if (BN_is_one(r)) 1286202719Sgabor (*onecount)++; 1287202719Sgabor ret = BN_is_zero(r); 1288202719Sgabor BN_free(r); 1289202719Sgabor return (ret || *onecount > 1); 1290202719Sgabor} 1291202719Sgabor 1292202719Sgaborstatic void 1293202719Sgaborbsqrt(void) 1294202719Sgabor{ 1295203443Sgabor struct number *n, *r; 1296203443Sgabor BIGNUM *x, *y; 1297203443Sgabor BN_CTX *ctx; 1298203443Sgabor u_int onecount, scale; 1299202719Sgabor 1300202719Sgabor onecount = 0; 1301202719Sgabor n = pop_number(); 1302202719Sgabor if (n == NULL) { 1303202719Sgabor return; 1304202719Sgabor } 1305202719Sgabor if (BN_is_zero(n->number)) { 1306202719Sgabor r = new_number(); 1307202719Sgabor push_number(r); 1308244861Skevlo } else if (BN_is_negative(n->number)) 1309202719Sgabor warnx("square root of negative number"); 1310202719Sgabor else { 1311202719Sgabor scale = max(bmachine.scale, n->scale); 1312202719Sgabor normalize(n, 2*scale); 1313202719Sgabor x = BN_dup(n->number); 1314202719Sgabor bn_checkp(x); 1315202719Sgabor bn_check(BN_rshift(x, x, BN_num_bits(x)/2)); 1316202719Sgabor y = BN_new(); 1317202719Sgabor bn_checkp(y); 1318202719Sgabor ctx = BN_CTX_new(); 1319202719Sgabor bn_checkp(ctx); 1320202719Sgabor for (;;) { 1321202719Sgabor bn_checkp(BN_copy(y, x)); 1322202719Sgabor bn_check(BN_div(x, NULL, n->number, x, ctx)); 1323202719Sgabor bn_check(BN_add(x, x, y)); 1324202719Sgabor bn_check(BN_rshift1(x, x)); 1325202719Sgabor if (bsqrt_stop(x, y, &onecount)) 1326202719Sgabor break; 1327202719Sgabor } 1328202719Sgabor r = bmalloc(sizeof(*r)); 1329202719Sgabor r->scale = scale; 1330202719Sgabor r->number = y; 1331202719Sgabor BN_free(x); 1332202719Sgabor BN_CTX_free(ctx); 1333202719Sgabor push_number(r); 1334202719Sgabor } 1335202719Sgabor 1336202719Sgabor free_number(n); 1337202719Sgabor} 1338202719Sgabor 1339202719Sgaborstatic void 1340202719Sgabornot(void) 1341202719Sgabor{ 1342203443Sgabor struct number *a; 1343202719Sgabor 1344202719Sgabor a = pop_number(); 1345202719Sgabor if (a == NULL) { 1346202719Sgabor return; 1347202719Sgabor } 1348202719Sgabor a->scale = 0; 1349202719Sgabor bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1)); 1350202719Sgabor push_number(a); 1351202719Sgabor} 1352202719Sgabor 1353202719Sgaborstatic void 1354202719Sgaborequal(void) 1355202719Sgabor{ 1356202719Sgabor 1357202719Sgabor compare(BCODE_EQUAL); 1358202719Sgabor} 1359202719Sgabor 1360202719Sgaborstatic void 1361202719Sgaborequal_numbers(void) 1362202719Sgabor{ 1363203443Sgabor struct number *a, *b, *r; 1364202719Sgabor 1365202719Sgabor a = pop_number(); 1366202719Sgabor if (a == NULL) { 1367202719Sgabor return; 1368202719Sgabor } 1369202719Sgabor b = pop_number(); 1370202719Sgabor if (b == NULL) { 1371202719Sgabor push_number(a); 1372202719Sgabor return; 1373202719Sgabor } 1374202719Sgabor r = new_number(); 1375202719Sgabor bn_check(BN_set_word(r->number, 1376202719Sgabor compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0)); 1377202719Sgabor push_number(r); 1378202719Sgabor} 1379202719Sgabor 1380202719Sgaborstatic void 1381202719Sgaborless_numbers(void) 1382202719Sgabor{ 1383203443Sgabor struct number *a, *b, *r; 1384202719Sgabor 1385202719Sgabor a = pop_number(); 1386202719Sgabor if (a == NULL) { 1387202719Sgabor return; 1388202719Sgabor } 1389202719Sgabor b = pop_number(); 1390202719Sgabor if (b == NULL) { 1391202719Sgabor push_number(a); 1392202719Sgabor return; 1393202719Sgabor } 1394202719Sgabor r = new_number(); 1395202719Sgabor bn_check(BN_set_word(r->number, 1396202719Sgabor compare_numbers(BCODE_LESS, a, b) ? 1 : 0)); 1397202719Sgabor push_number(r); 1398202719Sgabor} 1399202719Sgabor 1400202719Sgaborstatic void 1401202719Sgaborlesseq_numbers(void) 1402202719Sgabor{ 1403203443Sgabor struct number *a, *b, *r; 1404202719Sgabor 1405202719Sgabor a = pop_number(); 1406202719Sgabor if (a == NULL) { 1407202719Sgabor return; 1408202719Sgabor } 1409202719Sgabor b = pop_number(); 1410202719Sgabor if (b == NULL) { 1411202719Sgabor push_number(a); 1412202719Sgabor return; 1413202719Sgabor } 1414202719Sgabor r = new_number(); 1415202719Sgabor bn_check(BN_set_word(r->number, 1416202719Sgabor compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0)); 1417202719Sgabor push_number(r); 1418202719Sgabor} 1419202719Sgabor 1420202719Sgaborstatic void 1421202719Sgabornot_equal(void) 1422202719Sgabor{ 1423202719Sgabor 1424202719Sgabor compare(BCODE_NOT_EQUAL); 1425202719Sgabor} 1426202719Sgabor 1427202719Sgaborstatic void 1428202719Sgaborless(void) 1429202719Sgabor{ 1430202719Sgabor 1431202719Sgabor compare(BCODE_LESS); 1432202719Sgabor} 1433202719Sgabor 1434202719Sgaborstatic void 1435202719Sgabornot_compare(void) 1436202719Sgabor{ 1437203443Sgabor 1438202719Sgabor switch (readch()) { 1439202719Sgabor case '<': 1440202719Sgabor not_less(); 1441202719Sgabor break; 1442202719Sgabor case '>': 1443202719Sgabor not_greater(); 1444202719Sgabor break; 1445202719Sgabor case '=': 1446202719Sgabor not_equal(); 1447202719Sgabor break; 1448202719Sgabor default: 1449202719Sgabor unreadch(); 1450202719Sgabor bexec(readline()); 1451202719Sgabor break; 1452202719Sgabor } 1453202719Sgabor} 1454202719Sgabor 1455202719Sgaborstatic void 1456202719Sgabornot_less(void) 1457202719Sgabor{ 1458202719Sgabor 1459202719Sgabor compare(BCODE_NOT_LESS); 1460202719Sgabor} 1461202719Sgabor 1462202719Sgaborstatic void 1463202719Sgaborgreater(void) 1464202719Sgabor{ 1465202719Sgabor 1466202719Sgabor compare(BCODE_GREATER); 1467202719Sgabor} 1468202719Sgabor 1469202719Sgaborstatic void 1470202719Sgabornot_greater(void) 1471202719Sgabor{ 1472202719Sgabor 1473202719Sgabor compare(BCODE_NOT_GREATER); 1474202719Sgabor} 1475202719Sgabor 1476202719Sgaborstatic bool 1477202719Sgaborcompare_numbers(enum bcode_compare type, struct number *a, struct number *b) 1478202719Sgabor{ 1479203443Sgabor u_int scale; 1480203443Sgabor int cmp; 1481202719Sgabor 1482202719Sgabor scale = max(a->scale, b->scale); 1483202719Sgabor 1484202719Sgabor if (scale > a->scale) 1485202719Sgabor normalize(a, scale); 1486202719Sgabor else if (scale > b->scale) 1487202719Sgabor normalize(b, scale); 1488202719Sgabor 1489202719Sgabor cmp = BN_cmp(a->number, b->number); 1490202719Sgabor 1491202719Sgabor free_number(a); 1492202719Sgabor free_number(b); 1493202719Sgabor 1494202719Sgabor switch (type) { 1495202719Sgabor case BCODE_EQUAL: 1496202719Sgabor return (cmp == 0); 1497202719Sgabor case BCODE_NOT_EQUAL: 1498202719Sgabor return (cmp != 0); 1499202719Sgabor case BCODE_LESS: 1500202719Sgabor return (cmp < 0); 1501202719Sgabor case BCODE_NOT_LESS: 1502202719Sgabor return (cmp >= 0); 1503202719Sgabor case BCODE_GREATER: 1504202719Sgabor return (cmp > 0); 1505202719Sgabor case BCODE_NOT_GREATER: 1506202719Sgabor return (cmp <= 0); 1507202719Sgabor } 1508202719Sgabor return (false); 1509202719Sgabor} 1510202719Sgabor 1511202719Sgaborstatic void 1512202719Sgaborcompare(enum bcode_compare type) 1513202719Sgabor{ 1514203443Sgabor struct number *a, *b; 1515203443Sgabor struct value *v; 1516203443Sgabor int idx, elseidx; 1517203443Sgabor bool ok; 1518202719Sgabor 1519202719Sgabor elseidx = NO_ELSE; 1520202719Sgabor idx = readreg(); 1521202719Sgabor if (readch() == 'e') 1522202719Sgabor elseidx = readreg(); 1523202719Sgabor else 1524202719Sgabor unreadch(); 1525202719Sgabor 1526202719Sgabor a = pop_number(); 1527202719Sgabor if (a == NULL) 1528202719Sgabor return; 1529202719Sgabor b = pop_number(); 1530202719Sgabor if (b == NULL) { 1531202719Sgabor push_number(a); 1532202719Sgabor return; 1533202719Sgabor } 1534202719Sgabor 1535202719Sgabor ok = compare_numbers(type, a, b); 1536202719Sgabor 1537202719Sgabor if (!ok && elseidx != NO_ELSE) 1538202719Sgabor idx = elseidx; 1539202719Sgabor 1540202719Sgabor if (idx >= 0 && (ok || (!ok && elseidx != NO_ELSE))) { 1541202719Sgabor v = stack_tos(&bmachine.reg[idx]); 1542202719Sgabor if (v == NULL) 1543202719Sgabor warnx("register '%c' (0%o) is empty", idx, idx); 1544202719Sgabor else { 1545202719Sgabor switch(v->type) { 1546202719Sgabor case BCODE_NONE: 1547202719Sgabor warnx("register '%c' (0%o) is empty", idx, idx); 1548202719Sgabor break; 1549202719Sgabor case BCODE_NUMBER: 1550202719Sgabor warn("eval called with non-string argument"); 1551202719Sgabor break; 1552202719Sgabor case BCODE_STRING: 1553202719Sgabor eval_string(bstrdup(v->u.string)); 1554202719Sgabor break; 1555202719Sgabor } 1556202719Sgabor } 1557202719Sgabor } 1558202719Sgabor} 1559202719Sgabor 1560202719Sgabor 1561202719Sgaborstatic void 1562202719Sgabornop(void) 1563202719Sgabor{ 1564203443Sgabor 1565202719Sgabor} 1566202719Sgabor 1567202719Sgaborstatic void 1568202719Sgaborquit(void) 1569202719Sgabor{ 1570203443Sgabor 1571202719Sgabor if (bmachine.readsp < 2) 1572202719Sgabor exit(0); 1573202719Sgabor src_free(); 1574202719Sgabor bmachine.readsp--; 1575202719Sgabor src_free(); 1576202719Sgabor bmachine.readsp--; 1577202719Sgabor} 1578202719Sgabor 1579202719Sgaborstatic void 1580202719SgaborquitN(void) 1581202719Sgabor{ 1582203443Sgabor struct number *n; 1583203443Sgabor u_long i; 1584202719Sgabor 1585202719Sgabor n = pop_number(); 1586202719Sgabor if (n == NULL) 1587202719Sgabor return; 1588202719Sgabor i = get_ulong(n); 1589202719Sgabor free_number(n); 1590202719Sgabor if (i == BN_MASK2 || i == 0) 1591202719Sgabor warnx("Q command requires a number >= 1"); 1592202719Sgabor else if (bmachine.readsp < i) 1593202719Sgabor warnx("Q command argument exceeded string execution depth"); 1594202719Sgabor else { 1595202719Sgabor while (i-- > 0) { 1596202719Sgabor src_free(); 1597202719Sgabor bmachine.readsp--; 1598202719Sgabor } 1599202719Sgabor } 1600202719Sgabor} 1601202719Sgabor 1602202719Sgaborstatic void 1603202719SgaborskipN(void) 1604202719Sgabor{ 1605203443Sgabor struct number *n; 1606203443Sgabor u_long i; 1607202719Sgabor 1608202719Sgabor n = pop_number(); 1609202719Sgabor if (n == NULL) 1610202719Sgabor return; 1611202719Sgabor i = get_ulong(n); 1612202719Sgabor if (i == BN_MASK2) 1613202719Sgabor warnx("J command requires a number >= 0"); 1614202719Sgabor else if (i > 0 && bmachine.readsp < i) 1615202719Sgabor warnx("J command argument exceeded string execution depth"); 1616202719Sgabor else { 1617202719Sgabor while (i-- > 0) { 1618202719Sgabor src_free(); 1619202719Sgabor bmachine.readsp--; 1620202719Sgabor } 1621202719Sgabor skip_until_mark(); 1622202719Sgabor } 1623202719Sgabor} 1624202719Sgabor 1625202719Sgaborstatic void 1626202719Sgaborskip_until_mark(void) 1627202719Sgabor{ 1628202719Sgabor 1629202719Sgabor for (;;) { 1630203438Sgabor switch (readch()) { 1631202719Sgabor case 'M': 1632202719Sgabor return; 1633202719Sgabor case EOF: 1634202719Sgabor errx(1, "mark not found"); 1635202719Sgabor return; 1636202719Sgabor case 'l': 1637202719Sgabor case 'L': 1638202719Sgabor case 's': 1639202719Sgabor case 'S': 1640202719Sgabor case ':': 1641202719Sgabor case ';': 1642202719Sgabor case '<': 1643202719Sgabor case '>': 1644202719Sgabor case '=': 1645202719Sgabor readreg(); 1646202719Sgabor if (readch() == 'e') 1647202719Sgabor readreg(); 1648202719Sgabor else 1649202719Sgabor unreadch(); 1650202719Sgabor break; 1651202719Sgabor case '[': 1652202719Sgabor free(read_string(&bmachine.readstack[bmachine.readsp])); 1653202719Sgabor break; 1654202719Sgabor case '!': 1655203438Sgabor switch (readch()) { 1656202719Sgabor case '<': 1657202719Sgabor case '>': 1658202719Sgabor case '=': 1659202719Sgabor readreg(); 1660202719Sgabor if (readch() == 'e') 1661202719Sgabor readreg(); 1662202719Sgabor else 1663202719Sgabor unreadch(); 1664202719Sgabor break; 1665202719Sgabor default: 1666202719Sgabor free(readline()); 1667202719Sgabor break; 1668202719Sgabor } 1669202719Sgabor break; 1670202719Sgabor default: 1671202719Sgabor break; 1672202719Sgabor } 1673202719Sgabor } 1674202719Sgabor} 1675202719Sgabor 1676202719Sgaborstatic void 1677202719Sgaborparse_number(void) 1678202719Sgabor{ 1679202719Sgabor 1680202719Sgabor unreadch(); 1681202719Sgabor push_number(readnumber(&bmachine.readstack[bmachine.readsp], 1682202719Sgabor bmachine.ibase)); 1683202719Sgabor} 1684202719Sgabor 1685202719Sgaborstatic void 1686202719Sgaborunknown(void) 1687202719Sgabor{ 1688202719Sgabor int ch = bmachine.readstack[bmachine.readsp].lastchar; 1689202719Sgabor warnx("%c (0%o) is unimplemented", ch, ch); 1690202719Sgabor} 1691202719Sgabor 1692202719Sgaborstatic void 1693202719Sgaboreval_string(char *p) 1694202719Sgabor{ 1695203443Sgabor int ch; 1696202719Sgabor 1697202719Sgabor if (bmachine.readsp > 0) { 1698202719Sgabor /* Check for tail call. Do not recurse in that case. */ 1699202719Sgabor ch = readch(); 1700202719Sgabor if (ch == EOF) { 1701202719Sgabor src_free(); 1702202719Sgabor src_setstring(&bmachine.readstack[bmachine.readsp], p); 1703202719Sgabor return; 1704202719Sgabor } else 1705202719Sgabor unreadch(); 1706202719Sgabor } 1707202719Sgabor if (bmachine.readsp == bmachine.readstack_sz - 1) { 1708202719Sgabor size_t newsz = bmachine.readstack_sz * 2; 1709202719Sgabor struct source *stack; 1710202719Sgabor stack = realloc(bmachine.readstack, newsz * 1711202719Sgabor sizeof(struct source)); 1712202719Sgabor if (stack == NULL) 1713202719Sgabor err(1, "recursion too deep"); 1714202719Sgabor bmachine.readstack_sz = newsz; 1715202719Sgabor bmachine.readstack = stack; 1716202719Sgabor } 1717202719Sgabor src_setstring(&bmachine.readstack[++bmachine.readsp], p); 1718202719Sgabor} 1719202719Sgabor 1720202719Sgaborstatic void 1721202719Sgaboreval_line(void) 1722202719Sgabor{ 1723202719Sgabor /* Always read from stdin */ 1724203443Sgabor struct source in; 1725203443Sgabor char *p; 1726202719Sgabor 1727202719Sgabor clearerr(stdin); 1728202719Sgabor src_setstream(&in, stdin); 1729202719Sgabor p = (*in.vtable->readline)(&in); 1730202719Sgabor eval_string(p); 1731202719Sgabor} 1732202719Sgabor 1733202719Sgaborstatic void 1734202719Sgaboreval_tos(void) 1735202719Sgabor{ 1736203443Sgabor char *p; 1737202719Sgabor 1738202719Sgabor p = pop_string(); 1739202719Sgabor if (p == NULL) 1740202719Sgabor return; 1741202719Sgabor eval_string(p); 1742202719Sgabor} 1743202719Sgabor 1744202719Sgaborvoid 1745202719Sgaboreval(void) 1746202719Sgabor{ 1747203443Sgabor int ch; 1748202719Sgabor 1749202719Sgabor for (;;) { 1750202719Sgabor ch = readch(); 1751202719Sgabor if (ch == EOF) { 1752202719Sgabor if (bmachine.readsp == 0) 1753202719Sgabor return; 1754202719Sgabor src_free(); 1755202719Sgabor bmachine.readsp--; 1756202719Sgabor continue; 1757202719Sgabor } 1758202719Sgabor#ifdef DEBUGGING 1759202719Sgabor fprintf(stderr, "# %c\n", ch); 1760202719Sgabor stack_print(stderr, &bmachine.stack, "* ", 1761202719Sgabor bmachine.obase); 1762202719Sgabor fprintf(stderr, "%zd =>\n", bmachine.readsp); 1763202719Sgabor#endif 1764202719Sgabor 1765202719Sgabor if (0 <= ch && ch < (signed)UCHAR_MAX) 1766202719Sgabor (*jump_table[ch])(); 1767202719Sgabor else 1768202719Sgabor warnx("internal error: opcode %d", ch); 1769202719Sgabor 1770202719Sgabor#ifdef DEBUGGING 1771202719Sgabor stack_print(stderr, &bmachine.stack, "* ", 1772202719Sgabor bmachine.obase); 1773202719Sgabor fprintf(stderr, "%zd ==\n", bmachine.readsp); 1774202719Sgabor#endif 1775202719Sgabor } 1776202719Sgabor} 1777