Annotation of src/usr.bin/dc/bcode.c, Revision 1.59
1.59 ! otto 1: /* $OpenBSD: bcode.c,v 1.58 2017/12/02 12:43:18 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);
69: static __inline void clear_stack(void);
70: static __inline 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.18 otto 74: static __inline void print_stack(void);
1.1 otto 75: static __inline 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:
480: static __inline void
481: clear_stack(void)
482: {
483: stack_clear(&bmachine.stack);
484: }
485:
486: static __inline void
487: print_stack(void)
488: {
489: stack_print(stdout, &bmachine.stack, "", bmachine.obase);
490: }
491:
492: static __inline void
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.50 otto 499: }
500: else
501: warnx("stack empty");
502: }
503:
504: static void
505: print_err(void)
506: {
507: struct value *value = tos();
508: if (value != NULL) {
509: print_value(stderr, value, "", bmachine.obase);
510: (void)putc('\n', stderr);
1.1 otto 511: }
512: else
513: warnx("stack empty");
514: }
515:
1.14 otto 516: static void
1.1 otto 517: pop_print(void)
518: {
519: struct value *value = pop();
1.14 otto 520:
1.1 otto 521: if (value != NULL) {
522: switch (value->type) {
523: case BCODE_NONE:
524: break;
525: case BCODE_NUMBER:
526: normalize(value->u.num, 0);
527: print_ascii(stdout, value->u.num);
1.31 otto 528: (void)fflush(stdout);
1.1 otto 529: break;
530: case BCODE_STRING:
1.31 otto 531: (void)fputs(value->u.string, stdout);
532: (void)fflush(stdout);
1.1 otto 533: break;
534: }
535: stack_free_value(value);
536: }
537: }
538:
1.14 otto 539: static void
540: pop_printn(void)
541: {
542: struct value *value = pop();
543:
544: if (value != NULL) {
545: print_value(stdout, value, "", bmachine.obase);
1.31 otto 546: (void)fflush(stdout);
1.14 otto 547: stack_free_value(value);
548: }
549: }
550:
1.1 otto 551: static __inline void
552: dup(void)
553: {
554: stack_dup(&bmachine.stack);
1.13 otto 555: }
556:
557: static void
558: swap(void)
559: {
560: stack_swap(&bmachine.stack);
1.17 otto 561: }
562:
563: static void
564: drop(void)
565: {
566: struct value *v = pop();
567: if (v != NULL)
568: stack_free_value(v);
1.1 otto 569: }
570:
571: static void
572: get_scale(void)
573: {
574: struct number *n;
575:
576: n = new_number();
577: bn_check(BN_set_word(n->number, bmachine.scale));
578: push_number(n);
579: }
580:
581: static void
582: set_scale(void)
583: {
584: struct number *n;
585: u_long scale;
586:
587: n = pop_number();
588: if (n != NULL) {
1.44 otto 589: if (BN_is_negative(n->number))
1.1 otto 590: warnx("scale must be a nonnegative number");
591: else {
592: scale = get_ulong(n);
1.34 otto 593: if (scale != BN_MASK2 && scale <= UINT_MAX)
594: bmachine.scale = (u_int)scale;
1.1 otto 595: else
596: warnx("scale too large");
597: }
598: free_number(n);
599: }
600: }
601:
602: static void
603: get_obase(void)
604: {
605: struct number *n;
606:
607: n = new_number();
608: bn_check(BN_set_word(n->number, bmachine.obase));
609: push_number(n);
610: }
611:
612: static void
613: set_obase(void)
614: {
615: struct number *n;
616: u_long base;
617:
618: n = pop_number();
619: if (n != NULL) {
620: base = get_ulong(n);
1.34 otto 621: if (base != BN_MASK2 && base > 1 && base <= UINT_MAX)
622: bmachine.obase = (u_int)base;
1.1 otto 623: else
624: warnx("output base must be a number greater than 1");
625: free_number(n);
626: }
627: }
628:
629: static void
630: get_ibase(void)
631: {
632: struct number *n;
633:
634: n = new_number();
635: bn_check(BN_set_word(n->number, bmachine.ibase));
636: push_number(n);
637: }
638:
639: static void
640: set_ibase(void)
641: {
642: struct number *n;
643: u_long base;
644:
645: n = pop_number();
646: if (n != NULL) {
647: base = get_ulong(n);
648: if (base != BN_MASK2 && 2 <= base && base <= 16)
1.34 otto 649: bmachine.ibase = (u_int)base;
1.1 otto 650: else
651: warnx("input base must be a number between 2 and 16 "
652: "(inclusive)");
653: free_number(n);
654: }
655: }
656:
657: static void
658: stackdepth(void)
659: {
1.33 otto 660: size_t i;
1.1 otto 661: struct number *n;
662:
663: i = stack_size(&bmachine.stack);
664: n = new_number();
665: bn_check(BN_set_word(n->number, i));
666: push_number(n);
667: }
668:
669: static void
670: push_scale(void)
671: {
672: struct value *value;
673: u_int scale = 0;
674: struct number *n;
675:
676:
677: value = pop();
678: if (value != NULL) {
679: switch (value->type) {
680: case BCODE_NONE:
681: return;
682: case BCODE_NUMBER:
683: scale = value->u.num->scale;
684: break;
685: case BCODE_STRING:
686: break;
687: }
688: stack_free_value(value);
689: n = new_number();
690: bn_check(BN_set_word(n->number, scale));
691: push_number(n);
692: }
693: }
694:
695: static u_int
696: count_digits(const struct number *n)
697: {
1.57 otto 698: BIGNUM *int_part, *a, *p;
699: uint d;
700: const uint64_t c = 1292913986; /* floor(2^32 * log_10(2)) */
701: int bits;
1.1 otto 702:
703: if (BN_is_zero(n->number))
1.58 otto 704: return n->scale;
1.1 otto 705:
1.57 otto 706: int_part = BN_new();
707: bn_checkp(int_part);
708:
709: split_number(n, int_part, NULL);
710: bits = BN_num_bits(int_part);
711:
712: if (bits == 0)
713: d = 0;
714: else {
715: /*
716: * Estimate number of decimal digits based on number of bits.
717: * Divide 2^32 factor out by shifting
718: */
719: d = (c * bits) >> 32;
720:
721: /* If close to a possible rounding error fix if needed */
722: if (d != (c * (bits - 1)) >> 32) {
723: a = BN_new();
724: bn_checkp(a);
725: p = BN_new();
726: bn_checkp(p);
727:
728: bn_check(BN_set_word(a, 10));
729: bn_check(BN_set_word(p, d));
1.59 ! otto 730: bn_check(BN_exp(a, a, p, bmachine.ctx));
1.57 otto 731:
732: if (BN_ucmp(int_part, a) >= 0)
733: d++;
734:
735: BN_free(a);
736: BN_free(p);
737: } else
738: d++;
739: }
740:
741: BN_free(int_part);
742:
743: return d + n->scale;
1.1 otto 744: }
745:
746: static void
747: num_digits(void)
748: {
749: struct value *value;
1.34 otto 750: size_t digits;
1.14 otto 751: struct number *n = NULL;
1.1 otto 752:
753: value = pop();
754: if (value != NULL) {
755: switch (value->type) {
756: case BCODE_NONE:
1.14 otto 757: return;
1.1 otto 758: case BCODE_NUMBER:
759: digits = count_digits(value->u.num);
760: n = new_number();
761: bn_check(BN_set_word(n->number, digits));
762: break;
763: case BCODE_STRING:
764: digits = strlen(value->u.string);
765: n = new_number();
766: bn_check(BN_set_word(n->number, digits));
767: break;
768: }
1.14 otto 769: stack_free_value(value);
770: push_number(n);
771: }
772: }
773:
774: static void
775: to_ascii(void)
776: {
777: char str[2];
778: struct value *value;
779: struct number *n;
780:
781: value = pop();
782: if (value != NULL) {
783: str[1] = '\0';
784: switch (value->type) {
785: case BCODE_NONE:
786: return;
787: case BCODE_NUMBER:
788: n = value->u.num;
789: normalize(n, 0);
790: if (BN_num_bits(n->number) > 8)
791: bn_check(BN_mask_bits(n->number, 8));
1.33 otto 792: str[0] = (char)BN_get_word(n->number);
1.14 otto 793: break;
794: case BCODE_STRING:
795: str[0] = value->u.string[0];
796: break;
797: }
798: stack_free_value(value);
799: push_string(bstrdup(str));
1.1 otto 800: }
801: }
802:
1.18 otto 803: static int
804: readreg(void)
805: {
1.32 otto 806: int idx, ch1, ch2;
1.18 otto 807:
1.32 otto 808: idx = readch();
809: if (idx == 0xff && bmachine.extended_regs) {
1.18 otto 810: ch1 = readch();
811: ch2 = readch();
812: if (ch1 == EOF || ch2 == EOF) {
813: warnx("unexpected eof");
1.32 otto 814: idx = -1;
1.18 otto 815: } else
1.32 otto 816: idx = (ch1 << 8) + ch2 + UCHAR_MAX + 1;
1.18 otto 817: }
1.32 otto 818: if (idx < 0 || idx >= bmachine.reg_array_size) {
819: warnx("internal error: reg num = %d", idx);
820: idx = -1;
1.18 otto 821: }
1.32 otto 822: return idx;
1.18 otto 823: }
824:
1.1 otto 825: static void
826: load(void)
827: {
1.32 otto 828: int idx;
1.1 otto 829: struct value *v, copy;
1.5 otto 830: struct number *n;
1.1 otto 831:
1.32 otto 832: idx = readreg();
833: if (idx >= 0) {
834: v = stack_tos(&bmachine.reg[idx]);
1.5 otto 835: if (v == NULL) {
836: n = new_number();
1.51 otto 837: bn_check(BN_set_word(n->number, 0));
1.5 otto 838: push_number(n);
839: } else
1.1 otto 840: push(stack_dup_value(v, ©));
1.18 otto 841: }
1.1 otto 842: }
843:
844: static void
845: store(void)
846: {
1.32 otto 847: int idx;
1.1 otto 848: struct value *val;
849:
1.32 otto 850: idx = readreg();
851: if (idx >= 0) {
1.1 otto 852: val = pop();
853: if (val == NULL) {
854: return;
855: }
1.32 otto 856: stack_set_tos(&bmachine.reg[idx], val);
1.18 otto 857: }
1.1 otto 858: }
859:
860: static void
861: load_stack(void)
862: {
1.32 otto 863: int idx;
1.1 otto 864: struct stack *stack;
1.37 otto 865: struct value *value;
1.1 otto 866:
1.32 otto 867: idx = readreg();
868: if (idx >= 0) {
869: stack = &bmachine.reg[idx];
1.1 otto 870: value = NULL;
871: if (stack_size(stack) > 0) {
872: value = stack_pop(stack);
873: }
874: if (value != NULL)
1.37 otto 875: push(value);
1.1 otto 876: else
877: warnx("stack register '%c' (0%o) is empty",
1.32 otto 878: idx, idx);
1.18 otto 879: }
1.1 otto 880: }
881:
882: static void
883: store_stack(void)
884: {
1.32 otto 885: int idx;
1.1 otto 886: struct value *value;
887:
1.32 otto 888: idx = readreg();
889: if (idx >= 0) {
1.1 otto 890: value = pop();
891: if (value == NULL)
892: return;
1.32 otto 893: stack_push(&bmachine.reg[idx], value);
1.18 otto 894: }
1.1 otto 895: }
896:
897: static void
898: load_array(void)
899: {
900: int reg;
901: struct number *inumber, *n;
1.32 otto 902: u_long idx;
1.1 otto 903: struct stack *stack;
904: struct value *v, copy;
905:
1.18 otto 906: reg = readreg();
907: if (reg >= 0) {
1.1 otto 908: inumber = pop_number();
909: if (inumber == NULL)
910: return;
1.32 otto 911: idx = get_ulong(inumber);
1.44 otto 912: if (BN_is_negative(inumber->number))
1.32 otto 913: warnx("negative idx");
914: else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX)
915: warnx("idx too big");
1.1 otto 916: else {
917: stack = &bmachine.reg[reg];
1.32 otto 918: v = frame_retrieve(stack, idx);
1.39 otto 919: if (v == NULL || v->type == BCODE_NONE) {
1.1 otto 920: n = new_number();
1.51 otto 921: bn_check(BN_set_word(n->number, 0));
1.1 otto 922: push_number(n);
923: }
924: else
925: push(stack_dup_value(v, ©));
926: }
927: free_number(inumber);
1.18 otto 928: }
1.1 otto 929: }
930:
931: static void
932: store_array(void)
933: {
934: int reg;
935: struct number *inumber;
1.32 otto 936: u_long idx;
1.1 otto 937: struct value *value;
938: struct stack *stack;
939:
1.18 otto 940: reg = readreg();
941: if (reg >= 0) {
1.1 otto 942: inumber = pop_number();
1.6 otto 943: if (inumber == NULL)
944: return;
1.1 otto 945: value = pop();
1.6 otto 946: if (value == NULL) {
947: free_number(inumber);
1.1 otto 948: return;
949: }
1.32 otto 950: idx = get_ulong(inumber);
1.44 otto 951: if (BN_is_negative(inumber->number)) {
1.32 otto 952: warnx("negative idx");
1.1 otto 953: stack_free_value(value);
1.32 otto 954: } else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) {
955: warnx("idx too big");
1.1 otto 956: stack_free_value(value);
957: } else {
958: stack = &bmachine.reg[reg];
1.32 otto 959: frame_assign(stack, idx, value);
1.1 otto 960: }
961: free_number(inumber);
1.18 otto 962: }
1.1 otto 963: }
964:
965: static void
966: push_line(void)
967: {
968: push_string(read_string(&bmachine.readstack[bmachine.readsp]));
1.14 otto 969: }
970:
971: static void
972: comment(void)
973: {
974: free(readline());
1.1 otto 975: }
976:
977: static void
978: badd(void)
979: {
980: struct number *a, *b;
981: struct number *r;
982:
983: a = pop_number();
1.49 otto 984: if (a == NULL)
1.1 otto 985: return;
986: b = pop_number();
987: if (b == NULL) {
988: push_number(a);
989: return;
990: }
991:
992: r = new_number();
993: r->scale = max(a->scale, b->scale);
994: if (r->scale > a->scale)
995: normalize(a, r->scale);
996: else if (r->scale > b->scale)
997: normalize(b, r->scale);
998: bn_check(BN_add(r->number, a->number, b->number));
999: push_number(r);
1000: free_number(a);
1001: free_number(b);
1002: }
1003:
1004: static void
1005: bsub(void)
1006: {
1007: struct number *a, *b;
1008: struct number *r;
1009:
1010: a = pop_number();
1.49 otto 1011: if (a == NULL)
1.1 otto 1012: return;
1013: b = pop_number();
1014: if (b == NULL) {
1015: push_number(a);
1016: return;
1017: }
1018:
1019: r = new_number();
1020:
1021: r->scale = max(a->scale, b->scale);
1022: if (r->scale > a->scale)
1023: normalize(a, r->scale);
1024: else if (r->scale > b->scale)
1025: normalize(b, r->scale);
1026: bn_check(BN_sub(r->number, b->number, a->number));
1027: push_number(r);
1028: free_number(a);
1029: free_number(b);
1030: }
1031:
1032: void
1.45 otto 1033: bmul_number(struct number *r, struct number *a, struct number *b, u_int scale)
1.1 otto 1034: {
1035: /* Create copies of the scales, since r might be equal to a or b */
1036: u_int ascale = a->scale;
1037: u_int bscale = b->scale;
1038: u_int rscale = ascale + bscale;
1039:
1.59 ! otto 1040: bn_check(BN_mul(r->number, a->number, b->number, bmachine.ctx));
1.1 otto 1041:
1.45 otto 1042: r->scale = rscale;
1043: if (rscale > bmachine.scale && rscale > ascale && rscale > bscale)
1044: normalize(r, max(scale, max(ascale, bscale)));
1.1 otto 1045: }
1046:
1047: static void
1048: bmul(void)
1049: {
1050: struct number *a, *b;
1051: struct number *r;
1052:
1053: a = pop_number();
1.49 otto 1054: if (a == NULL)
1.1 otto 1055: return;
1056: b = pop_number();
1057: if (b == NULL) {
1058: push_number(a);
1059: return;
1060: }
1061:
1062: r = new_number();
1.45 otto 1063: bmul_number(r, a, b, bmachine.scale);
1.1 otto 1064:
1065: push_number(r);
1066: free_number(a);
1067: free_number(b);
1068: }
1069:
1070: static void
1071: bdiv(void)
1072: {
1073: struct number *a, *b;
1074: struct number *r;
1075: u_int scale;
1076:
1077: a = pop_number();
1.49 otto 1078: if (a == NULL)
1.1 otto 1079: return;
1080: b = pop_number();
1081: if (b == NULL) {
1082: push_number(a);
1083: return;
1084: }
1085:
1086: r = new_number();
1087: r->scale = bmachine.scale;
1088: scale = max(a->scale, b->scale);
1089:
1090: if (BN_is_zero(a->number))
1091: warnx("divide by zero");
1092: else {
1093: normalize(a, scale);
1094: normalize(b, scale + r->scale);
1095:
1.59 ! otto 1096: bn_check(BN_div(r->number, NULL, b->number, a->number, bmachine.ctx));
1.1 otto 1097: }
1098: push_number(r);
1099: free_number(a);
1100: free_number(b);
1101: }
1102:
1103: static void
1104: bmod(void)
1105: {
1106: struct number *a, *b;
1107: struct number *r;
1108: u_int scale;
1109:
1110: a = pop_number();
1.49 otto 1111: if (a == NULL)
1.1 otto 1112: return;
1113: b = pop_number();
1114: if (b == NULL) {
1115: push_number(a);
1116: return;
1117: }
1118:
1119: r = new_number();
1120: scale = max(a->scale, b->scale);
1121: r->scale = max(b->scale, a->scale + bmachine.scale);
1122:
1123: if (BN_is_zero(a->number))
1124: warnx("remainder by zero");
1125: else {
1126: normalize(a, scale);
1127: normalize(b, scale + bmachine.scale);
1128:
1.59 ! otto 1129: bn_check(BN_mod(r->number, b->number, a->number, bmachine.ctx));
1.1 otto 1130: }
1131: push_number(r);
1.8 otto 1132: free_number(a);
1133: free_number(b);
1134: }
1135:
1136: static void
1137: bdivmod(void)
1138: {
1139: struct number *a, *b;
1140: struct number *rdiv, *rmod;
1141: u_int scale;
1142:
1143: a = pop_number();
1.49 otto 1144: if (a == NULL)
1.8 otto 1145: return;
1146: b = pop_number();
1147: if (b == NULL) {
1148: push_number(a);
1149: return;
1150: }
1151:
1152: rdiv = new_number();
1153: rmod = new_number();
1154: rdiv->scale = bmachine.scale;
1155: rmod->scale = max(b->scale, a->scale + bmachine.scale);
1156: scale = max(a->scale, b->scale);
1157:
1158: if (BN_is_zero(a->number))
1159: warnx("divide by zero");
1160: else {
1161: normalize(a, scale);
1162: normalize(b, scale + bmachine.scale);
1163:
1164: bn_check(BN_div(rdiv->number, rmod->number,
1.59 ! otto 1165: b->number, a->number, bmachine.ctx));
1.8 otto 1166: }
1167: push_number(rdiv);
1168: push_number(rmod);
1.1 otto 1169: free_number(a);
1170: free_number(b);
1171: }
1172:
1173: static void
1174: bexp(void)
1175: {
1176: struct number *a, *p;
1177: struct number *r;
1178: bool neg;
1.45 otto 1179: u_int rscale;
1.1 otto 1180:
1181: p = pop_number();
1.49 otto 1182: if (p == NULL)
1.1 otto 1183: return;
1184: a = pop_number();
1185: if (a == NULL) {
1186: push_number(p);
1187: return;
1188: }
1189:
1.43 otto 1190: if (p->scale != 0) {
1191: BIGNUM *i, *f;
1192: i = BN_new();
1193: bn_checkp(i);
1194: f = BN_new();
1195: bn_checkp(f);
1196: split_number(p, i, f);
1197: if (!BN_is_zero(f))
1198: warnx("Runtime warning: non-zero fractional part in exponent");
1199: BN_free(i);
1200: BN_free(f);
1201: }
1202:
1.1 otto 1203: normalize(p, 0);
1204:
1205: neg = false;
1.43 otto 1206: if (BN_is_negative(p->number)) {
1.1 otto 1207: neg = true;
1208: negate(p);
1.45 otto 1209: rscale = bmachine.scale;
1.1 otto 1210: } else {
1.53 otto 1211: /* Posix bc says min(a.scale * b, max(a.scale, scale)) */
1.1 otto 1212: u_long b;
1213: u_int m;
1214:
1215: b = BN_get_word(p->number);
1216: m = max(a->scale, bmachine.scale);
1.45 otto 1217: rscale = a->scale * (u_int)b;
1218: if (rscale > m || (a->scale > 0 && (b == BN_MASK2 ||
1.34 otto 1219: b > UINT_MAX)))
1.45 otto 1220: rscale = m;
1.1 otto 1221: }
1.2 deraadt 1222:
1.1 otto 1223: if (BN_is_zero(p->number)) {
1224: r = new_number();
1225: bn_check(BN_one(r->number));
1.45 otto 1226: normalize(r, rscale);
1.1 otto 1227: } else {
1.45 otto 1228: u_int ascale, mscale;
1229:
1230: ascale = a->scale;
1.1 otto 1231: while (!BN_is_bit_set(p->number, 0)) {
1.45 otto 1232: ascale *= 2;
1233: bmul_number(a, a, a, ascale);
1.1 otto 1234: bn_check(BN_rshift1(p->number, p->number));
1235: }
1236:
1237: r = dup_number(a);
1238: bn_check(BN_rshift1(p->number, p->number));
1239:
1.45 otto 1240: mscale = ascale;
1.1 otto 1241: while (!BN_is_zero(p->number)) {
1.45 otto 1242: ascale *= 2;
1243: bmul_number(a, a, a, ascale);
1244: if (BN_is_bit_set(p->number, 0)) {
1245: mscale += ascale;
1246: bmul_number(r, r, a, mscale);
1247: }
1.1 otto 1248: bn_check(BN_rshift1(p->number, p->number));
1249: }
1250:
1251: if (neg) {
1252: BIGNUM *one;
1253:
1254: one = BN_new();
1255: bn_checkp(one);
1.31 otto 1256: bn_check(BN_one(one));
1.45 otto 1257: scale_number(one, r->scale + rscale);
1.43 otto 1258:
1259: if (BN_is_zero(r->number))
1260: warnx("divide by zero");
1261: else
1262: bn_check(BN_div(r->number, NULL, one,
1.59 ! otto 1263: r->number, bmachine.ctx));
1.1 otto 1264: BN_free(one);
1.45 otto 1265: r->scale = rscale;
1.29 otto 1266: } else
1.45 otto 1267: normalize(r, rscale);
1.1 otto 1268: }
1269: push_number(r);
1270: free_number(a);
1271: free_number(p);
1272: }
1273:
1274: static void
1275: bsqrt(void)
1276: {
1277: struct number *n;
1278: struct number *r;
1.56 otto 1279: BIGNUM *x, *y, *t;
1.25 otto 1280: u_int scale, onecount;
1.1 otto 1281:
1.25 otto 1282: onecount = 0;
1.1 otto 1283: n = pop_number();
1.49 otto 1284: if (n == NULL)
1.1 otto 1285: return;
1286: if (BN_is_zero(n->number)) {
1287: r = new_number();
1288: push_number(r);
1.44 otto 1289: } else if (BN_is_negative(n->number))
1.1 otto 1290: warnx("square root of negative number");
1291: else {
1292: scale = max(bmachine.scale, n->scale);
1293: normalize(n, 2*scale);
1294: x = BN_dup(n->number);
1295: bn_checkp(x);
1296: bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
1297: y = BN_new();
1298: bn_checkp(y);
1.56 otto 1299: do {
1.59 ! otto 1300: bn_check(BN_div(y, NULL, n->number, x, bmachine.ctx));
1.56 otto 1301: bn_check(BN_add(y, x, y));
1302: bn_check(BN_rshift1(y, y));
1303: bn_check(BN_sub(x, y, x));
1304: t = x;
1305: x = y;
1306: y = t;
1307: } while (!BN_is_zero(y) && (onecount += BN_is_one(y)) < 2);
1308: bn_check(BN_sub(y, x, y));
1.1 otto 1309: r = bmalloc(sizeof(*r));
1310: r->scale = scale;
1311: r->number = y;
1312: BN_free(x);
1313: push_number(r);
1314: }
1315:
1316: free_number(n);
1317: }
1318:
1319: static void
1.16 otto 1320: not(void)
1321: {
1322: struct number *a;
1323:
1324: a = pop_number();
1.49 otto 1325: if (a == NULL)
1.16 otto 1326: return;
1327: a->scale = 0;
1328: bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1));
1329: push_number(a);
1330: }
1331:
1332: static void
1.1 otto 1333: equal(void)
1334: {
1335: compare(BCODE_EQUAL);
1336: }
1337:
1338: static void
1.16 otto 1339: equal_numbers(void)
1340: {
1341: struct number *a, *b, *r;
1342:
1343: a = pop_number();
1.49 otto 1344: if (a == NULL)
1.16 otto 1345: return;
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:
1357: static void
1358: less_numbers(void)
1359: {
1360: struct number *a, *b, *r;
1361:
1362: a = pop_number();
1.49 otto 1363: if (a == NULL)
1.16 otto 1364: return;
1365: b = pop_number();
1366: if (b == NULL) {
1367: push_number(a);
1368: return;
1369: }
1370: r = new_number();
1371: bn_check(BN_set_word(r->number,
1372: compare_numbers(BCODE_LESS, a, b) ? 1 : 0));
1373: push_number(r);
1374: }
1375:
1376: static void
1377: lesseq_numbers(void)
1378: {
1379: struct number *a, *b, *r;
1380:
1381: a = pop_number();
1.49 otto 1382: if (a == NULL)
1.16 otto 1383: return;
1384: b = pop_number();
1385: if (b == NULL) {
1386: push_number(a);
1387: return;
1388: }
1389: r = new_number();
1390: bn_check(BN_set_word(r->number,
1391: compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
1392: push_number(r);
1393: }
1394:
1395: static void
1.1 otto 1396: less(void)
1397: {
1398: compare(BCODE_LESS);
1399: }
1400:
1401: static void
1402: not_compare(void)
1403: {
1404: switch (readch()) {
1405: case '<':
1.53 otto 1406: compare(BCODE_NOT_LESS);
1.1 otto 1407: break;
1408: case '>':
1.53 otto 1409: compare(BCODE_NOT_GREATER);
1.1 otto 1410: break;
1411: case '=':
1.53 otto 1412: compare(BCODE_NOT_EQUAL);
1.1 otto 1413: break;
1.2 deraadt 1414: default:
1.1 otto 1415: unreadch();
1.55 otto 1416: warnx("! command is deprecated");
1.1 otto 1417: break;
1418: }
1419: }
1420:
1421: static void
1422: greater(void)
1423: {
1424: compare(BCODE_GREATER);
1425: }
1426:
1.16 otto 1427: static bool
1428: compare_numbers(enum bcode_compare type, struct number *a, struct number *b)
1429: {
1430: u_int scale;
1431: int cmp;
1432:
1433: scale = max(a->scale, b->scale);
1434:
1435: if (scale > a->scale)
1436: normalize(a, scale);
1.30 otto 1437: else if (scale > b->scale)
1.16 otto 1438: normalize(b, scale);
1439:
1440: cmp = BN_cmp(a->number, b->number);
1441:
1442: free_number(a);
1443: free_number(b);
1444:
1445: switch (type) {
1446: case BCODE_EQUAL:
1447: return cmp == 0;
1448: case BCODE_NOT_EQUAL:
1449: return cmp != 0;
1450: case BCODE_LESS:
1451: return cmp < 0;
1452: case BCODE_NOT_LESS:
1453: return cmp >= 0;
1454: case BCODE_GREATER:
1455: return cmp > 0;
1456: case BCODE_NOT_GREATER:
1457: return cmp <= 0;
1458: }
1459: return false;
1460: }
1461:
1.1 otto 1462: static void
1463: compare(enum bcode_compare type)
1464: {
1.32 otto 1465: int idx, elseidx;
1.1 otto 1466: struct number *a, *b;
1467: bool ok;
1468: struct value *v;
1469:
1.32 otto 1470: elseidx = NO_ELSE;
1471: idx = readreg();
1.11 otto 1472: if (readch() == 'e')
1.32 otto 1473: elseidx = readreg();
1.11 otto 1474: else
1475: unreadch();
1.1 otto 1476:
1477: a = pop_number();
1.11 otto 1478: if (a == NULL)
1.1 otto 1479: return;
1480: b = pop_number();
1481: if (b == NULL) {
1482: push_number(a);
1483: return;
1484: }
1485:
1.16 otto 1486: ok = compare_numbers(type, a, b);
1.1 otto 1487:
1.32 otto 1488: if (!ok && elseidx != NO_ELSE)
1489: idx = elseidx;
1.11 otto 1490:
1.32 otto 1491: if (idx >= 0 && (ok || (!ok && elseidx != NO_ELSE))) {
1492: v = stack_tos(&bmachine.reg[idx]);
1.1 otto 1493: if (v == NULL)
1.32 otto 1494: warnx("register '%c' (0%o) is empty", idx, idx);
1.1 otto 1495: else {
1496: switch(v->type) {
1497: case BCODE_NONE:
1.32 otto 1498: warnx("register '%c' (0%o) is empty", idx, idx);
1.1 otto 1499: break;
1500: case BCODE_NUMBER:
1501: warn("eval called with non-string argument");
1502: break;
1503: case BCODE_STRING:
1504: eval_string(bstrdup(v->u.string));
1505: break;
1506: }
1507: }
1508: }
1509: }
1510:
1511:
1512: static void
1513: nop(void)
1514: {
1515: }
1516:
1.2 deraadt 1517: static void
1.1 otto 1518: quit(void)
1519: {
1.2 deraadt 1520: if (bmachine.readsp < 2)
1.1 otto 1521: exit(0);
1522: src_free();
1523: bmachine.readsp--;
1524: src_free();
1525: bmachine.readsp--;
1526: }
1527:
1528: static void
1529: quitN(void)
1530: {
1531: struct number *n;
1532: u_long i;
1533:
1534: n = pop_number();
1535: if (n == NULL)
1536: return;
1537: i = get_ulong(n);
1.37 otto 1538: free_number(n);
1.1 otto 1539: if (i == BN_MASK2 || i == 0)
1540: warnx("Q command requires a number >= 1");
1541: else if (bmachine.readsp < i)
1542: warnx("Q command argument exceeded string execution depth");
1543: else {
1544: while (i-- > 0) {
1545: src_free();
1546: bmachine.readsp--;
1547: }
1548: }
1549: }
1550:
1551: static void
1.9 otto 1552: skipN(void)
1553: {
1554: struct number *n;
1555: u_long i;
1556:
1557: n = pop_number();
1558: if (n == NULL)
1559: return;
1560: i = get_ulong(n);
1561: if (i == BN_MASK2)
1562: warnx("J command requires a number >= 0");
1563: else if (i > 0 && bmachine.readsp < i)
1564: warnx("J command argument exceeded string execution depth");
1565: else {
1566: while (i-- > 0) {
1567: src_free();
1568: bmachine.readsp--;
1569: }
1570: skip_until_mark();
1571: }
1572: }
1573:
1574: static void
1575: skip_until_mark(void)
1576: {
1577: for (;;) {
1.54 otto 1578: switch (readch()) {
1.9 otto 1579: case 'M':
1580: return;
1581: case EOF:
1582: errx(1, "mark not found");
1583: return;
1584: case 'l':
1585: case 'L':
1586: case 's':
1587: case 'S':
1588: case ':':
1589: case ';':
1590: case '<':
1591: case '>':
1592: case '=':
1.31 otto 1593: (void)readreg();
1.12 otto 1594: if (readch() == 'e')
1.31 otto 1595: (void)readreg();
1.12 otto 1596: else
1597: unreadch();
1.9 otto 1598: break;
1599: case '[':
1600: free(read_string(&bmachine.readstack[bmachine.readsp]));
1601: break;
1602: case '!':
1.54 otto 1603: switch (readch()) {
1.9 otto 1604: case '<':
1605: case '>':
1606: case '=':
1.31 otto 1607: (void)readreg();
1.12 otto 1608: if (readch() == 'e')
1.31 otto 1609: (void)readreg();
1.12 otto 1610: else
1611: unreadch();
1.9 otto 1612: break;
1613: default:
1614: free(readline());
1615: break;
1616: }
1617: break;
1618: default:
1619: break;
1620: }
1621: }
1622: }
1623:
1624: static void
1.1 otto 1625: parse_number(void)
1626: {
1627: unreadch();
1628: push_number(readnumber(&bmachine.readstack[bmachine.readsp],
1629: bmachine.ibase));
1630: }
1631:
1632: static void
1633: unknown(void)
1634: {
1635: int ch = bmachine.readstack[bmachine.readsp].lastchar;
1636: warnx("%c (0%o) is unimplemented", ch, ch);
1637: }
1638:
1639: static void
1640: eval_string(char *p)
1641: {
1642: int ch;
1643:
1644: if (bmachine.readsp > 0) {
1645: /* Check for tail call. Do not recurse in that case. */
1646: ch = readch();
1647: if (ch == EOF) {
1648: src_free();
1649: src_setstring(&bmachine.readstack[bmachine.readsp], p);
1650: return;
1651: } else
1652: unreadch();
1653: }
1.27 otto 1654: if (bmachine.readsp == bmachine.readstack_sz - 1) {
1655: size_t newsz = bmachine.readstack_sz * 2;
1656: struct source *stack;
1.46 doug 1657: stack = reallocarray(bmachine.readstack, newsz,
1.27 otto 1658: sizeof(struct source));
1659: if (stack == NULL)
1660: err(1, "recursion too deep");
1661: bmachine.readstack_sz = newsz;
1662: bmachine.readstack = stack;
1663: }
1.1 otto 1664: src_setstring(&bmachine.readstack[++bmachine.readsp], p);
1665: }
1666:
1667: static void
1668: eval_line(void)
1669: {
1670: /* Always read from stdin */
1671: struct source in;
1672: char *p;
1673:
1.38 otto 1674: clearerr(stdin);
1.1 otto 1675: src_setstream(&in, stdin);
1676: p = (*in.vtable->readline)(&in);
1677: eval_string(p);
1678: }
1679:
1680: static void
1681: eval_tos(void)
1682: {
1683: char *p;
1684:
1685: p = pop_string();
1.49 otto 1686: if (p != NULL)
1687: eval_string(p);
1.1 otto 1688: }
1689:
1690: void
1691: eval(void)
1692: {
1693: int ch;
1694:
1695: for (;;) {
1696: ch = readch();
1697: if (ch == EOF) {
1698: if (bmachine.readsp == 0)
1.24 otto 1699: return;
1.1 otto 1700: src_free();
1701: bmachine.readsp--;
1702: continue;
1.20 otto 1703: }
1704: if (bmachine.interrupted) {
1705: if (bmachine.readsp > 0) {
1706: src_free();
1707: bmachine.readsp--;
1708: continue;
1.22 otto 1709: } else
1.20 otto 1710: bmachine.interrupted = false;
1.1 otto 1711: }
1.9 otto 1712: #ifdef DEBUGGING
1.31 otto 1713: (void)fprintf(stderr, "# %c\n", ch);
1.9 otto 1714: stack_print(stderr, &bmachine.stack, "* ",
1715: bmachine.obase);
1.36 otto 1716: (void)fprintf(stderr, "%zd =>\n", bmachine.readsp);
1.9 otto 1717: #endif
1.1 otto 1718:
1.52 tom 1719: if (0 <= ch && ch < nitems(jump_table))
1.1 otto 1720: (*jump_table[ch])();
1721: else
1.52 tom 1722: unknown();
1.1 otto 1723:
1.9 otto 1724: #ifdef DEBUGGING
1725: stack_print(stderr, &bmachine.stack, "* ",
1726: bmachine.obase);
1.36 otto 1727: (void)fprintf(stderr, "%zd ==\n", bmachine.readsp);
1.9 otto 1728: #endif
1.1 otto 1729: }
1730: }