bcode.c revision 203438
1202719Sgabor/*	$OpenBSD: bcode.c,v 1.40 2009/10/27 23:59:37 deraadt 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: head/usr.bin/dc/bcode.c 203438 2010-02-03 19:13:41Z gabor $");
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
32202719SgaborBIGNUM		zero;
33202719Sgabor
34202719Sgabor#define __inline
35202719Sgabor
36202719Sgabor#define MAX_ARRAY_INDEX		2048
37202719Sgabor#define READSTACK_SIZE		8
38202719Sgabor
39202719Sgabor#define NO_ELSE			-2	/* -1 is EOF */
40202719Sgabor#define REG_ARRAY_SIZE_SMALL	(UCHAR_MAX + 1)
41202719Sgabor#define REG_ARRAY_SIZE_BIG	(UCHAR_MAX + 1 + USHRT_MAX + 1)
42202719Sgabor
43202719Sgaborstruct bmachine {
44202719Sgabor	struct stack		 stack;
45202719Sgabor	u_int			 scale;
46202719Sgabor	u_int			 obase;
47202719Sgabor	u_int			 ibase;
48202719Sgabor	size_t			 readsp;
49202719Sgabor	bool			 extended_regs;
50202719Sgabor	size_t			 reg_array_size;
51202719Sgabor	struct stack		*reg;
52202719Sgabor	volatile sig_atomic_t	 interrupted;
53202719Sgabor	struct source		*readstack;
54202719Sgabor	size_t			 readstack_sz;
55202719Sgabor};
56202719Sgabor
57202719Sgaborstatic struct bmachine	 bmachine;
58202719Sgaborstatic void		 sighandler(int);
59202719Sgabor
60202719Sgaborstatic __inline int	 readch(void);
61202719Sgaborstatic __inline void	 unreadch(void);
62202719Sgaborstatic __inline char	*readline(void);
63202719Sgaborstatic __inline void	 src_free(void);
64202719Sgabor
65202719Sgaborstatic __inline u_int	 max(u_int, u_int);
66202719Sgaborstatic u_long		 get_ulong(struct number *);
67202719Sgabor
68202719Sgaborstatic __inline void	 push_number(struct number *);
69202719Sgaborstatic __inline void	 push_string(char *);
70202719Sgaborstatic __inline void	 push(struct value *);
71202719Sgaborstatic __inline struct value *tos(void);
72202719Sgaborstatic __inline struct number	*pop_number(void);
73202719Sgaborstatic __inline char	*pop_string(void);
74202719Sgaborstatic __inline void	 clear_stack(void);
75202719Sgaborstatic __inline void	 print_tos(void);
76202719Sgaborstatic void		 pop_print(void);
77202719Sgaborstatic void		 pop_printn(void);
78202719Sgaborstatic __inline void	 print_stack(void);
79202719Sgaborstatic __inline void	 dup(void);
80202719Sgaborstatic void		 swap(void);
81202719Sgaborstatic void		 drop(void);
82202719Sgabor
83202719Sgaborstatic void		 get_scale(void);
84202719Sgaborstatic void		 set_scale(void);
85202719Sgaborstatic void		 get_obase(void);
86202719Sgaborstatic void		 set_obase(void);
87202719Sgaborstatic void		 get_ibase(void);
88202719Sgaborstatic void		 set_ibase(void);
89202719Sgaborstatic void		 stackdepth(void);
90202719Sgaborstatic void		 push_scale(void);
91202719Sgaborstatic u_int		 count_digits(const struct number *);
92202719Sgaborstatic void		 num_digits(void);
93202719Sgaborstatic void		 to_ascii(void);
94202719Sgaborstatic void		 push_line(void);
95202719Sgaborstatic void		 comment(void);
96202719Sgaborstatic void		 bexec(char *);
97202719Sgaborstatic void		 badd(void);
98202719Sgaborstatic void		 bsub(void);
99202719Sgaborstatic void		 bmul(void);
100202719Sgaborstatic void		 bdiv(void);
101202719Sgaborstatic void		 bmod(void);
102202719Sgaborstatic void		 bdivmod(void);
103202719Sgaborstatic void		 bexp(void);
104202719Sgaborstatic bool		 bsqrt_stop(const BIGNUM *, const BIGNUM *, u_int *);
105202719Sgaborstatic void		 bsqrt(void);
106202719Sgaborstatic void		 not(void);
107202719Sgaborstatic void		 equal_numbers(void);
108202719Sgaborstatic void		 less_numbers(void);
109202719Sgaborstatic void		 lesseq_numbers(void);
110202719Sgaborstatic void		 equal(void);
111202719Sgaborstatic void		 not_equal(void);
112202719Sgaborstatic void		 less(void);
113202719Sgaborstatic void		 not_less(void);
114202719Sgaborstatic void		 greater(void);
115202719Sgaborstatic void		 not_greater(void);
116202719Sgaborstatic void		 not_compare(void);
117202719Sgaborstatic bool		 compare_numbers(enum bcode_compare, struct number *,
118202719Sgabor			     struct number *);
119202719Sgaborstatic void		 compare(enum bcode_compare);
120202719Sgaborstatic int		 readreg(void);
121202719Sgaborstatic void		 load(void);
122202719Sgaborstatic void		 store(void);
123202719Sgaborstatic void		 load_stack(void);
124202719Sgaborstatic void		 store_stack(void);
125202719Sgaborstatic void		 load_array(void);
126202719Sgaborstatic void		 store_array(void);
127202719Sgaborstatic void		 nop(void);
128202719Sgaborstatic void		 quit(void);
129202719Sgaborstatic void		 quitN(void);
130202719Sgaborstatic void		 skipN(void);
131202719Sgaborstatic void		 skip_until_mark(void);
132202719Sgaborstatic void		 parse_number(void);
133202719Sgaborstatic void		 unknown(void);
134202719Sgaborstatic void		 eval_string(char *);
135202719Sgaborstatic void		 eval_line(void);
136202719Sgaborstatic void		 eval_tos(void);
137202719Sgabor
138202719Sgabor
139202719Sgabortypedef void		(*opcode_function)(void);
140202719Sgabor
141202719Sgaborstruct jump_entry {
142202719Sgabor	u_char		 ch;
143202719Sgabor	opcode_function	 f;
144202719Sgabor};
145202719Sgabor
146202719Sgaborstatic opcode_function jump_table[UCHAR_MAX];
147202719Sgabor
148202719Sgaborstatic const struct jump_entry jump_table_data[] = {
149202719Sgabor	{ ' ',	nop		},
150202719Sgabor	{ '!',	not_compare	},
151202719Sgabor	{ '#',	comment		},
152202719Sgabor	{ '%',	bmod		},
153202719Sgabor	{ '(',	less_numbers	},
154202719Sgabor	{ '*',	bmul		},
155202719Sgabor	{ '+',	badd		},
156202719Sgabor	{ '-',	bsub		},
157202719Sgabor	{ '.',	parse_number	},
158202719Sgabor	{ '/',	bdiv		},
159202719Sgabor	{ '0',	parse_number	},
160202719Sgabor	{ '1',	parse_number	},
161202719Sgabor	{ '2',	parse_number	},
162202719Sgabor	{ '3',	parse_number	},
163202719Sgabor	{ '4',	parse_number	},
164202719Sgabor	{ '5',	parse_number	},
165202719Sgabor	{ '6',	parse_number	},
166202719Sgabor	{ '7',	parse_number	},
167202719Sgabor	{ '8',	parse_number	},
168202719Sgabor	{ '9',	parse_number	},
169202719Sgabor	{ ':',	store_array	},
170202719Sgabor	{ ';',	load_array	},
171202719Sgabor	{ '<',	less		},
172202719Sgabor	{ '=',	equal		},
173202719Sgabor	{ '>',	greater		},
174202719Sgabor	{ '?',	eval_line	},
175202719Sgabor	{ 'A',	parse_number	},
176202719Sgabor	{ 'B',	parse_number	},
177202719Sgabor	{ 'C',	parse_number	},
178202719Sgabor	{ 'D',	parse_number	},
179202719Sgabor	{ 'E',	parse_number	},
180202719Sgabor	{ 'F',	parse_number	},
181202719Sgabor	{ 'G',	equal_numbers	},
182202719Sgabor	{ 'I',	get_ibase	},
183202719Sgabor	{ 'J',	skipN		},
184202719Sgabor	{ 'K',	get_scale	},
185202719Sgabor	{ 'L',	load_stack	},
186202719Sgabor	{ 'M',	nop		},
187202719Sgabor	{ 'N',	not		},
188202719Sgabor	{ 'O',	get_obase	},
189202719Sgabor	{ 'P',	pop_print	},
190202719Sgabor	{ 'Q',	quitN		},
191202719Sgabor	{ 'R',	drop		},
192202719Sgabor	{ 'S',	store_stack	},
193202719Sgabor	{ 'X',	push_scale	},
194202719Sgabor	{ 'Z',	num_digits	},
195202719Sgabor	{ '[',	push_line	},
196202719Sgabor	{ '\f',	nop		},
197202719Sgabor	{ '\n',	nop		},
198202719Sgabor	{ '\r',	nop		},
199202719Sgabor	{ '\t',	nop		},
200202719Sgabor	{ '^',	bexp		},
201202719Sgabor	{ '_',	parse_number	},
202202719Sgabor	{ 'a',	to_ascii	},
203202719Sgabor	{ 'c',	clear_stack	},
204202719Sgabor	{ 'd',	dup		},
205202719Sgabor	{ 'f',	print_stack	},
206202719Sgabor	{ 'i',	set_ibase	},
207202719Sgabor	{ 'k',	set_scale	},
208202719Sgabor	{ 'l',	load		},
209202719Sgabor	{ 'n',	pop_printn	},
210202719Sgabor	{ 'o',	set_obase	},
211202719Sgabor	{ 'p',	print_tos	},
212202719Sgabor	{ 'q',	quit		},
213202719Sgabor	{ 'r',	swap		},
214202719Sgabor	{ 's',	store		},
215202719Sgabor	{ 'v',	bsqrt		},
216202719Sgabor	{ 'x',	eval_tos	},
217202719Sgabor	{ 'z',	stackdepth	},
218202719Sgabor	{ '{',	lesseq_numbers	},
219202719Sgabor	{ '~',	bdivmod		}
220202719Sgabor};
221202719Sgabor
222202719Sgabor#define JUMP_TABLE_DATA_SIZE \
223202719Sgabor	(sizeof(jump_table_data)/sizeof(jump_table_data[0]))
224202719Sgabor
225202719Sgaborstatic void
226202719Sgaborsighandler(int ignored)
227202719Sgabor{
228202719Sgabor
229202719Sgabor	switch (ignored)
230202719Sgabor	{
231202719Sgabor	default:
232202719Sgabor		bmachine.interrupted = true;
233202719Sgabor	}
234202719Sgabor}
235202719Sgabor
236202719Sgaborvoid
237202719Sgaborinit_bmachine(bool extended_registers)
238202719Sgabor{
239202719Sgabor	unsigned int	 i;
240202719Sgabor
241202719Sgabor	bmachine.extended_regs = extended_registers;
242202719Sgabor	bmachine.reg_array_size = bmachine.extended_regs ?
243202719Sgabor	    REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL;
244202719Sgabor
245202719Sgabor	bmachine.reg = calloc(bmachine.reg_array_size,
246202719Sgabor	    sizeof(bmachine.reg[0]));
247202719Sgabor	if (bmachine.reg == NULL)
248202719Sgabor		err(1, NULL);
249202719Sgabor
250202719Sgabor	for (i = 0; i < UCHAR_MAX; i++)
251202719Sgabor		jump_table[i] = unknown;
252202719Sgabor	for (i = 0; i < JUMP_TABLE_DATA_SIZE; i++)
253202719Sgabor		jump_table[jump_table_data[i].ch] = jump_table_data[i].f;
254202719Sgabor
255202719Sgabor	stack_init(&bmachine.stack);
256202719Sgabor
257202719Sgabor	for (i = 0; i < bmachine.reg_array_size; i++)
258202719Sgabor		stack_init(&bmachine.reg[i]);
259202719Sgabor
260202719Sgabor	bmachine.readstack_sz = READSTACK_SIZE;
261202719Sgabor	bmachine.readstack = calloc(sizeof(struct source),
262202719Sgabor	    bmachine.readstack_sz);
263202719Sgabor	if (bmachine.readstack == NULL)
264202719Sgabor		err(1, NULL);
265202719Sgabor	bmachine.obase = bmachine.ibase = 10;
266202719Sgabor	BN_init(&zero);
267202719Sgabor	bn_check(BN_zero(&zero));
268202719Sgabor	signal(SIGINT, sighandler);
269202719Sgabor}
270202719Sgabor
271202719Sgabor/* Reset the things needed before processing a (new) file */
272202719Sgaborvoid
273202719Sgaborreset_bmachine(struct source *src)
274202719Sgabor{
275202719Sgabor
276202719Sgabor	bmachine.readsp = 0;
277202719Sgabor	bmachine.readstack[0] = *src;
278202719Sgabor}
279202719Sgabor
280202719Sgaborstatic __inline int
281202719Sgaborreadch(void)
282202719Sgabor{
283202719Sgabor	struct source	*src = &bmachine.readstack[bmachine.readsp];
284202719Sgabor
285202719Sgabor	return (src->vtable->readchar(src));
286202719Sgabor}
287202719Sgabor
288202719Sgaborstatic __inline void
289202719Sgaborunreadch(void)
290202719Sgabor{
291202719Sgabor	struct source	*src = &bmachine.readstack[bmachine.readsp];
292202719Sgabor
293202719Sgabor	src->vtable->unreadchar(src);
294202719Sgabor}
295202719Sgabor
296202719Sgaborstatic __inline char *
297202719Sgaborreadline(void)
298202719Sgabor{
299202719Sgabor	struct source	*src = &bmachine.readstack[bmachine.readsp];
300202719Sgabor
301202719Sgabor	return (src->vtable->readline(src));
302202719Sgabor}
303202719Sgabor
304202719Sgaborstatic __inline void
305202719Sgaborsrc_free(void)
306202719Sgabor{
307202719Sgabor	struct source	*src = &bmachine.readstack[bmachine.readsp];
308202719Sgabor
309202719Sgabor	src->vtable->free(src);
310202719Sgabor}
311202719Sgabor
312202719Sgabor#ifdef DEBUGGING
313202719Sgaborvoid
314202719Sgaborpn(const char *str, const struct number *n)
315202719Sgabor{
316202719Sgabor	char	*p = BN_bn2dec(n->number);
317202719Sgabor
318202719Sgabor	if (p == NULL)
319202719Sgabor		err(1, "BN_bn2dec failed");
320202719Sgabor	fputs(str, stderr);
321202719Sgabor	fprintf(stderr, " %s (%u)\n" , p, n->scale);
322202719Sgabor	OPENSSL_free(p);
323202719Sgabor}
324202719Sgabor
325202719Sgaborvoid
326202719Sgaborpbn(const char *str, const BIGNUM *n)
327202719Sgabor{
328202719Sgabor	char	*p = BN_bn2dec(n);
329202719Sgabor
330202719Sgabor	if (p == NULL)
331202719Sgabor		err(1, "BN_bn2dec failed");
332202719Sgabor	fputs(str, stderr);
333202719Sgabor	fprintf(stderr, " %s\n", p);
334202719Sgabor	OPENSSL_free(p);
335202719Sgabor}
336202719Sgabor
337202719Sgabor#endif
338202719Sgabor
339202719Sgaborstatic __inline u_int
340202719Sgabormax(u_int a, u_int b)
341202719Sgabor{
342202719Sgabor
343202719Sgabor	return (a > b ? a : b);
344202719Sgabor}
345202719Sgabor
346202719Sgaborstatic unsigned long factors[] = {
347202719Sgabor	0, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
348202719Sgabor	100000000, 1000000000
349202719Sgabor};
350202719Sgabor
351202719Sgaborvoid
352202719Sgaborscale_number(BIGNUM *n, int s)
353202719Sgabor{
354202719Sgabor	unsigned int	 abs_scale;
355202719Sgabor
356202719Sgabor	if (s == 0)
357202719Sgabor		return;
358202719Sgabor
359202719Sgabor	abs_scale = s > 0 ? s : -s;
360202719Sgabor
361202719Sgabor	if (abs_scale < sizeof(factors)/sizeof(factors[0])) {
362202719Sgabor		if (s > 0)
363202719Sgabor			bn_check(BN_mul_word(n, factors[abs_scale]));
364202719Sgabor		else
365202719Sgabor			BN_div_word(n, factors[abs_scale]);
366202719Sgabor	} else {
367202719Sgabor		BIGNUM	*a, *p;
368202719Sgabor		BN_CTX	*ctx;
369202719Sgabor
370202719Sgabor		a = BN_new();
371202719Sgabor		bn_checkp(a);
372202719Sgabor		p = BN_new();
373202719Sgabor		bn_checkp(p);
374202719Sgabor		ctx = BN_CTX_new();
375202719Sgabor		bn_checkp(ctx);
376202719Sgabor
377202719Sgabor		bn_check(BN_set_word(a, 10));
378202719Sgabor		bn_check(BN_set_word(p, abs_scale));
379202719Sgabor		bn_check(BN_exp(a, a, p, ctx));
380202719Sgabor		if (s > 0)
381202719Sgabor			bn_check(BN_mul(n, n, a, ctx));
382202719Sgabor		else
383202719Sgabor			bn_check(BN_div(n, NULL, n, a, ctx));
384202719Sgabor		BN_CTX_free(ctx);
385202719Sgabor		BN_free(a);
386202719Sgabor		BN_free(p);
387202719Sgabor	}
388202719Sgabor}
389202719Sgabor
390202719Sgaborvoid
391202719Sgaborsplit_number(const struct number *n, BIGNUM *i, BIGNUM *f)
392202719Sgabor{
393202719Sgabor	u_long	 rem;
394202719Sgabor
395202719Sgabor	bn_checkp(BN_copy(i, n->number));
396202719Sgabor
397202719Sgabor	if (n->scale == 0 && f != NULL)
398202719Sgabor		bn_check(BN_zero(f));
399202719Sgabor	else if (n->scale < sizeof(factors)/sizeof(factors[0])) {
400202719Sgabor		rem = BN_div_word(i, factors[n->scale]);
401202719Sgabor		if (f != NULL)
402202719Sgabor			bn_check(BN_set_word(f, rem));
403202719Sgabor	} else {
404202719Sgabor		BIGNUM	*a, *p;
405202719Sgabor		BN_CTX	*ctx;
406202719Sgabor
407202719Sgabor		a = BN_new();
408202719Sgabor		bn_checkp(a);
409202719Sgabor		p = BN_new();
410202719Sgabor		bn_checkp(p);
411202719Sgabor		ctx = BN_CTX_new();
412202719Sgabor		bn_checkp(ctx);
413202719Sgabor
414202719Sgabor		bn_check(BN_set_word(a, 10));
415202719Sgabor		bn_check(BN_set_word(p, n->scale));
416202719Sgabor		bn_check(BN_exp(a, a, p, ctx));
417202719Sgabor		bn_check(BN_div(i, f, n->number, a, ctx));
418202719Sgabor		BN_CTX_free(ctx);
419202719Sgabor		BN_free(a);
420202719Sgabor		BN_free(p);
421202719Sgabor	}
422202719Sgabor}
423202719Sgabor
424202719Sgabor__inline void
425202719Sgabornormalize(struct number *n, u_int s)
426202719Sgabor{
427202719Sgabor
428202719Sgabor	scale_number(n->number, s - n->scale);
429202719Sgabor	n->scale = s;
430202719Sgabor}
431202719Sgabor
432202719Sgaborstatic u_long
433202719Sgaborget_ulong(struct number *n)
434202719Sgabor{
435202719Sgabor
436202719Sgabor	normalize(n, 0);
437202719Sgabor	return (BN_get_word(n->number));
438202719Sgabor}
439202719Sgabor
440202719Sgaborvoid
441202719Sgabornegate(struct number *n)
442202719Sgabor{
443202719Sgabor
444202719Sgabor	bn_check(BN_sub(n->number, &zero, n->number));
445202719Sgabor}
446202719Sgabor
447202719Sgaborstatic __inline void
448202719Sgaborpush_number(struct number *n)
449202719Sgabor{
450202719Sgabor
451202719Sgabor	stack_pushnumber(&bmachine.stack, n);
452202719Sgabor}
453202719Sgabor
454202719Sgaborstatic __inline void
455202719Sgaborpush_string(char *string)
456202719Sgabor{
457202719Sgabor
458202719Sgabor	stack_pushstring(&bmachine.stack, string);
459202719Sgabor}
460202719Sgabor
461202719Sgaborstatic __inline void
462202719Sgaborpush(struct value *v)
463202719Sgabor{
464202719Sgabor
465202719Sgabor	stack_push(&bmachine.stack, v);
466202719Sgabor}
467202719Sgabor
468202719Sgaborstatic __inline struct value *
469202719Sgabortos(void)
470202719Sgabor{
471202719Sgabor
472202719Sgabor	return (stack_tos(&bmachine.stack));
473202719Sgabor}
474202719Sgabor
475202719Sgaborstatic __inline struct value *
476202719Sgaborpop(void)
477202719Sgabor{
478202719Sgabor
479202719Sgabor	return (stack_pop(&bmachine.stack));
480202719Sgabor}
481202719Sgabor
482202719Sgaborstatic __inline struct number *
483202719Sgaborpop_number(void)
484202719Sgabor{
485202719Sgabor
486202719Sgabor	return (stack_popnumber(&bmachine.stack));
487202719Sgabor}
488202719Sgabor
489202719Sgaborstatic __inline char *
490202719Sgaborpop_string(void)
491202719Sgabor{
492202719Sgabor
493202719Sgabor	return (stack_popstring(&bmachine.stack));
494202719Sgabor}
495202719Sgabor
496202719Sgaborstatic __inline void
497202719Sgaborclear_stack(void)
498202719Sgabor{
499202719Sgabor
500202719Sgabor	stack_clear(&bmachine.stack);
501202719Sgabor}
502202719Sgabor
503202719Sgaborstatic __inline void
504202719Sgaborprint_stack(void)
505202719Sgabor{
506202719Sgabor
507202719Sgabor	stack_print(stdout, &bmachine.stack, "", bmachine.obase);
508202719Sgabor}
509202719Sgabor
510202719Sgaborstatic __inline void
511202719Sgaborprint_tos(void)
512202719Sgabor{
513202719Sgabor	struct value	*value = tos();
514202719Sgabor
515202719Sgabor	if (value != NULL) {
516202719Sgabor		print_value(stdout, value, "", bmachine.obase);
517202719Sgabor		putchar('\n');
518202719Sgabor	}
519202719Sgabor	else
520202719Sgabor		warnx("stack empty");
521202719Sgabor}
522202719Sgabor
523202719Sgaborstatic void
524202719Sgaborpop_print(void)
525202719Sgabor{
526202719Sgabor	struct value	*value = pop();
527202719Sgabor
528202719Sgabor	if (value != NULL) {
529202719Sgabor		switch (value->type) {
530202719Sgabor		case BCODE_NONE:
531202719Sgabor			break;
532202719Sgabor		case BCODE_NUMBER:
533202719Sgabor			normalize(value->u.num, 0);
534202719Sgabor			print_ascii(stdout, value->u.num);
535202719Sgabor			fflush(stdout);
536202719Sgabor			break;
537202719Sgabor		case BCODE_STRING:
538202719Sgabor			fputs(value->u.string, stdout);
539202719Sgabor			fflush(stdout);
540202719Sgabor			break;
541202719Sgabor		}
542202719Sgabor		stack_free_value(value);
543202719Sgabor	}
544202719Sgabor}
545202719Sgabor
546202719Sgaborstatic void
547202719Sgaborpop_printn(void)
548202719Sgabor{
549202719Sgabor	struct value	*value = pop();
550202719Sgabor
551202719Sgabor	if (value != NULL) {
552202719Sgabor		print_value(stdout, value, "", bmachine.obase);
553202719Sgabor		fflush(stdout);
554202719Sgabor		stack_free_value(value);
555202719Sgabor	}
556202719Sgabor}
557202719Sgabor
558202719Sgaborstatic __inline void
559202719Sgabordup(void)
560202719Sgabor{
561202719Sgabor
562202719Sgabor	stack_dup(&bmachine.stack);
563202719Sgabor}
564202719Sgabor
565202719Sgaborstatic void
566202719Sgaborswap(void)
567202719Sgabor{
568202719Sgabor
569202719Sgabor	stack_swap(&bmachine.stack);
570202719Sgabor}
571202719Sgabor
572202719Sgaborstatic void
573202719Sgabordrop(void)
574202719Sgabor{
575202719Sgabor	struct value	*v = pop();
576202719Sgabor	if (v != NULL)
577202719Sgabor		stack_free_value(v);
578202719Sgabor}
579202719Sgabor
580202719Sgaborstatic void
581202719Sgaborget_scale(void)
582202719Sgabor{
583202719Sgabor	struct number	*n;
584202719Sgabor
585202719Sgabor	n = new_number();
586202719Sgabor	bn_check(BN_set_word(n->number, bmachine.scale));
587202719Sgabor	push_number(n);
588202719Sgabor}
589202719Sgabor
590202719Sgaborstatic void
591202719Sgaborset_scale(void)
592202719Sgabor{
593202719Sgabor	struct number	*n;
594202719Sgabor	u_long		 scale;
595202719Sgabor
596202719Sgabor	n = pop_number();
597202719Sgabor	if (n != NULL) {
598202719Sgabor		if (BN_cmp(n->number, &zero) < 0)
599202719Sgabor			warnx("scale must be a nonnegative number");
600202719Sgabor		else {
601202719Sgabor			scale = get_ulong(n);
602202719Sgabor			if (scale != BN_MASK2 && scale <= UINT_MAX)
603202719Sgabor				bmachine.scale = (u_int)scale;
604202719Sgabor			else
605202719Sgabor				warnx("scale too large");
606202719Sgabor			}
607202719Sgabor		free_number(n);
608202719Sgabor	}
609202719Sgabor}
610202719Sgabor
611202719Sgaborstatic void
612202719Sgaborget_obase(void)
613202719Sgabor{
614202719Sgabor	struct number	*n;
615202719Sgabor
616202719Sgabor	n = new_number();
617202719Sgabor	bn_check(BN_set_word(n->number, bmachine.obase));
618202719Sgabor	push_number(n);
619202719Sgabor}
620202719Sgabor
621202719Sgaborstatic void
622202719Sgaborset_obase(void)
623202719Sgabor{
624202719Sgabor	struct number	*n;
625202719Sgabor	u_long		 base;
626202719Sgabor
627202719Sgabor	n = pop_number();
628202719Sgabor	if (n != NULL) {
629202719Sgabor		base = get_ulong(n);
630202719Sgabor		if (base != BN_MASK2 && base > 1 && base <= UINT_MAX)
631202719Sgabor			bmachine.obase = (u_int)base;
632202719Sgabor		else
633202719Sgabor			warnx("output base must be a number greater than 1");
634202719Sgabor		free_number(n);
635202719Sgabor	}
636202719Sgabor}
637202719Sgabor
638202719Sgaborstatic void
639202719Sgaborget_ibase(void)
640202719Sgabor{
641202719Sgabor	struct number	*n;
642202719Sgabor
643202719Sgabor	n = new_number();
644202719Sgabor	bn_check(BN_set_word(n->number, bmachine.ibase));
645202719Sgabor	push_number(n);
646202719Sgabor}
647202719Sgabor
648202719Sgaborstatic void
649202719Sgaborset_ibase(void)
650202719Sgabor{
651202719Sgabor	struct number	*n;
652202719Sgabor	u_long		 base;
653202719Sgabor
654202719Sgabor	n = pop_number();
655202719Sgabor	if (n != NULL) {
656202719Sgabor		base = get_ulong(n);
657202719Sgabor		if (base != BN_MASK2 && 2 <= base && base <= 16)
658202719Sgabor			bmachine.ibase = (u_int)base;
659202719Sgabor		else
660202719Sgabor			warnx("input base must be a number between 2 and 16 "
661202719Sgabor			    "(inclusive)");
662202719Sgabor		free_number(n);
663202719Sgabor	}
664202719Sgabor}
665202719Sgabor
666202719Sgaborstatic void
667202719Sgaborstackdepth(void)
668202719Sgabor{
669202719Sgabor	size_t		 i;
670202719Sgabor	struct number	*n;
671202719Sgabor
672202719Sgabor	i = stack_size(&bmachine.stack);
673202719Sgabor	n = new_number();
674202719Sgabor	bn_check(BN_set_word(n->number, i));
675202719Sgabor	push_number(n);
676202719Sgabor}
677202719Sgabor
678202719Sgaborstatic void
679202719Sgaborpush_scale(void)
680202719Sgabor{
681202719Sgabor	struct value	*value;
682202719Sgabor	u_int		 scale = 0;
683202719Sgabor	struct number	*n;
684202719Sgabor
685202719Sgabor
686202719Sgabor	value = pop();
687202719Sgabor	if (value != NULL) {
688202719Sgabor		switch (value->type) {
689202719Sgabor		case BCODE_NONE:
690202719Sgabor			return;
691202719Sgabor		case BCODE_NUMBER:
692202719Sgabor			scale = value->u.num->scale;
693202719Sgabor			break;
694202719Sgabor		case BCODE_STRING:
695202719Sgabor			break;
696202719Sgabor		}
697202719Sgabor		stack_free_value(value);
698202719Sgabor		n = new_number();
699202719Sgabor		bn_check(BN_set_word(n->number, scale));
700202719Sgabor		push_number(n);
701202719Sgabor	}
702202719Sgabor}
703202719Sgabor
704202719Sgaborstatic u_int
705202719Sgaborcount_digits(const struct number *n)
706202719Sgabor{
707202719Sgabor	struct number	*int_part, *fract_part;
708202719Sgabor	u_int		 i;
709202719Sgabor
710202719Sgabor	if (BN_is_zero(n->number))
711202719Sgabor		return (1);
712202719Sgabor
713202719Sgabor	int_part = new_number();
714202719Sgabor	fract_part = new_number();
715202719Sgabor	fract_part->scale = n->scale;
716202719Sgabor	split_number(n, int_part->number, fract_part->number);
717202719Sgabor
718202719Sgabor	i = 0;
719202719Sgabor	while (!BN_is_zero(int_part->number)) {
720202719Sgabor		BN_div_word(int_part->number, 10);
721202719Sgabor		i++;
722202719Sgabor	}
723202719Sgabor	free_number(int_part);
724202719Sgabor	free_number(fract_part);
725202719Sgabor	return (i + n->scale);
726202719Sgabor}
727202719Sgabor
728202719Sgaborstatic void
729202719Sgabornum_digits(void)
730202719Sgabor{
731202719Sgabor	struct value	*value;
732202719Sgabor	size_t		 digits;
733202719Sgabor	struct number	*n = NULL;
734202719Sgabor
735202719Sgabor	value = pop();
736202719Sgabor	if (value != NULL) {
737202719Sgabor		switch (value->type) {
738202719Sgabor		case BCODE_NONE:
739202719Sgabor			return;
740202719Sgabor		case BCODE_NUMBER:
741202719Sgabor			digits = count_digits(value->u.num);
742202719Sgabor			n = new_number();
743202719Sgabor			bn_check(BN_set_word(n->number, digits));
744202719Sgabor			break;
745202719Sgabor		case BCODE_STRING:
746202719Sgabor			digits = strlen(value->u.string);
747202719Sgabor			n = new_number();
748202719Sgabor			bn_check(BN_set_word(n->number, digits));
749202719Sgabor			break;
750202719Sgabor		}
751202719Sgabor		stack_free_value(value);
752202719Sgabor		push_number(n);
753202719Sgabor	}
754202719Sgabor}
755202719Sgabor
756202719Sgaborstatic void
757202719Sgaborto_ascii(void)
758202719Sgabor{
759202719Sgabor	char		 str[2];
760202719Sgabor	struct value	*value;
761202719Sgabor	struct number	*n;
762202719Sgabor
763202719Sgabor	value = pop();
764202719Sgabor	if (value != NULL) {
765202719Sgabor		str[1] = '\0';
766202719Sgabor		switch (value->type) {
767202719Sgabor		case BCODE_NONE:
768202719Sgabor			return;
769202719Sgabor		case BCODE_NUMBER:
770202719Sgabor			n = value->u.num;
771202719Sgabor			normalize(n, 0);
772202719Sgabor			if (BN_num_bits(n->number) > 8)
773202719Sgabor				bn_check(BN_mask_bits(n->number, 8));
774202719Sgabor			str[0] = (char)BN_get_word(n->number);
775202719Sgabor			break;
776202719Sgabor		case BCODE_STRING:
777202719Sgabor			str[0] = value->u.string[0];
778202719Sgabor			break;
779202719Sgabor		}
780202719Sgabor		stack_free_value(value);
781202719Sgabor		push_string(bstrdup(str));
782202719Sgabor	}
783202719Sgabor}
784202719Sgabor
785202719Sgaborstatic int
786202719Sgaborreadreg(void)
787202719Sgabor{
788202719Sgabor	int	 idx, ch1, ch2;
789202719Sgabor
790202719Sgabor	idx = readch();
791202719Sgabor	if (idx == 0xff && bmachine.extended_regs) {
792202719Sgabor		ch1 = readch();
793202719Sgabor		ch2 = readch();
794202719Sgabor		if (ch1 == EOF || ch2 == EOF) {
795202719Sgabor			warnx("unexpected eof");
796202719Sgabor			idx = -1;
797202719Sgabor		} else
798202719Sgabor			idx = (ch1 << 8) + ch2 + UCHAR_MAX + 1;
799202719Sgabor	}
800202719Sgabor	if (idx < 0 || (unsigned)idx >= bmachine.reg_array_size) {
801202719Sgabor		warnx("internal error: reg num = %d", idx);
802202719Sgabor		idx = -1;
803202719Sgabor	}
804202719Sgabor	return (idx);
805202719Sgabor}
806202719Sgabor
807202719Sgaborstatic void
808202719Sgaborload(void)
809202719Sgabor{
810202719Sgabor	int		 idx;
811202719Sgabor	struct value	*v, copy;
812202719Sgabor	struct number	*n;
813202719Sgabor
814202719Sgabor	idx = readreg();
815202719Sgabor	if (idx >= 0) {
816202719Sgabor		v = stack_tos(&bmachine.reg[idx]);
817202719Sgabor		if (v == NULL) {
818202719Sgabor			n = new_number();
819202719Sgabor			bn_check(BN_zero(n->number));
820202719Sgabor			push_number(n);
821202719Sgabor		} else
822202719Sgabor			push(stack_dup_value(v, &copy));
823202719Sgabor	}
824202719Sgabor}
825202719Sgabor
826202719Sgaborstatic void
827202719Sgaborstore(void)
828202719Sgabor{
829202719Sgabor	int		 idx;
830202719Sgabor	struct value	*val;
831202719Sgabor
832202719Sgabor	idx = readreg();
833202719Sgabor	if (idx >= 0) {
834202719Sgabor		val = pop();
835202719Sgabor		if (val == NULL) {
836202719Sgabor			return;
837202719Sgabor		}
838202719Sgabor		stack_set_tos(&bmachine.reg[idx], val);
839202719Sgabor	}
840202719Sgabor}
841202719Sgabor
842202719Sgaborstatic void
843202719Sgaborload_stack(void)
844202719Sgabor{
845202719Sgabor	int		 idx;
846202719Sgabor	struct stack	*stack;
847202719Sgabor	struct value	*value;
848202719Sgabor
849202719Sgabor	idx = readreg();
850202719Sgabor	if (idx >= 0) {
851202719Sgabor		stack = &bmachine.reg[idx];
852202719Sgabor		value = NULL;
853202719Sgabor		if (stack_size(stack) > 0) {
854202719Sgabor			value = stack_pop(stack);
855202719Sgabor		}
856202719Sgabor		if (value != NULL)
857202719Sgabor			push(value);
858202719Sgabor		else
859202719Sgabor			warnx("stack register '%c' (0%o) is empty",
860202719Sgabor			    idx, idx);
861202719Sgabor	}
862202719Sgabor}
863202719Sgabor
864202719Sgaborstatic void
865202719Sgaborstore_stack(void)
866202719Sgabor{
867202719Sgabor	int		 idx;
868202719Sgabor	struct value	*value;
869202719Sgabor
870202719Sgabor	idx = readreg();
871202719Sgabor	if (idx >= 0) {
872202719Sgabor		value = pop();
873202719Sgabor		if (value == NULL)
874202719Sgabor			return;
875202719Sgabor		stack_push(&bmachine.reg[idx], value);
876202719Sgabor	}
877202719Sgabor}
878202719Sgabor
879202719Sgaborstatic void
880202719Sgaborload_array(void)
881202719Sgabor{
882202719Sgabor	int			 reg;
883202719Sgabor	struct number		*inumber, *n;
884202719Sgabor	u_long			 idx;
885202719Sgabor	struct stack		*stack;
886202719Sgabor	struct value		*v, copy;
887202719Sgabor
888202719Sgabor	reg = readreg();
889202719Sgabor	if (reg >= 0) {
890202719Sgabor		inumber = pop_number();
891202719Sgabor		if (inumber == NULL)
892202719Sgabor			return;
893202719Sgabor		idx = get_ulong(inumber);
894202719Sgabor		if (BN_cmp(inumber->number, &zero) < 0)
895202719Sgabor			warnx("negative idx");
896202719Sgabor		else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX)
897202719Sgabor			warnx("idx too big");
898202719Sgabor		else {
899202719Sgabor			stack = &bmachine.reg[reg];
900202719Sgabor			v = frame_retrieve(stack, idx);
901202719Sgabor			if (v == NULL || v->type == BCODE_NONE) {
902202719Sgabor				n = new_number();
903202719Sgabor				bn_check(BN_zero(n->number));
904202719Sgabor				push_number(n);
905202719Sgabor			}
906202719Sgabor			else
907202719Sgabor				push(stack_dup_value(v, &copy));
908202719Sgabor		}
909202719Sgabor		free_number(inumber);
910202719Sgabor	}
911202719Sgabor}
912202719Sgabor
913202719Sgaborstatic void
914202719Sgaborstore_array(void)
915202719Sgabor{
916202719Sgabor	int			 reg;
917202719Sgabor	struct number		*inumber;
918202719Sgabor	u_long			 idx;
919202719Sgabor	struct value		*value;
920202719Sgabor	struct stack		*stack;
921202719Sgabor
922202719Sgabor	reg = readreg();
923202719Sgabor	if (reg >= 0) {
924202719Sgabor		inumber = pop_number();
925202719Sgabor		if (inumber == NULL)
926202719Sgabor			return;
927202719Sgabor		value = pop();
928202719Sgabor		if (value == NULL) {
929202719Sgabor			free_number(inumber);
930202719Sgabor			return;
931202719Sgabor		}
932202719Sgabor		idx = get_ulong(inumber);
933202719Sgabor		if (BN_cmp(inumber->number, &zero) < 0) {
934202719Sgabor			warnx("negative idx");
935202719Sgabor			stack_free_value(value);
936202719Sgabor		} else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) {
937202719Sgabor			warnx("idx too big");
938202719Sgabor			stack_free_value(value);
939202719Sgabor		} else {
940202719Sgabor			stack = &bmachine.reg[reg];
941202719Sgabor			frame_assign(stack, idx, value);
942202719Sgabor		}
943202719Sgabor		free_number(inumber);
944202719Sgabor	}
945202719Sgabor}
946202719Sgabor
947202719Sgaborstatic void
948202719Sgaborpush_line(void)
949202719Sgabor{
950202719Sgabor
951202719Sgabor	push_string(read_string(&bmachine.readstack[bmachine.readsp]));
952202719Sgabor}
953202719Sgabor
954202719Sgaborstatic void
955202719Sgaborcomment(void)
956202719Sgabor{
957202719Sgabor
958202719Sgabor	free(readline());
959202719Sgabor}
960202719Sgabor
961202719Sgaborstatic void
962202719Sgaborbexec(char *line)
963202719Sgabor{
964202719Sgabor
965202719Sgabor	system(line);
966202719Sgabor	free(line);
967202719Sgabor}
968202719Sgabor
969202719Sgaborstatic void
970202719Sgaborbadd(void)
971202719Sgabor{
972202719Sgabor	struct number	*a, *b;
973202719Sgabor	struct number	*r;
974202719Sgabor
975202719Sgabor	a = pop_number();
976202719Sgabor	if (a == NULL) {
977202719Sgabor		return;
978202719Sgabor	}
979202719Sgabor	b = pop_number();
980202719Sgabor	if (b == NULL) {
981202719Sgabor		push_number(a);
982202719Sgabor		return;
983202719Sgabor	}
984202719Sgabor
985202719Sgabor	r = new_number();
986202719Sgabor	r->scale = max(a->scale, b->scale);
987202719Sgabor	if (r->scale > a->scale)
988202719Sgabor		normalize(a, r->scale);
989202719Sgabor	else if (r->scale > b->scale)
990202719Sgabor		normalize(b, r->scale);
991202719Sgabor	bn_check(BN_add(r->number, a->number, b->number));
992202719Sgabor	push_number(r);
993202719Sgabor	free_number(a);
994202719Sgabor	free_number(b);
995202719Sgabor}
996202719Sgabor
997202719Sgaborstatic void
998202719Sgaborbsub(void)
999202719Sgabor{
1000202719Sgabor	struct number	*a, *b;
1001202719Sgabor	struct number	*r;
1002202719Sgabor
1003202719Sgabor	a = pop_number();
1004202719Sgabor	if (a == NULL) {
1005202719Sgabor		return;
1006202719Sgabor	}
1007202719Sgabor	b = pop_number();
1008202719Sgabor	if (b == NULL) {
1009202719Sgabor		push_number(a);
1010202719Sgabor		return;
1011202719Sgabor	}
1012202719Sgabor
1013202719Sgabor	r = new_number();
1014202719Sgabor
1015202719Sgabor	r->scale = max(a->scale, b->scale);
1016202719Sgabor	if (r->scale > a->scale)
1017202719Sgabor		normalize(a, r->scale);
1018202719Sgabor	else if (r->scale > b->scale)
1019202719Sgabor		normalize(b, r->scale);
1020202719Sgabor	bn_check(BN_sub(r->number, b->number, a->number));
1021202719Sgabor	push_number(r);
1022202719Sgabor	free_number(a);
1023202719Sgabor	free_number(b);
1024202719Sgabor}
1025202719Sgabor
1026202719Sgaborvoid
1027202719Sgaborbmul_number(struct number *r, struct number *a, struct number *b)
1028202719Sgabor{
1029202719Sgabor	BN_CTX		*ctx;
1030202719Sgabor
1031202719Sgabor	/* Create copies of the scales, since r might be equal to a or b */
1032202719Sgabor	u_int ascale = a->scale;
1033202719Sgabor	u_int bscale = b->scale;
1034202719Sgabor	u_int rscale = ascale + bscale;
1035202719Sgabor
1036202719Sgabor	ctx = BN_CTX_new();
1037202719Sgabor	bn_checkp(ctx);
1038202719Sgabor	bn_check(BN_mul(r->number, a->number, b->number, ctx));
1039202719Sgabor	BN_CTX_free(ctx);
1040202719Sgabor
1041202719Sgabor	if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) {
1042202719Sgabor		r->scale = rscale;
1043202719Sgabor		normalize(r, max(bmachine.scale, max(ascale, bscale)));
1044202719Sgabor	} else
1045202719Sgabor		r->scale = rscale;
1046202719Sgabor}
1047202719Sgabor
1048202719Sgaborstatic void
1049202719Sgaborbmul(void)
1050202719Sgabor{
1051202719Sgabor	struct number	*a, *b;
1052202719Sgabor	struct number	*r;
1053202719Sgabor
1054202719Sgabor	a = pop_number();
1055202719Sgabor	if (a == NULL) {
1056202719Sgabor		return;
1057202719Sgabor	}
1058202719Sgabor	b = pop_number();
1059202719Sgabor	if (b == NULL) {
1060202719Sgabor		push_number(a);
1061202719Sgabor		return;
1062202719Sgabor	}
1063202719Sgabor
1064202719Sgabor	r = new_number();
1065202719Sgabor	bmul_number(r, a, b);
1066202719Sgabor
1067202719Sgabor	push_number(r);
1068202719Sgabor	free_number(a);
1069202719Sgabor	free_number(b);
1070202719Sgabor}
1071202719Sgabor
1072202719Sgaborstatic void
1073202719Sgaborbdiv(void)
1074202719Sgabor{
1075202719Sgabor	struct number	*a, *b;
1076202719Sgabor	struct number	*r;
1077202719Sgabor	u_int		 scale;
1078202719Sgabor	BN_CTX		*ctx;
1079202719Sgabor
1080202719Sgabor	a = pop_number();
1081202719Sgabor	if (a == NULL) {
1082202719Sgabor		return;
1083202719Sgabor	}
1084202719Sgabor	b = pop_number();
1085202719Sgabor	if (b == NULL) {
1086202719Sgabor		push_number(a);
1087202719Sgabor		return;
1088202719Sgabor	}
1089202719Sgabor
1090202719Sgabor	r = new_number();
1091202719Sgabor	r->scale = bmachine.scale;
1092202719Sgabor	scale = max(a->scale, b->scale);
1093202719Sgabor
1094202719Sgabor	if (BN_is_zero(a->number))
1095202719Sgabor		warnx("divide by zero");
1096202719Sgabor	else {
1097202719Sgabor		normalize(a, scale);
1098202719Sgabor		normalize(b, scale + r->scale);
1099202719Sgabor
1100202719Sgabor		ctx = BN_CTX_new();
1101202719Sgabor		bn_checkp(ctx);
1102202719Sgabor		bn_check(BN_div(r->number, NULL, b->number, a->number, ctx));
1103202719Sgabor		BN_CTX_free(ctx);
1104202719Sgabor	}
1105202719Sgabor	push_number(r);
1106202719Sgabor	free_number(a);
1107202719Sgabor	free_number(b);
1108202719Sgabor}
1109202719Sgabor
1110202719Sgaborstatic void
1111202719Sgaborbmod(void)
1112202719Sgabor{
1113202719Sgabor	struct number	*a, *b;
1114202719Sgabor	struct number	*r;
1115202719Sgabor	u_int		 scale;
1116202719Sgabor	BN_CTX		*ctx;
1117202719Sgabor
1118202719Sgabor	a = pop_number();
1119202719Sgabor	if (a == NULL) {
1120202719Sgabor		return;
1121202719Sgabor	}
1122202719Sgabor	b = pop_number();
1123202719Sgabor	if (b == NULL) {
1124202719Sgabor		push_number(a);
1125202719Sgabor		return;
1126202719Sgabor	}
1127202719Sgabor
1128202719Sgabor	r = new_number();
1129202719Sgabor	scale = max(a->scale, b->scale);
1130202719Sgabor	r->scale = max(b->scale, a->scale + bmachine.scale);
1131202719Sgabor
1132202719Sgabor	if (BN_is_zero(a->number))
1133202719Sgabor		warnx("remainder by zero");
1134202719Sgabor	else {
1135202719Sgabor		normalize(a, scale);
1136202719Sgabor		normalize(b, scale + bmachine.scale);
1137202719Sgabor
1138202719Sgabor		ctx = BN_CTX_new();
1139202719Sgabor		bn_checkp(ctx);
1140202719Sgabor		bn_check(BN_mod(r->number, b->number, a->number, ctx));
1141202719Sgabor		BN_CTX_free(ctx);
1142202719Sgabor	}
1143202719Sgabor	push_number(r);
1144202719Sgabor	free_number(a);
1145202719Sgabor	free_number(b);
1146202719Sgabor}
1147202719Sgabor
1148202719Sgaborstatic void
1149202719Sgaborbdivmod(void)
1150202719Sgabor{
1151202719Sgabor	struct number	*a, *b;
1152202719Sgabor	struct number	*rdiv, *rmod;
1153202719Sgabor	u_int		 scale;
1154202719Sgabor	BN_CTX		*ctx;
1155202719Sgabor
1156202719Sgabor	a = pop_number();
1157202719Sgabor	if (a == NULL) {
1158202719Sgabor		return;
1159202719Sgabor	}
1160202719Sgabor	b = pop_number();
1161202719Sgabor	if (b == NULL) {
1162202719Sgabor		push_number(a);
1163202719Sgabor		return;
1164202719Sgabor	}
1165202719Sgabor
1166202719Sgabor	rdiv = new_number();
1167202719Sgabor	rmod = new_number();
1168202719Sgabor	rdiv->scale = bmachine.scale;
1169202719Sgabor	rmod->scale = max(b->scale, a->scale + bmachine.scale);
1170202719Sgabor	scale = max(a->scale, b->scale);
1171202719Sgabor
1172202719Sgabor	if (BN_is_zero(a->number))
1173202719Sgabor		warnx("divide by zero");
1174202719Sgabor	else {
1175202719Sgabor		normalize(a, scale);
1176202719Sgabor		normalize(b, scale + bmachine.scale);
1177202719Sgabor
1178202719Sgabor		ctx = BN_CTX_new();
1179202719Sgabor		bn_checkp(ctx);
1180202719Sgabor		bn_check(BN_div(rdiv->number, rmod->number,
1181202719Sgabor		    b->number, a->number, ctx));
1182202719Sgabor		BN_CTX_free(ctx);
1183202719Sgabor	}
1184202719Sgabor	push_number(rdiv);
1185202719Sgabor	push_number(rmod);
1186202719Sgabor	free_number(a);
1187202719Sgabor	free_number(b);
1188202719Sgabor}
1189202719Sgabor
1190202719Sgaborstatic void
1191202719Sgaborbexp(void)
1192202719Sgabor{
1193202719Sgabor	struct number	*a, *p;
1194202719Sgabor	struct number	*r;
1195202719Sgabor	bool		 neg;
1196202719Sgabor	u_int		 scale;
1197202719Sgabor
1198202719Sgabor	p = pop_number();
1199202719Sgabor	if (p == NULL) {
1200202719Sgabor		return;
1201202719Sgabor	}
1202202719Sgabor	a = pop_number();
1203202719Sgabor	if (a == NULL) {
1204202719Sgabor		push_number(p);
1205202719Sgabor		return;
1206202719Sgabor	}
1207202719Sgabor
1208202719Sgabor	if (p->scale != 0)
1209202719Sgabor		warnx("Runtime warning: non-zero scale in exponent");
1210202719Sgabor	normalize(p, 0);
1211202719Sgabor
1212202719Sgabor	neg = false;
1213202719Sgabor	if (BN_cmp(p->number, &zero) < 0) {
1214202719Sgabor		neg = true;
1215202719Sgabor		negate(p);
1216202719Sgabor		scale = bmachine.scale;
1217202719Sgabor	} else {
1218202719Sgabor		/* Posix bc says min(a.scale * b, max(a.scale, scale) */
1219202719Sgabor		u_long	 b;
1220202719Sgabor		u_int	 m;
1221202719Sgabor
1222202719Sgabor		b = BN_get_word(p->number);
1223202719Sgabor		m = max(a->scale, bmachine.scale);
1224202719Sgabor		scale = a->scale * (u_int)b;
1225202719Sgabor		if (scale > m || (a->scale > 0 && (b == BN_MASK2 ||
1226202719Sgabor		    b > UINT_MAX)))
1227202719Sgabor			scale = m;
1228202719Sgabor	}
1229202719Sgabor
1230202719Sgabor	if (BN_is_zero(p->number)) {
1231202719Sgabor		r = new_number();
1232202719Sgabor		bn_check(BN_one(r->number));
1233202719Sgabor		normalize(r, scale);
1234202719Sgabor	} else {
1235202719Sgabor		while (!BN_is_bit_set(p->number, 0)) {
1236202719Sgabor			bmul_number(a, a, a);
1237202719Sgabor			bn_check(BN_rshift1(p->number, p->number));
1238202719Sgabor		}
1239202719Sgabor
1240202719Sgabor		r = dup_number(a);
1241202719Sgabor		normalize(r, scale);
1242202719Sgabor		bn_check(BN_rshift1(p->number, p->number));
1243202719Sgabor
1244202719Sgabor		while (!BN_is_zero(p->number)) {
1245202719Sgabor			bmul_number(a, a, a);
1246202719Sgabor			if (BN_is_bit_set(p->number, 0))
1247202719Sgabor				bmul_number(r, r, a);
1248202719Sgabor			bn_check(BN_rshift1(p->number, p->number));
1249202719Sgabor		}
1250202719Sgabor
1251202719Sgabor		if (neg) {
1252202719Sgabor			BN_CTX	*ctx;
1253202719Sgabor			BIGNUM	*one;
1254202719Sgabor
1255202719Sgabor			one = BN_new();
1256202719Sgabor			bn_checkp(one);
1257202719Sgabor			bn_check(BN_one(one));
1258202719Sgabor			ctx = BN_CTX_new();
1259202719Sgabor			bn_checkp(ctx);
1260202719Sgabor			scale_number(one, r->scale + scale);
1261202719Sgabor			normalize(r, scale);
1262202719Sgabor			bn_check(BN_div(r->number, NULL, one, r->number, ctx));
1263202719Sgabor			BN_free(one);
1264202719Sgabor			BN_CTX_free(ctx);
1265202719Sgabor		} else
1266202719Sgabor			normalize(r, scale);
1267202719Sgabor	}
1268202719Sgabor	push_number(r);
1269202719Sgabor	free_number(a);
1270202719Sgabor	free_number(p);
1271202719Sgabor}
1272202719Sgabor
1273202719Sgaborstatic bool
1274202719Sgaborbsqrt_stop(const BIGNUM *x, const BIGNUM *y, u_int *onecount)
1275202719Sgabor{
1276202719Sgabor	BIGNUM	*r;
1277202719Sgabor	bool	 ret;
1278202719Sgabor
1279202719Sgabor	r = BN_new();
1280202719Sgabor	bn_checkp(r);
1281202719Sgabor	bn_check(BN_sub(r, x, y));
1282202719Sgabor	if (BN_is_one(r))
1283202719Sgabor		(*onecount)++;
1284202719Sgabor	ret = BN_is_zero(r);
1285202719Sgabor	BN_free(r);
1286202719Sgabor	return (ret || *onecount > 1);
1287202719Sgabor}
1288202719Sgabor
1289202719Sgaborstatic void
1290202719Sgaborbsqrt(void)
1291202719Sgabor{
1292202719Sgabor	struct number	*n;
1293202719Sgabor	struct number	*r;
1294202719Sgabor	BIGNUM		*x, *y;
1295202719Sgabor	u_int		 scale, onecount;
1296202719Sgabor	BN_CTX		*ctx;
1297202719Sgabor
1298202719Sgabor	onecount = 0;
1299202719Sgabor	n = pop_number();
1300202719Sgabor	if (n == NULL) {
1301202719Sgabor		return;
1302202719Sgabor	}
1303202719Sgabor	if (BN_is_zero(n->number)) {
1304202719Sgabor		r = new_number();
1305202719Sgabor		push_number(r);
1306202719Sgabor	} else if (BN_cmp(n->number, &zero) < 0)
1307202719Sgabor		warnx("square root of negative number");
1308202719Sgabor	else {
1309202719Sgabor		scale = max(bmachine.scale, n->scale);
1310202719Sgabor		normalize(n, 2*scale);
1311202719Sgabor		x = BN_dup(n->number);
1312202719Sgabor		bn_checkp(x);
1313202719Sgabor		bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
1314202719Sgabor		y = BN_new();
1315202719Sgabor		bn_checkp(y);
1316202719Sgabor		ctx = BN_CTX_new();
1317202719Sgabor		bn_checkp(ctx);
1318202719Sgabor		for (;;) {
1319202719Sgabor			bn_checkp(BN_copy(y, x));
1320202719Sgabor			bn_check(BN_div(x, NULL, n->number, x, ctx));
1321202719Sgabor			bn_check(BN_add(x, x, y));
1322202719Sgabor			bn_check(BN_rshift1(x, x));
1323202719Sgabor			if (bsqrt_stop(x, y, &onecount))
1324202719Sgabor				break;
1325202719Sgabor		}
1326202719Sgabor		r = bmalloc(sizeof(*r));
1327202719Sgabor		r->scale = scale;
1328202719Sgabor		r->number = y;
1329202719Sgabor		BN_free(x);
1330202719Sgabor		BN_CTX_free(ctx);
1331202719Sgabor		push_number(r);
1332202719Sgabor	}
1333202719Sgabor
1334202719Sgabor	free_number(n);
1335202719Sgabor}
1336202719Sgabor
1337202719Sgaborstatic void
1338202719Sgabornot(void)
1339202719Sgabor{
1340202719Sgabor	struct number	*a;
1341202719Sgabor
1342202719Sgabor	a = pop_number();
1343202719Sgabor	if (a == NULL) {
1344202719Sgabor		return;
1345202719Sgabor	}
1346202719Sgabor	a->scale = 0;
1347202719Sgabor	bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1));
1348202719Sgabor	push_number(a);
1349202719Sgabor}
1350202719Sgabor
1351202719Sgaborstatic void
1352202719Sgaborequal(void)
1353202719Sgabor{
1354202719Sgabor
1355202719Sgabor	compare(BCODE_EQUAL);
1356202719Sgabor}
1357202719Sgabor
1358202719Sgaborstatic void
1359202719Sgaborequal_numbers(void)
1360202719Sgabor{
1361202719Sgabor	struct number	*a, *b, *r;
1362202719Sgabor
1363202719Sgabor	a = pop_number();
1364202719Sgabor	if (a == NULL) {
1365202719Sgabor		return;
1366202719Sgabor	}
1367202719Sgabor	b = pop_number();
1368202719Sgabor	if (b == NULL) {
1369202719Sgabor		push_number(a);
1370202719Sgabor		return;
1371202719Sgabor	}
1372202719Sgabor	r = new_number();
1373202719Sgabor	bn_check(BN_set_word(r->number,
1374202719Sgabor	    compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0));
1375202719Sgabor	push_number(r);
1376202719Sgabor}
1377202719Sgabor
1378202719Sgaborstatic void
1379202719Sgaborless_numbers(void)
1380202719Sgabor{
1381202719Sgabor	struct number	*a, *b, *r;
1382202719Sgabor
1383202719Sgabor	a = pop_number();
1384202719Sgabor	if (a == NULL) {
1385202719Sgabor		return;
1386202719Sgabor	}
1387202719Sgabor	b = pop_number();
1388202719Sgabor	if (b == NULL) {
1389202719Sgabor		push_number(a);
1390202719Sgabor		return;
1391202719Sgabor	}
1392202719Sgabor	r = new_number();
1393202719Sgabor	bn_check(BN_set_word(r->number,
1394202719Sgabor	    compare_numbers(BCODE_LESS, a, b) ? 1 : 0));
1395202719Sgabor	push_number(r);
1396202719Sgabor}
1397202719Sgabor
1398202719Sgaborstatic void
1399202719Sgaborlesseq_numbers(void)
1400202719Sgabor{
1401202719Sgabor	struct number	*a, *b, *r;
1402202719Sgabor
1403202719Sgabor	a = pop_number();
1404202719Sgabor	if (a == NULL) {
1405202719Sgabor		return;
1406202719Sgabor	}
1407202719Sgabor	b = pop_number();
1408202719Sgabor	if (b == NULL) {
1409202719Sgabor		push_number(a);
1410202719Sgabor		return;
1411202719Sgabor	}
1412202719Sgabor	r = new_number();
1413202719Sgabor	bn_check(BN_set_word(r->number,
1414202719Sgabor	    compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
1415202719Sgabor	push_number(r);
1416202719Sgabor}
1417202719Sgabor
1418202719Sgaborstatic void
1419202719Sgabornot_equal(void)
1420202719Sgabor{
1421202719Sgabor
1422202719Sgabor	compare(BCODE_NOT_EQUAL);
1423202719Sgabor}
1424202719Sgabor
1425202719Sgaborstatic void
1426202719Sgaborless(void)
1427202719Sgabor{
1428202719Sgabor
1429202719Sgabor	compare(BCODE_LESS);
1430202719Sgabor}
1431202719Sgabor
1432202719Sgaborstatic void
1433202719Sgabornot_compare(void)
1434202719Sgabor{
1435202719Sgabor	switch (readch()) {
1436202719Sgabor	case '<':
1437202719Sgabor		not_less();
1438202719Sgabor		break;
1439202719Sgabor	case '>':
1440202719Sgabor		not_greater();
1441202719Sgabor		break;
1442202719Sgabor	case '=':
1443202719Sgabor		not_equal();
1444202719Sgabor		break;
1445202719Sgabor	default:
1446202719Sgabor		unreadch();
1447202719Sgabor		bexec(readline());
1448202719Sgabor		break;
1449202719Sgabor	}
1450202719Sgabor}
1451202719Sgabor
1452202719Sgaborstatic void
1453202719Sgabornot_less(void)
1454202719Sgabor{
1455202719Sgabor
1456202719Sgabor	compare(BCODE_NOT_LESS);
1457202719Sgabor}
1458202719Sgabor
1459202719Sgaborstatic void
1460202719Sgaborgreater(void)
1461202719Sgabor{
1462202719Sgabor
1463202719Sgabor	compare(BCODE_GREATER);
1464202719Sgabor}
1465202719Sgabor
1466202719Sgaborstatic void
1467202719Sgabornot_greater(void)
1468202719Sgabor{
1469202719Sgabor
1470202719Sgabor	compare(BCODE_NOT_GREATER);
1471202719Sgabor}
1472202719Sgabor
1473202719Sgaborstatic bool
1474202719Sgaborcompare_numbers(enum bcode_compare type, struct number *a, struct number *b)
1475202719Sgabor{
1476202719Sgabor	u_int	 scale;
1477202719Sgabor	int	 cmp;
1478202719Sgabor
1479202719Sgabor	scale = max(a->scale, b->scale);
1480202719Sgabor
1481202719Sgabor	if (scale > a->scale)
1482202719Sgabor		normalize(a, scale);
1483202719Sgabor	else if (scale > b->scale)
1484202719Sgabor		normalize(b, scale);
1485202719Sgabor
1486202719Sgabor	cmp = BN_cmp(a->number, b->number);
1487202719Sgabor
1488202719Sgabor	free_number(a);
1489202719Sgabor	free_number(b);
1490202719Sgabor
1491202719Sgabor	switch (type) {
1492202719Sgabor	case BCODE_EQUAL:
1493202719Sgabor		return (cmp == 0);
1494202719Sgabor	case BCODE_NOT_EQUAL:
1495202719Sgabor		return (cmp != 0);
1496202719Sgabor	case BCODE_LESS:
1497202719Sgabor		return (cmp < 0);
1498202719Sgabor	case BCODE_NOT_LESS:
1499202719Sgabor		return (cmp >= 0);
1500202719Sgabor	case BCODE_GREATER:
1501202719Sgabor		return (cmp > 0);
1502202719Sgabor	case BCODE_NOT_GREATER:
1503202719Sgabor		return (cmp <= 0);
1504202719Sgabor	}
1505202719Sgabor	return (false);
1506202719Sgabor}
1507202719Sgabor
1508202719Sgaborstatic void
1509202719Sgaborcompare(enum bcode_compare type)
1510202719Sgabor{
1511202719Sgabor	int		 idx, elseidx;
1512202719Sgabor	struct number	*a, *b;
1513202719Sgabor	bool		 ok;
1514202719Sgabor	struct value	*v;
1515202719Sgabor
1516202719Sgabor	elseidx = NO_ELSE;
1517202719Sgabor	idx = readreg();
1518202719Sgabor	if (readch() == 'e')
1519202719Sgabor		elseidx = readreg();
1520202719Sgabor	else
1521202719Sgabor		unreadch();
1522202719Sgabor
1523202719Sgabor	a = pop_number();
1524202719Sgabor	if (a == NULL)
1525202719Sgabor		return;
1526202719Sgabor	b = pop_number();
1527202719Sgabor	if (b == NULL) {
1528202719Sgabor		push_number(a);
1529202719Sgabor		return;
1530202719Sgabor	}
1531202719Sgabor
1532202719Sgabor	ok = compare_numbers(type, a, b);
1533202719Sgabor
1534202719Sgabor	if (!ok && elseidx != NO_ELSE)
1535202719Sgabor		idx = elseidx;
1536202719Sgabor
1537202719Sgabor	if (idx >= 0 && (ok || (!ok && elseidx != NO_ELSE))) {
1538202719Sgabor		v = stack_tos(&bmachine.reg[idx]);
1539202719Sgabor		if (v == NULL)
1540202719Sgabor			warnx("register '%c' (0%o) is empty", idx, idx);
1541202719Sgabor		else {
1542202719Sgabor			switch(v->type) {
1543202719Sgabor			case BCODE_NONE:
1544202719Sgabor				warnx("register '%c' (0%o) is empty", idx, idx);
1545202719Sgabor				break;
1546202719Sgabor			case BCODE_NUMBER:
1547202719Sgabor				warn("eval called with non-string argument");
1548202719Sgabor				break;
1549202719Sgabor			case BCODE_STRING:
1550202719Sgabor				eval_string(bstrdup(v->u.string));
1551202719Sgabor				break;
1552202719Sgabor			}
1553202719Sgabor		}
1554202719Sgabor	}
1555202719Sgabor}
1556202719Sgabor
1557202719Sgabor
1558202719Sgaborstatic void
1559202719Sgabornop(void)
1560202719Sgabor{
1561202719Sgabor}
1562202719Sgabor
1563202719Sgaborstatic void
1564202719Sgaborquit(void)
1565202719Sgabor{
1566202719Sgabor	if (bmachine.readsp < 2)
1567202719Sgabor		exit(0);
1568202719Sgabor	src_free();
1569202719Sgabor	bmachine.readsp--;
1570202719Sgabor	src_free();
1571202719Sgabor	bmachine.readsp--;
1572202719Sgabor}
1573202719Sgabor
1574202719Sgaborstatic void
1575202719SgaborquitN(void)
1576202719Sgabor{
1577202719Sgabor	struct number	*n;
1578202719Sgabor	u_long		 i;
1579202719Sgabor
1580202719Sgabor	n = pop_number();
1581202719Sgabor	if (n == NULL)
1582202719Sgabor		return;
1583202719Sgabor	i = get_ulong(n);
1584202719Sgabor	free_number(n);
1585202719Sgabor	if (i == BN_MASK2 || i == 0)
1586202719Sgabor		warnx("Q command requires a number >= 1");
1587202719Sgabor	else if (bmachine.readsp < i)
1588202719Sgabor		warnx("Q command argument exceeded string execution depth");
1589202719Sgabor	else {
1590202719Sgabor		while (i-- > 0) {
1591202719Sgabor			src_free();
1592202719Sgabor			bmachine.readsp--;
1593202719Sgabor		}
1594202719Sgabor	}
1595202719Sgabor}
1596202719Sgabor
1597202719Sgaborstatic void
1598202719SgaborskipN(void)
1599202719Sgabor{
1600202719Sgabor	struct number	*n;
1601202719Sgabor	u_long		 i;
1602202719Sgabor
1603202719Sgabor	n = pop_number();
1604202719Sgabor	if (n == NULL)
1605202719Sgabor		return;
1606202719Sgabor	i = get_ulong(n);
1607202719Sgabor	if (i == BN_MASK2)
1608202719Sgabor		warnx("J command requires a number >= 0");
1609202719Sgabor	else if (i > 0 && bmachine.readsp < i)
1610202719Sgabor		warnx("J command argument exceeded string execution depth");
1611202719Sgabor	else {
1612202719Sgabor		while (i-- > 0) {
1613202719Sgabor			src_free();
1614202719Sgabor			bmachine.readsp--;
1615202719Sgabor		}
1616202719Sgabor		skip_until_mark();
1617202719Sgabor	}
1618202719Sgabor}
1619202719Sgabor
1620202719Sgaborstatic void
1621202719Sgaborskip_until_mark(void)
1622202719Sgabor{
1623202719Sgabor
1624202719Sgabor	for (;;) {
1625203438Sgabor		switch (readch()) {
1626202719Sgabor		case 'M':
1627202719Sgabor			return;
1628202719Sgabor		case EOF:
1629202719Sgabor			errx(1, "mark not found");
1630202719Sgabor			return;
1631202719Sgabor		case 'l':
1632202719Sgabor		case 'L':
1633202719Sgabor		case 's':
1634202719Sgabor		case 'S':
1635202719Sgabor		case ':':
1636202719Sgabor		case ';':
1637202719Sgabor		case '<':
1638202719Sgabor		case '>':
1639202719Sgabor		case '=':
1640202719Sgabor			readreg();
1641202719Sgabor			if (readch() == 'e')
1642202719Sgabor				readreg();
1643202719Sgabor			else
1644202719Sgabor				unreadch();
1645202719Sgabor			break;
1646202719Sgabor		case '[':
1647202719Sgabor			free(read_string(&bmachine.readstack[bmachine.readsp]));
1648202719Sgabor			break;
1649202719Sgabor		case '!':
1650203438Sgabor			switch (readch()) {
1651202719Sgabor				case '<':
1652202719Sgabor				case '>':
1653202719Sgabor				case '=':
1654202719Sgabor					readreg();
1655202719Sgabor					if (readch() == 'e')
1656202719Sgabor						readreg();
1657202719Sgabor					else
1658202719Sgabor						unreadch();
1659202719Sgabor					break;
1660202719Sgabor				default:
1661202719Sgabor					free(readline());
1662202719Sgabor					break;
1663202719Sgabor			}
1664202719Sgabor			break;
1665202719Sgabor		default:
1666202719Sgabor			break;
1667202719Sgabor		}
1668202719Sgabor	}
1669202719Sgabor}
1670202719Sgabor
1671202719Sgaborstatic void
1672202719Sgaborparse_number(void)
1673202719Sgabor{
1674202719Sgabor
1675202719Sgabor	unreadch();
1676202719Sgabor	push_number(readnumber(&bmachine.readstack[bmachine.readsp],
1677202719Sgabor	    bmachine.ibase));
1678202719Sgabor}
1679202719Sgabor
1680202719Sgaborstatic void
1681202719Sgaborunknown(void)
1682202719Sgabor{
1683202719Sgabor	int ch = bmachine.readstack[bmachine.readsp].lastchar;
1684202719Sgabor	warnx("%c (0%o) is unimplemented", ch, ch);
1685202719Sgabor}
1686202719Sgabor
1687202719Sgaborstatic void
1688202719Sgaboreval_string(char *p)
1689202719Sgabor{
1690202719Sgabor	int	 ch;
1691202719Sgabor
1692202719Sgabor	if (bmachine.readsp > 0) {
1693202719Sgabor		/* Check for tail call. Do not recurse in that case. */
1694202719Sgabor		ch = readch();
1695202719Sgabor		if (ch == EOF) {
1696202719Sgabor			src_free();
1697202719Sgabor			src_setstring(&bmachine.readstack[bmachine.readsp], p);
1698202719Sgabor			return;
1699202719Sgabor		} else
1700202719Sgabor			unreadch();
1701202719Sgabor	}
1702202719Sgabor	if (bmachine.readsp == bmachine.readstack_sz - 1) {
1703202719Sgabor		size_t newsz = bmachine.readstack_sz * 2;
1704202719Sgabor		struct source *stack;
1705202719Sgabor		stack = realloc(bmachine.readstack, newsz *
1706202719Sgabor		    sizeof(struct source));
1707202719Sgabor		if (stack == NULL)
1708202719Sgabor			err(1, "recursion too deep");
1709202719Sgabor		bmachine.readstack_sz = newsz;
1710202719Sgabor		bmachine.readstack = stack;
1711202719Sgabor	}
1712202719Sgabor	src_setstring(&bmachine.readstack[++bmachine.readsp], p);
1713202719Sgabor}
1714202719Sgabor
1715202719Sgaborstatic void
1716202719Sgaboreval_line(void)
1717202719Sgabor{
1718202719Sgabor	/* Always read from stdin */
1719202719Sgabor	struct source	 in;
1720202719Sgabor	char		*p;
1721202719Sgabor
1722202719Sgabor	clearerr(stdin);
1723202719Sgabor	src_setstream(&in, stdin);
1724202719Sgabor	p = (*in.vtable->readline)(&in);
1725202719Sgabor	eval_string(p);
1726202719Sgabor}
1727202719Sgabor
1728202719Sgaborstatic void
1729202719Sgaboreval_tos(void)
1730202719Sgabor{
1731202719Sgabor	char	*p;
1732202719Sgabor
1733202719Sgabor	p = pop_string();
1734202719Sgabor	if (p == NULL)
1735202719Sgabor		return;
1736202719Sgabor	eval_string(p);
1737202719Sgabor}
1738202719Sgabor
1739202719Sgaborvoid
1740202719Sgaboreval(void)
1741202719Sgabor{
1742202719Sgabor	int	 ch;
1743202719Sgabor
1744202719Sgabor	for (;;) {
1745202719Sgabor		ch = readch();
1746202719Sgabor		if (ch == EOF) {
1747202719Sgabor			if (bmachine.readsp == 0)
1748202719Sgabor				return;
1749202719Sgabor			src_free();
1750202719Sgabor			bmachine.readsp--;
1751202719Sgabor			continue;
1752202719Sgabor		}
1753202719Sgabor		if (bmachine.interrupted) {
1754202719Sgabor			if (bmachine.readsp > 0) {
1755202719Sgabor				src_free();
1756202719Sgabor				bmachine.readsp--;
1757202719Sgabor				continue;
1758202719Sgabor			} else
1759202719Sgabor				bmachine.interrupted = false;
1760202719Sgabor		}
1761202719Sgabor#ifdef DEBUGGING
1762202719Sgabor		fprintf(stderr, "# %c\n", ch);
1763202719Sgabor		stack_print(stderr, &bmachine.stack, "* ",
1764202719Sgabor		    bmachine.obase);
1765202719Sgabor		fprintf(stderr, "%zd =>\n", bmachine.readsp);
1766202719Sgabor#endif
1767202719Sgabor
1768202719Sgabor		if (0 <= ch && ch < (signed)UCHAR_MAX)
1769202719Sgabor			(*jump_table[ch])();
1770202719Sgabor		else
1771202719Sgabor			warnx("internal error: opcode %d", ch);
1772202719Sgabor
1773202719Sgabor#ifdef DEBUGGING
1774202719Sgabor		stack_print(stderr, &bmachine.stack, "* ",
1775202719Sgabor		    bmachine.obase);
1776202719Sgabor		fprintf(stderr, "%zd ==\n", bmachine.readsp);
1777202719Sgabor#endif
1778202719Sgabor	}
1779202719Sgabor}
1780