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