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