xref: /freebsd-14.2/usr.bin/dc/bcode.c (revision fdf1f88b)
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, &copy));
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, &copy));
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