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