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