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