Annotation of src/usr.bin/dc/bcode.c, Revision 1.56
1.56 ! otto 1: /* $OpenBSD: bcode.c,v 1.55 2017/11/28 17:43:45 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.1 otto 49: };
50:
51: static struct bmachine bmachine;
1.20 otto 52: static void sighandler(int);
1.1 otto 53:
54: static __inline int readch(void);
1.31 otto 55: static __inline void unreadch(void);
1.1 otto 56: static __inline char *readline(void);
57: static __inline void src_free(void);
58:
59: static __inline u_int max(u_int, u_int);
60: static u_long get_ulong(struct number *);
61:
62: static __inline void push_number(struct number *);
63: static __inline void push_string(char *);
64: static __inline void push(struct value *);
65: static __inline struct value *tos(void);
66: static __inline struct number *pop_number(void);
67: static __inline char *pop_string(void);
68: static __inline void clear_stack(void);
69: static __inline void print_tos(void);
1.50 otto 70: static void print_err(void);
1.14 otto 71: static void pop_print(void);
72: static void pop_printn(void);
1.18 otto 73: static __inline void print_stack(void);
1.1 otto 74: static __inline void dup(void);
1.13 otto 75: static void swap(void);
1.17 otto 76: static void drop(void);
1.1 otto 77:
78: static void get_scale(void);
79: static void set_scale(void);
80: static void get_obase(void);
81: static void set_obase(void);
82: static void get_ibase(void);
83: static void set_ibase(void);
84: static void stackdepth(void);
85: static void push_scale(void);
86: static u_int count_digits(const struct number *);
87: static void num_digits(void);
1.14 otto 88: static void to_ascii(void);
1.1 otto 89: static void push_line(void);
1.14 otto 90: static void comment(void);
1.1 otto 91: static void badd(void);
92: static void bsub(void);
93: static void bmul(void);
94: static void bdiv(void);
95: static void bmod(void);
1.8 otto 96: static void bdivmod(void);
1.1 otto 97: static void bexp(void);
98: static void bsqrt(void);
1.16 otto 99: static void not(void);
100: static void equal_numbers(void);
101: static void less_numbers(void);
102: static void lesseq_numbers(void);
1.1 otto 103: static void equal(void);
104: static void less(void);
105: static void greater(void);
106: static void not_compare(void);
1.16 otto 107: static bool compare_numbers(enum bcode_compare, struct number *,
108: struct number *);
1.1 otto 109: static void compare(enum bcode_compare);
1.18 otto 110: static int readreg(void);
1.1 otto 111: static void load(void);
112: static void store(void);
113: static void load_stack(void);
114: static void store_stack(void);
115: static void load_array(void);
116: static void store_array(void);
117: static void nop(void);
118: static void quit(void);
119: static void quitN(void);
1.9 otto 120: static void skipN(void);
121: static void skip_until_mark(void);
1.1 otto 122: static void parse_number(void);
123: static void unknown(void);
124: static void eval_string(char *);
125: static void eval_line(void);
126: static void eval_tos(void);
127:
128:
129: typedef void (*opcode_function)(void);
130:
131: struct jump_entry {
132: u_char ch;
133: opcode_function f;
134: };
135:
1.52 tom 136: static opcode_function jump_table[UCHAR_MAX + 1];
1.1 otto 137:
138: static const struct jump_entry jump_table_data[] = {
1.14 otto 139: { ' ', nop },
140: { '!', not_compare },
141: { '#', comment },
142: { '%', bmod },
1.16 otto 143: { '(', less_numbers },
1.14 otto 144: { '*', bmul },
145: { '+', badd },
146: { '-', bsub },
147: { '.', parse_number },
148: { '/', bdiv },
1.1 otto 149: { '0', parse_number },
150: { '1', parse_number },
151: { '2', parse_number },
152: { '3', parse_number },
153: { '4', parse_number },
154: { '5', parse_number },
155: { '6', parse_number },
156: { '7', parse_number },
157: { '8', parse_number },
158: { '9', parse_number },
1.14 otto 159: { ':', store_array },
160: { ';', load_array },
161: { '<', less },
162: { '=', equal },
163: { '>', greater },
164: { '?', eval_line },
1.1 otto 165: { 'A', parse_number },
166: { 'B', parse_number },
167: { 'C', parse_number },
168: { 'D', parse_number },
169: { 'E', parse_number },
170: { 'F', parse_number },
1.16 otto 171: { 'G', equal_numbers },
1.14 otto 172: { 'I', get_ibase },
173: { 'J', skipN },
174: { 'K', get_scale },
1.1 otto 175: { 'L', load_stack },
1.14 otto 176: { 'M', nop },
1.16 otto 177: { 'N', not },
1.14 otto 178: { 'O', get_obase },
1.1 otto 179: { 'P', pop_print },
1.14 otto 180: { 'Q', quitN },
1.17 otto 181: { 'R', drop },
1.14 otto 182: { 'S', store_stack },
1.1 otto 183: { 'X', push_scale },
1.14 otto 184: { 'Z', num_digits },
1.1 otto 185: { '[', push_line },
1.14 otto 186: { '\f', nop },
187: { '\n', nop },
188: { '\r', nop },
189: { '\t', nop },
190: { '^', bexp },
191: { '_', parse_number },
192: { 'a', to_ascii },
1.1 otto 193: { 'c', clear_stack },
1.14 otto 194: { 'd', dup },
1.50 otto 195: { 'e', print_err },
1.14 otto 196: { 'f', print_stack },
1.1 otto 197: { 'i', set_ibase },
1.14 otto 198: { 'k', set_scale },
199: { 'l', load },
200: { 'n', pop_printn },
1.1 otto 201: { 'o', set_obase },
1.16 otto 202: { 'p', print_tos },
1.14 otto 203: { 'q', quit },
1.16 otto 204: { 'r', swap },
1.14 otto 205: { 's', store },
206: { 'v', bsqrt },
207: { 'x', eval_tos },
1.1 otto 208: { 'z', stackdepth },
1.16 otto 209: { '{', lesseq_numbers },
1.14 otto 210: { '~', bdivmod }
1.1 otto 211: };
212:
1.52 tom 213: #ifndef nitems
214: #define nitems(a) (sizeof((a)) / sizeof((a)[0]))
215: #endif
1.1 otto 216:
1.23 deraadt 217: /* ARGSUSED */
1.20 otto 218: static void
219: sighandler(int ignored)
220: {
221: bmachine.interrupted = true;
222: }
223:
1.1 otto 224: void
1.18 otto 225: init_bmachine(bool extended_registers)
1.1 otto 226: {
227: int i;
228:
1.18 otto 229: bmachine.extended_regs = extended_registers;
230: bmachine.reg_array_size = bmachine.extended_regs ?
231: REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL;
232:
1.35 deraadt 233: bmachine.reg = calloc(bmachine.reg_array_size,
1.18 otto 234: sizeof(bmachine.reg[0]));
235: if (bmachine.reg == NULL)
236: err(1, NULL);
237:
1.52 tom 238: for (i = 0; i < nitems(jump_table); i++)
1.1 otto 239: jump_table[i] = unknown;
1.52 tom 240:
241: for (i = 0; i < nitems(jump_table_data); i++) {
242: if ((unsigned int)jump_table_data[i].ch >= nitems(jump_table))
243: errx(1, "opcode '%c' overflows jump table",
244: jump_table_data[i].ch);
245: if (jump_table[jump_table_data[i].ch] != unknown)
246: errx(1, "opcode '%c' already assigned",
247: jump_table_data[i].ch);
1.1 otto 248: jump_table[jump_table_data[i].ch] = jump_table_data[i].f;
1.52 tom 249: }
1.1 otto 250:
251: stack_init(&bmachine.stack);
252:
1.18 otto 253: for (i = 0; i < bmachine.reg_array_size; i++)
1.1 otto 254: stack_init(&bmachine.reg[i]);
255:
1.27 otto 256: bmachine.readstack_sz = READSTACK_SIZE;
1.35 deraadt 257: bmachine.readstack = calloc(sizeof(struct source),
1.27 otto 258: bmachine.readstack_sz);
259: if (bmachine.readstack == NULL)
260: err(1, NULL);
1.1 otto 261: bmachine.obase = bmachine.ibase = 10;
1.31 otto 262: (void)signal(SIGINT, sighandler);
1.1 otto 263: }
264:
1.45 otto 265: u_int
266: bmachine_scale(void)
267: {
268: return bmachine.scale;
269: }
270:
1.1 otto 271: /* Reset the things needed before processing a (new) file */
272: void
273: reset_bmachine(struct source *src)
274: {
275: bmachine.readsp = 0;
276: bmachine.readstack[0] = *src;
277: }
278:
279: static __inline int
280: readch(void)
281: {
282: struct source *src = &bmachine.readstack[bmachine.readsp];
283:
284: return src->vtable->readchar(src);
285: }
286:
1.31 otto 287: static __inline void
1.1 otto 288: unreadch(void)
289: {
290: struct source *src = &bmachine.readstack[bmachine.readsp];
291:
1.31 otto 292: src->vtable->unreadchar(src);
1.1 otto 293: }
294:
295: static __inline char *
296: readline(void)
297: {
298: struct source *src = &bmachine.readstack[bmachine.readsp];
299:
300: return src->vtable->readline(src);
301: }
302:
303: static __inline void
304: src_free(void)
305: {
306: struct source *src = &bmachine.readstack[bmachine.readsp];
307:
308: src->vtable->free(src);
309: }
310:
1.10 otto 311: #ifdef DEBUGGING
1.1 otto 312: void
1.28 deraadt 313: pn(const char *str, const struct number *n)
1.1 otto 314: {
315: char *p = BN_bn2dec(n->number);
316: if (p == NULL)
317: err(1, "BN_bn2dec failed");
1.31 otto 318: (void)fputs(str, stderr);
319: (void)fprintf(stderr, " %s (%u)\n" , p, n->scale);
1.1 otto 320: OPENSSL_free(p);
321: }
322:
323: void
1.28 deraadt 324: pbn(const char *str, const BIGNUM *n)
1.1 otto 325: {
326: char *p = BN_bn2dec(n);
327: if (p == NULL)
328: err(1, "BN_bn2dec failed");
1.31 otto 329: (void)fputs(str, stderr);
330: (void)fprintf(stderr, " %s\n", p);
1.1 otto 331: OPENSSL_free(p);
332: }
333:
334: #endif
335:
336: static __inline u_int
337: max(u_int a, u_int b)
338: {
339: return a > b ? a : b;
340: }
341:
342: static unsigned long factors[] = {
343: 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
344: 100000000, 1000000000
345: };
346:
347: void
348: scale_number(BIGNUM *n, int s)
349: {
350: int abs_scale;
351:
352: if (s == 0)
353: return;
354:
355: abs_scale = s > 0 ? s : -s;
356:
357: if (abs_scale < sizeof(factors)/sizeof(factors[0])) {
358: if (s > 0)
359: bn_check(BN_mul_word(n, factors[abs_scale]));
360: else
1.31 otto 361: (void)BN_div_word(n, factors[abs_scale]);
1.1 otto 362: } else {
363: BIGNUM *a, *p;
364: BN_CTX *ctx;
365:
366: a = BN_new();
367: bn_checkp(a);
368: p = BN_new();
369: bn_checkp(p);
370: ctx = BN_CTX_new();
371: bn_checkp(ctx);
372:
373: bn_check(BN_set_word(a, 10));
374: bn_check(BN_set_word(p, abs_scale));
375: bn_check(BN_exp(a, a, p, ctx));
376: if (s > 0)
377: bn_check(BN_mul(n, n, a, ctx));
378: else
379: bn_check(BN_div(n, NULL, n, a, ctx));
380: BN_CTX_free(ctx);
381: BN_free(a);
382: BN_free(p);
383: }
384: }
385:
386: void
387: split_number(const struct number *n, BIGNUM *i, BIGNUM *f)
388: {
389: u_long rem;
390:
391: bn_checkp(BN_copy(i, n->number));
392:
393: if (n->scale == 0 && f != NULL)
1.51 otto 394: bn_check(BN_set_word(f, 0));
1.1 otto 395: else if (n->scale < sizeof(factors)/sizeof(factors[0])) {
396: rem = BN_div_word(i, factors[n->scale]);
397: if (f != NULL)
1.31 otto 398: bn_check(BN_set_word(f, rem));
1.1 otto 399: } else {
400: BIGNUM *a, *p;
401: BN_CTX *ctx;
402:
403: a = BN_new();
404: bn_checkp(a);
405: p = BN_new();
406: bn_checkp(p);
407: ctx = BN_CTX_new();
408: bn_checkp(ctx);
409:
410: bn_check(BN_set_word(a, 10));
411: bn_check(BN_set_word(p, n->scale));
412: bn_check(BN_exp(a, a, p, ctx));
413: bn_check(BN_div(i, f, n->number, a, ctx));
414: BN_CTX_free(ctx);
415: BN_free(a);
416: BN_free(p);
417: }
418: }
419:
1.41 otto 420: void
1.1 otto 421: normalize(struct number *n, u_int s)
422: {
423: scale_number(n->number, s - n->scale);
424: n->scale = s;
425: }
426:
427: static u_long
428: get_ulong(struct number *n)
429: {
430: normalize(n, 0);
431: return BN_get_word(n->number);
432: }
433:
434: void
435: negate(struct number *n)
436: {
1.44 otto 437: BN_set_negative(n->number, !BN_is_negative(n->number));
1.1 otto 438: }
439:
440: static __inline void
441: push_number(struct number *n)
442: {
443: stack_pushnumber(&bmachine.stack, n);
444: }
445:
446: static __inline void
447: push_string(char *string)
448: {
449: stack_pushstring(&bmachine.stack, string);
450: }
451:
452: static __inline void
453: push(struct value *v)
454: {
455: stack_push(&bmachine.stack, v);
456: }
457:
458: static __inline struct value *
459: tos(void)
460: {
461: return stack_tos(&bmachine.stack);
462: }
463:
464: static __inline struct value *
465: pop(void)
466: {
467: return stack_pop(&bmachine.stack);
468: }
469:
470: static __inline struct number *
471: pop_number(void)
472: {
473: return stack_popnumber(&bmachine.stack);
474: }
475:
476: static __inline char *
477: pop_string(void)
478: {
479: return stack_popstring(&bmachine.stack);
480: }
481:
482: static __inline void
483: clear_stack(void)
484: {
485: stack_clear(&bmachine.stack);
486: }
487:
488: static __inline void
489: print_stack(void)
490: {
491: stack_print(stdout, &bmachine.stack, "", bmachine.obase);
492: }
493:
494: static __inline void
495: print_tos(void)
496: {
497: struct value *value = tos();
498: if (value != NULL) {
499: print_value(stdout, value, "", bmachine.obase);
1.31 otto 500: (void)putchar('\n');
1.50 otto 501: }
502: else
503: warnx("stack empty");
504: }
505:
506: static void
507: print_err(void)
508: {
509: struct value *value = tos();
510: if (value != NULL) {
511: print_value(stderr, value, "", bmachine.obase);
512: (void)putc('\n', stderr);
1.1 otto 513: }
514: else
515: warnx("stack empty");
516: }
517:
1.14 otto 518: static void
1.1 otto 519: pop_print(void)
520: {
521: struct value *value = pop();
1.14 otto 522:
1.1 otto 523: if (value != NULL) {
524: switch (value->type) {
525: case BCODE_NONE:
526: break;
527: case BCODE_NUMBER:
528: normalize(value->u.num, 0);
529: print_ascii(stdout, value->u.num);
1.31 otto 530: (void)fflush(stdout);
1.1 otto 531: break;
532: case BCODE_STRING:
1.31 otto 533: (void)fputs(value->u.string, stdout);
534: (void)fflush(stdout);
1.1 otto 535: break;
536: }
537: stack_free_value(value);
538: }
539: }
540:
1.14 otto 541: static void
542: pop_printn(void)
543: {
544: struct value *value = pop();
545:
546: if (value != NULL) {
547: print_value(stdout, value, "", bmachine.obase);
1.31 otto 548: (void)fflush(stdout);
1.14 otto 549: stack_free_value(value);
550: }
551: }
552:
1.1 otto 553: static __inline void
554: dup(void)
555: {
556: stack_dup(&bmachine.stack);
1.13 otto 557: }
558:
559: static void
560: swap(void)
561: {
562: stack_swap(&bmachine.stack);
1.17 otto 563: }
564:
565: static void
566: drop(void)
567: {
568: struct value *v = pop();
569: if (v != NULL)
570: stack_free_value(v);
1.1 otto 571: }
572:
573: static void
574: get_scale(void)
575: {
576: struct number *n;
577:
578: n = new_number();
579: bn_check(BN_set_word(n->number, bmachine.scale));
580: push_number(n);
581: }
582:
583: static void
584: set_scale(void)
585: {
586: struct number *n;
587: u_long scale;
588:
589: n = pop_number();
590: if (n != NULL) {
1.44 otto 591: if (BN_is_negative(n->number))
1.1 otto 592: warnx("scale must be a nonnegative number");
593: else {
594: scale = get_ulong(n);
1.34 otto 595: if (scale != BN_MASK2 && scale <= UINT_MAX)
596: bmachine.scale = (u_int)scale;
1.1 otto 597: else
598: warnx("scale too large");
599: }
600: free_number(n);
601: }
602: }
603:
604: static void
605: get_obase(void)
606: {
607: struct number *n;
608:
609: n = new_number();
610: bn_check(BN_set_word(n->number, bmachine.obase));
611: push_number(n);
612: }
613:
614: static void
615: set_obase(void)
616: {
617: struct number *n;
618: u_long base;
619:
620: n = pop_number();
621: if (n != NULL) {
622: base = get_ulong(n);
1.34 otto 623: if (base != BN_MASK2 && base > 1 && base <= UINT_MAX)
624: bmachine.obase = (u_int)base;
1.1 otto 625: else
626: warnx("output base must be a number greater than 1");
627: free_number(n);
628: }
629: }
630:
631: static void
632: get_ibase(void)
633: {
634: struct number *n;
635:
636: n = new_number();
637: bn_check(BN_set_word(n->number, bmachine.ibase));
638: push_number(n);
639: }
640:
641: static void
642: set_ibase(void)
643: {
644: struct number *n;
645: u_long base;
646:
647: n = pop_number();
648: if (n != NULL) {
649: base = get_ulong(n);
650: if (base != BN_MASK2 && 2 <= base && base <= 16)
1.34 otto 651: bmachine.ibase = (u_int)base;
1.1 otto 652: else
653: warnx("input base must be a number between 2 and 16 "
654: "(inclusive)");
655: free_number(n);
656: }
657: }
658:
659: static void
660: stackdepth(void)
661: {
1.33 otto 662: size_t i;
1.1 otto 663: struct number *n;
664:
665: i = stack_size(&bmachine.stack);
666: n = new_number();
667: bn_check(BN_set_word(n->number, i));
668: push_number(n);
669: }
670:
671: static void
672: push_scale(void)
673: {
674: struct value *value;
675: u_int scale = 0;
676: struct number *n;
677:
678:
679: value = pop();
680: if (value != NULL) {
681: switch (value->type) {
682: case BCODE_NONE:
683: return;
684: case BCODE_NUMBER:
685: scale = value->u.num->scale;
686: break;
687: case BCODE_STRING:
688: break;
689: }
690: stack_free_value(value);
691: n = new_number();
692: bn_check(BN_set_word(n->number, scale));
693: push_number(n);
694: }
695: }
696:
697: static u_int
698: count_digits(const struct number *n)
699: {
700: struct number *int_part, *fract_part;
701: u_int i;
702:
703: if (BN_is_zero(n->number))
1.42 otto 704: return n->scale ? n->scale : 1;
1.1 otto 705:
706: int_part = new_number();
707: fract_part = new_number();
708: fract_part->scale = n->scale;
709: split_number(n, int_part->number, fract_part->number);
710:
711: i = 0;
712: while (!BN_is_zero(int_part->number)) {
1.31 otto 713: (void)BN_div_word(int_part->number, 10);
1.1 otto 714: i++;
715: }
716: free_number(int_part);
717: free_number(fract_part);
718: return i + n->scale;
719: }
720:
721: static void
722: num_digits(void)
723: {
724: struct value *value;
1.34 otto 725: size_t digits;
1.14 otto 726: struct number *n = NULL;
1.1 otto 727:
728: value = pop();
729: if (value != NULL) {
730: switch (value->type) {
731: case BCODE_NONE:
1.14 otto 732: return;
1.1 otto 733: case BCODE_NUMBER:
734: digits = count_digits(value->u.num);
735: n = new_number();
736: bn_check(BN_set_word(n->number, digits));
737: break;
738: case BCODE_STRING:
739: digits = strlen(value->u.string);
740: n = new_number();
741: bn_check(BN_set_word(n->number, digits));
742: break;
743: }
1.14 otto 744: stack_free_value(value);
745: push_number(n);
746: }
747: }
748:
749: static void
750: to_ascii(void)
751: {
752: char str[2];
753: struct value *value;
754: struct number *n;
755:
756: value = pop();
757: if (value != NULL) {
758: str[1] = '\0';
759: switch (value->type) {
760: case BCODE_NONE:
761: return;
762: case BCODE_NUMBER:
763: n = value->u.num;
764: normalize(n, 0);
765: if (BN_num_bits(n->number) > 8)
766: bn_check(BN_mask_bits(n->number, 8));
1.33 otto 767: str[0] = (char)BN_get_word(n->number);
1.14 otto 768: break;
769: case BCODE_STRING:
770: str[0] = value->u.string[0];
771: break;
772: }
773: stack_free_value(value);
774: push_string(bstrdup(str));
1.1 otto 775: }
776: }
777:
1.18 otto 778: static int
779: readreg(void)
780: {
1.32 otto 781: int idx, ch1, ch2;
1.18 otto 782:
1.32 otto 783: idx = readch();
784: if (idx == 0xff && bmachine.extended_regs) {
1.18 otto 785: ch1 = readch();
786: ch2 = readch();
787: if (ch1 == EOF || ch2 == EOF) {
788: warnx("unexpected eof");
1.32 otto 789: idx = -1;
1.18 otto 790: } else
1.32 otto 791: idx = (ch1 << 8) + ch2 + UCHAR_MAX + 1;
1.18 otto 792: }
1.32 otto 793: if (idx < 0 || idx >= bmachine.reg_array_size) {
794: warnx("internal error: reg num = %d", idx);
795: idx = -1;
1.18 otto 796: }
1.32 otto 797: return idx;
1.18 otto 798: }
799:
1.1 otto 800: static void
801: load(void)
802: {
1.32 otto 803: int idx;
1.1 otto 804: struct value *v, copy;
1.5 otto 805: struct number *n;
1.1 otto 806:
1.32 otto 807: idx = readreg();
808: if (idx >= 0) {
809: v = stack_tos(&bmachine.reg[idx]);
1.5 otto 810: if (v == NULL) {
811: n = new_number();
1.51 otto 812: bn_check(BN_set_word(n->number, 0));
1.5 otto 813: push_number(n);
814: } else
1.1 otto 815: push(stack_dup_value(v, ©));
1.18 otto 816: }
1.1 otto 817: }
818:
819: static void
820: store(void)
821: {
1.32 otto 822: int idx;
1.1 otto 823: struct value *val;
824:
1.32 otto 825: idx = readreg();
826: if (idx >= 0) {
1.1 otto 827: val = pop();
828: if (val == NULL) {
829: return;
830: }
1.32 otto 831: stack_set_tos(&bmachine.reg[idx], val);
1.18 otto 832: }
1.1 otto 833: }
834:
835: static void
836: load_stack(void)
837: {
1.32 otto 838: int idx;
1.1 otto 839: struct stack *stack;
1.37 otto 840: struct value *value;
1.1 otto 841:
1.32 otto 842: idx = readreg();
843: if (idx >= 0) {
844: stack = &bmachine.reg[idx];
1.1 otto 845: value = NULL;
846: if (stack_size(stack) > 0) {
847: value = stack_pop(stack);
848: }
849: if (value != NULL)
1.37 otto 850: push(value);
1.1 otto 851: else
852: warnx("stack register '%c' (0%o) is empty",
1.32 otto 853: idx, idx);
1.18 otto 854: }
1.1 otto 855: }
856:
857: static void
858: store_stack(void)
859: {
1.32 otto 860: int idx;
1.1 otto 861: struct value *value;
862:
1.32 otto 863: idx = readreg();
864: if (idx >= 0) {
1.1 otto 865: value = pop();
866: if (value == NULL)
867: return;
1.32 otto 868: stack_push(&bmachine.reg[idx], value);
1.18 otto 869: }
1.1 otto 870: }
871:
872: static void
873: load_array(void)
874: {
875: int reg;
876: struct number *inumber, *n;
1.32 otto 877: u_long idx;
1.1 otto 878: struct stack *stack;
879: struct value *v, copy;
880:
1.18 otto 881: reg = readreg();
882: if (reg >= 0) {
1.1 otto 883: inumber = pop_number();
884: if (inumber == NULL)
885: return;
1.32 otto 886: idx = get_ulong(inumber);
1.44 otto 887: if (BN_is_negative(inumber->number))
1.32 otto 888: warnx("negative idx");
889: else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX)
890: warnx("idx too big");
1.1 otto 891: else {
892: stack = &bmachine.reg[reg];
1.32 otto 893: v = frame_retrieve(stack, idx);
1.39 otto 894: if (v == NULL || v->type == BCODE_NONE) {
1.1 otto 895: n = new_number();
1.51 otto 896: bn_check(BN_set_word(n->number, 0));
1.1 otto 897: push_number(n);
898: }
899: else
900: push(stack_dup_value(v, ©));
901: }
902: free_number(inumber);
1.18 otto 903: }
1.1 otto 904: }
905:
906: static void
907: store_array(void)
908: {
909: int reg;
910: struct number *inumber;
1.32 otto 911: u_long idx;
1.1 otto 912: struct value *value;
913: struct stack *stack;
914:
1.18 otto 915: reg = readreg();
916: if (reg >= 0) {
1.1 otto 917: inumber = pop_number();
1.6 otto 918: if (inumber == NULL)
919: return;
1.1 otto 920: value = pop();
1.6 otto 921: if (value == NULL) {
922: free_number(inumber);
1.1 otto 923: return;
924: }
1.32 otto 925: idx = get_ulong(inumber);
1.44 otto 926: if (BN_is_negative(inumber->number)) {
1.32 otto 927: warnx("negative idx");
1.1 otto 928: stack_free_value(value);
1.32 otto 929: } else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) {
930: warnx("idx too big");
1.1 otto 931: stack_free_value(value);
932: } else {
933: stack = &bmachine.reg[reg];
1.32 otto 934: frame_assign(stack, idx, value);
1.1 otto 935: }
936: free_number(inumber);
1.18 otto 937: }
1.1 otto 938: }
939:
940: static void
941: push_line(void)
942: {
943: push_string(read_string(&bmachine.readstack[bmachine.readsp]));
1.14 otto 944: }
945:
946: static void
947: comment(void)
948: {
949: free(readline());
1.1 otto 950: }
951:
952: static void
953: badd(void)
954: {
955: struct number *a, *b;
956: struct number *r;
957:
958: a = pop_number();
1.49 otto 959: if (a == NULL)
1.1 otto 960: return;
961: b = pop_number();
962: if (b == NULL) {
963: push_number(a);
964: return;
965: }
966:
967: r = new_number();
968: r->scale = max(a->scale, b->scale);
969: if (r->scale > a->scale)
970: normalize(a, r->scale);
971: else if (r->scale > b->scale)
972: normalize(b, r->scale);
973: bn_check(BN_add(r->number, a->number, b->number));
974: push_number(r);
975: free_number(a);
976: free_number(b);
977: }
978:
979: static void
980: bsub(void)
981: {
982: struct number *a, *b;
983: struct number *r;
984:
985: a = pop_number();
1.49 otto 986: if (a == NULL)
1.1 otto 987: return;
988: b = pop_number();
989: if (b == NULL) {
990: push_number(a);
991: return;
992: }
993:
994: r = new_number();
995:
996: r->scale = max(a->scale, b->scale);
997: if (r->scale > a->scale)
998: normalize(a, r->scale);
999: else if (r->scale > b->scale)
1000: normalize(b, r->scale);
1001: bn_check(BN_sub(r->number, b->number, a->number));
1002: push_number(r);
1003: free_number(a);
1004: free_number(b);
1005: }
1006:
1007: void
1.45 otto 1008: bmul_number(struct number *r, struct number *a, struct number *b, u_int scale)
1.1 otto 1009: {
1010: BN_CTX *ctx;
1011:
1012: /* Create copies of the scales, since r might be equal to a or b */
1013: u_int ascale = a->scale;
1014: u_int bscale = b->scale;
1015: u_int rscale = ascale + bscale;
1016:
1017: ctx = BN_CTX_new();
1018: bn_checkp(ctx);
1019: bn_check(BN_mul(r->number, a->number, b->number, ctx));
1020: BN_CTX_free(ctx);
1021:
1.45 otto 1022: r->scale = rscale;
1023: if (rscale > bmachine.scale && rscale > ascale && rscale > bscale)
1024: normalize(r, max(scale, max(ascale, bscale)));
1.1 otto 1025: }
1026:
1027: static void
1028: bmul(void)
1029: {
1030: struct number *a, *b;
1031: struct number *r;
1032:
1033: a = pop_number();
1.49 otto 1034: if (a == NULL)
1.1 otto 1035: return;
1036: b = pop_number();
1037: if (b == NULL) {
1038: push_number(a);
1039: return;
1040: }
1041:
1042: r = new_number();
1.45 otto 1043: bmul_number(r, a, b, bmachine.scale);
1.1 otto 1044:
1045: push_number(r);
1046: free_number(a);
1047: free_number(b);
1048: }
1049:
1050: static void
1051: bdiv(void)
1052: {
1053: struct number *a, *b;
1054: struct number *r;
1055: u_int scale;
1056: BN_CTX *ctx;
1057:
1058: a = pop_number();
1.49 otto 1059: if (a == NULL)
1.1 otto 1060: return;
1061: b = pop_number();
1062: if (b == NULL) {
1063: push_number(a);
1064: return;
1065: }
1066:
1067: r = new_number();
1068: r->scale = bmachine.scale;
1069: scale = max(a->scale, b->scale);
1070:
1071: if (BN_is_zero(a->number))
1072: warnx("divide by zero");
1073: else {
1074: normalize(a, scale);
1075: normalize(b, scale + r->scale);
1076:
1077: ctx = BN_CTX_new();
1078: bn_checkp(ctx);
1079: bn_check(BN_div(r->number, NULL, b->number, a->number, ctx));
1080: BN_CTX_free(ctx);
1081: }
1082: push_number(r);
1083: free_number(a);
1084: free_number(b);
1085: }
1086:
1087: static void
1088: bmod(void)
1089: {
1090: struct number *a, *b;
1091: struct number *r;
1092: u_int scale;
1093: BN_CTX *ctx;
1094:
1095: a = pop_number();
1.49 otto 1096: if (a == NULL)
1.1 otto 1097: return;
1098: b = pop_number();
1099: if (b == NULL) {
1100: push_number(a);
1101: return;
1102: }
1103:
1104: r = new_number();
1105: scale = max(a->scale, b->scale);
1106: r->scale = max(b->scale, a->scale + bmachine.scale);
1107:
1108: if (BN_is_zero(a->number))
1109: warnx("remainder by zero");
1110: else {
1111: normalize(a, scale);
1112: normalize(b, scale + bmachine.scale);
1113:
1114: ctx = BN_CTX_new();
1115: bn_checkp(ctx);
1116: bn_check(BN_mod(r->number, b->number, a->number, ctx));
1117: BN_CTX_free(ctx);
1118: }
1119: push_number(r);
1.8 otto 1120: free_number(a);
1121: free_number(b);
1122: }
1123:
1124: static void
1125: bdivmod(void)
1126: {
1127: struct number *a, *b;
1128: struct number *rdiv, *rmod;
1129: u_int scale;
1130: BN_CTX *ctx;
1131:
1132: a = pop_number();
1.49 otto 1133: if (a == NULL)
1.8 otto 1134: return;
1135: b = pop_number();
1136: if (b == NULL) {
1137: push_number(a);
1138: return;
1139: }
1140:
1141: rdiv = new_number();
1142: rmod = new_number();
1143: rdiv->scale = bmachine.scale;
1144: rmod->scale = max(b->scale, a->scale + bmachine.scale);
1145: scale = max(a->scale, b->scale);
1146:
1147: if (BN_is_zero(a->number))
1148: warnx("divide by zero");
1149: else {
1150: normalize(a, scale);
1151: normalize(b, scale + bmachine.scale);
1152:
1153: ctx = BN_CTX_new();
1154: bn_checkp(ctx);
1155: bn_check(BN_div(rdiv->number, rmod->number,
1156: b->number, a->number, ctx));
1157: BN_CTX_free(ctx);
1158: }
1159: push_number(rdiv);
1160: push_number(rmod);
1.1 otto 1161: free_number(a);
1162: free_number(b);
1163: }
1164:
1165: static void
1166: bexp(void)
1167: {
1168: struct number *a, *p;
1169: struct number *r;
1170: bool neg;
1.45 otto 1171: u_int rscale;
1.1 otto 1172:
1173: p = pop_number();
1.49 otto 1174: if (p == NULL)
1.1 otto 1175: return;
1176: a = pop_number();
1177: if (a == NULL) {
1178: push_number(p);
1179: return;
1180: }
1181:
1.43 otto 1182: if (p->scale != 0) {
1183: BIGNUM *i, *f;
1184: i = BN_new();
1185: bn_checkp(i);
1186: f = BN_new();
1187: bn_checkp(f);
1188: split_number(p, i, f);
1189: if (!BN_is_zero(f))
1190: warnx("Runtime warning: non-zero fractional part in exponent");
1191: BN_free(i);
1192: BN_free(f);
1193: }
1194:
1.1 otto 1195: normalize(p, 0);
1196:
1197: neg = false;
1.43 otto 1198: if (BN_is_negative(p->number)) {
1.1 otto 1199: neg = true;
1200: negate(p);
1.45 otto 1201: rscale = bmachine.scale;
1.1 otto 1202: } else {
1.53 otto 1203: /* Posix bc says min(a.scale * b, max(a.scale, scale)) */
1.1 otto 1204: u_long b;
1205: u_int m;
1206:
1207: b = BN_get_word(p->number);
1208: m = max(a->scale, bmachine.scale);
1.45 otto 1209: rscale = a->scale * (u_int)b;
1210: if (rscale > m || (a->scale > 0 && (b == BN_MASK2 ||
1.34 otto 1211: b > UINT_MAX)))
1.45 otto 1212: rscale = m;
1.1 otto 1213: }
1.2 deraadt 1214:
1.1 otto 1215: if (BN_is_zero(p->number)) {
1216: r = new_number();
1217: bn_check(BN_one(r->number));
1.45 otto 1218: normalize(r, rscale);
1.1 otto 1219: } else {
1.45 otto 1220: u_int ascale, mscale;
1221:
1222: ascale = a->scale;
1.1 otto 1223: while (!BN_is_bit_set(p->number, 0)) {
1.45 otto 1224: ascale *= 2;
1225: bmul_number(a, a, a, ascale);
1.1 otto 1226: bn_check(BN_rshift1(p->number, p->number));
1227: }
1228:
1229: r = dup_number(a);
1230: bn_check(BN_rshift1(p->number, p->number));
1231:
1.45 otto 1232: mscale = ascale;
1.1 otto 1233: while (!BN_is_zero(p->number)) {
1.45 otto 1234: ascale *= 2;
1235: bmul_number(a, a, a, ascale);
1236: if (BN_is_bit_set(p->number, 0)) {
1237: mscale += ascale;
1238: bmul_number(r, r, a, mscale);
1239: }
1.1 otto 1240: bn_check(BN_rshift1(p->number, p->number));
1241: }
1242:
1243: if (neg) {
1244: BN_CTX *ctx;
1245: BIGNUM *one;
1246:
1247: one = BN_new();
1248: bn_checkp(one);
1.31 otto 1249: bn_check(BN_one(one));
1.1 otto 1250: ctx = BN_CTX_new();
1251: bn_checkp(ctx);
1.45 otto 1252: scale_number(one, r->scale + rscale);
1.43 otto 1253:
1254: if (BN_is_zero(r->number))
1255: warnx("divide by zero");
1256: else
1257: bn_check(BN_div(r->number, NULL, one,
1258: r->number, ctx));
1.1 otto 1259: BN_free(one);
1260: BN_CTX_free(ctx);
1.45 otto 1261: r->scale = rscale;
1.29 otto 1262: } else
1.45 otto 1263: normalize(r, rscale);
1.1 otto 1264: }
1265: push_number(r);
1266: free_number(a);
1267: free_number(p);
1268: }
1269:
1270: static void
1271: bsqrt(void)
1272: {
1273: struct number *n;
1274: struct number *r;
1.56 ! otto 1275: BIGNUM *x, *y, *t;
1.25 otto 1276: u_int scale, onecount;
1.1 otto 1277: BN_CTX *ctx;
1278:
1.25 otto 1279: onecount = 0;
1.1 otto 1280: n = pop_number();
1.49 otto 1281: if (n == NULL)
1.1 otto 1282: return;
1283: if (BN_is_zero(n->number)) {
1284: r = new_number();
1285: push_number(r);
1.44 otto 1286: } else if (BN_is_negative(n->number))
1.1 otto 1287: warnx("square root of negative number");
1288: else {
1289: scale = max(bmachine.scale, n->scale);
1290: normalize(n, 2*scale);
1291: x = BN_dup(n->number);
1292: bn_checkp(x);
1293: bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
1294: y = BN_new();
1295: bn_checkp(y);
1296: ctx = BN_CTX_new();
1297: bn_checkp(ctx);
1.56 ! otto 1298: do {
! 1299: bn_check(BN_div(y, NULL, n->number, x, ctx));
! 1300: bn_check(BN_add(y, x, y));
! 1301: bn_check(BN_rshift1(y, y));
! 1302: bn_check(BN_sub(x, y, x));
! 1303: t = x;
! 1304: x = y;
! 1305: y = t;
! 1306: } while (!BN_is_zero(y) && (onecount += BN_is_one(y)) < 2);
! 1307: bn_check(BN_sub(y, x, y));
1.1 otto 1308: r = bmalloc(sizeof(*r));
1309: r->scale = scale;
1310: r->number = y;
1311: BN_free(x);
1312: BN_CTX_free(ctx);
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: }