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