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