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