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