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