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