Annotation of src/usr.bin/dc/bcode.c, Revision 1.55
1.55 ! otto 1: /* $OpenBSD: bcode.c,v 1.54 2017/11/28 09:44:14 otto Exp $ */
1.1 otto 2:
3: /*
4: * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <err.h>
20: #include <limits.h>
1.20 otto 21: #include <signal.h>
1.1 otto 22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25:
26: #include "extern.h"
27:
1.9 otto 28: /* #define DEBUGGING */
1.1 otto 29:
30: #define MAX_ARRAY_INDEX 2048
1.27 otto 31: #define READSTACK_SIZE 8
1.1 otto 32:
1.11 otto 33: #define NO_ELSE -2 /* -1 is EOF */
1.18 otto 34: #define REG_ARRAY_SIZE_SMALL (UCHAR_MAX + 1)
35: #define REG_ARRAY_SIZE_BIG (UCHAR_MAX + 1 + USHRT_MAX + 1)
1.11 otto 36:
1.1 otto 37: struct bmachine {
38: struct stack stack;
39: u_int scale;
40: u_int obase;
41: u_int ibase;
1.27 otto 42: size_t readsp;
1.18 otto 43: bool extended_regs;
44: size_t reg_array_size;
45: struct stack *reg;
1.26 otto 46: volatile sig_atomic_t interrupted;
1.27 otto 47: struct source *readstack;
48: size_t readstack_sz;
1.1 otto 49: };
50:
51: static struct bmachine bmachine;
1.20 otto 52: static void sighandler(int);
1.1 otto 53:
54: static __inline int readch(void);
1.31 otto 55: static __inline void unreadch(void);
1.1 otto 56: static __inline char *readline(void);
57: static __inline void src_free(void);
58:
59: static __inline u_int max(u_int, u_int);
60: static u_long get_ulong(struct number *);
61:
62: static __inline void push_number(struct number *);
63: static __inline void push_string(char *);
64: static __inline void push(struct value *);
65: static __inline struct value *tos(void);
66: static __inline struct number *pop_number(void);
67: static __inline char *pop_string(void);
68: static __inline void clear_stack(void);
69: static __inline void print_tos(void);
1.50 otto 70: static void print_err(void);
1.14 otto 71: static void pop_print(void);
72: static void pop_printn(void);
1.18 otto 73: static __inline void print_stack(void);
1.1 otto 74: static __inline void dup(void);
1.13 otto 75: static void swap(void);
1.17 otto 76: static void drop(void);
1.1 otto 77:
78: static void get_scale(void);
79: static void set_scale(void);
80: static void get_obase(void);
81: static void set_obase(void);
82: static void get_ibase(void);
83: static void set_ibase(void);
84: static void stackdepth(void);
85: static void push_scale(void);
86: static u_int count_digits(const struct number *);
87: static void num_digits(void);
1.14 otto 88: static void to_ascii(void);
1.1 otto 89: static void push_line(void);
1.14 otto 90: static void comment(void);
1.1 otto 91: static void badd(void);
92: static void bsub(void);
93: static void bmul(void);
94: static void bdiv(void);
95: static void bmod(void);
1.8 otto 96: static void bdivmod(void);
1.1 otto 97: static void bexp(void);
1.25 otto 98: static bool bsqrt_stop(const BIGNUM *, const BIGNUM *, u_int *);
1.1 otto 99: static void bsqrt(void);
1.16 otto 100: static void not(void);
101: static void equal_numbers(void);
102: static void less_numbers(void);
103: static void lesseq_numbers(void);
1.1 otto 104: static void equal(void);
105: static void less(void);
106: static void greater(void);
107: static void not_compare(void);
1.16 otto 108: static bool compare_numbers(enum bcode_compare, struct number *,
109: struct number *);
1.1 otto 110: static void compare(enum bcode_compare);
1.18 otto 111: static int readreg(void);
1.1 otto 112: static void load(void);
113: static void store(void);
114: static void load_stack(void);
115: static void store_stack(void);
116: static void load_array(void);
117: static void store_array(void);
118: static void nop(void);
119: static void quit(void);
120: static void quitN(void);
1.9 otto 121: static void skipN(void);
122: static void skip_until_mark(void);
1.1 otto 123: static void parse_number(void);
124: static void unknown(void);
125: static void eval_string(char *);
126: static void eval_line(void);
127: static void eval_tos(void);
128:
129:
130: typedef void (*opcode_function)(void);
131:
132: struct jump_entry {
133: u_char ch;
134: opcode_function f;
135: };
136:
1.52 tom 137: static opcode_function jump_table[UCHAR_MAX + 1];
1.1 otto 138:
139: static const struct jump_entry jump_table_data[] = {
1.14 otto 140: { ' ', nop },
141: { '!', not_compare },
142: { '#', comment },
143: { '%', bmod },
1.16 otto 144: { '(', less_numbers },
1.14 otto 145: { '*', bmul },
146: { '+', badd },
147: { '-', bsub },
148: { '.', parse_number },
149: { '/', bdiv },
1.1 otto 150: { '0', parse_number },
151: { '1', parse_number },
152: { '2', parse_number },
153: { '3', parse_number },
154: { '4', parse_number },
155: { '5', parse_number },
156: { '6', parse_number },
157: { '7', parse_number },
158: { '8', parse_number },
159: { '9', parse_number },
1.14 otto 160: { ':', store_array },
161: { ';', load_array },
162: { '<', less },
163: { '=', equal },
164: { '>', greater },
165: { '?', eval_line },
1.1 otto 166: { 'A', parse_number },
167: { 'B', parse_number },
168: { 'C', parse_number },
169: { 'D', parse_number },
170: { 'E', parse_number },
171: { 'F', parse_number },
1.16 otto 172: { 'G', equal_numbers },
1.14 otto 173: { 'I', get_ibase },
174: { 'J', skipN },
175: { 'K', get_scale },
1.1 otto 176: { 'L', load_stack },
1.14 otto 177: { 'M', nop },
1.16 otto 178: { 'N', not },
1.14 otto 179: { 'O', get_obase },
1.1 otto 180: { 'P', pop_print },
1.14 otto 181: { 'Q', quitN },
1.17 otto 182: { 'R', drop },
1.14 otto 183: { 'S', store_stack },
1.1 otto 184: { 'X', push_scale },
1.14 otto 185: { 'Z', num_digits },
1.1 otto 186: { '[', push_line },
1.14 otto 187: { '\f', nop },
188: { '\n', nop },
189: { '\r', nop },
190: { '\t', nop },
191: { '^', bexp },
192: { '_', parse_number },
193: { 'a', to_ascii },
1.1 otto 194: { 'c', clear_stack },
1.14 otto 195: { 'd', dup },
1.50 otto 196: { 'e', print_err },
1.14 otto 197: { 'f', print_stack },
1.1 otto 198: { 'i', set_ibase },
1.14 otto 199: { 'k', set_scale },
200: { 'l', load },
201: { 'n', pop_printn },
1.1 otto 202: { 'o', set_obase },
1.16 otto 203: { 'p', print_tos },
1.14 otto 204: { 'q', quit },
1.16 otto 205: { 'r', swap },
1.14 otto 206: { 's', store },
207: { 'v', bsqrt },
208: { 'x', eval_tos },
1.1 otto 209: { 'z', stackdepth },
1.16 otto 210: { '{', lesseq_numbers },
1.14 otto 211: { '~', bdivmod }
1.1 otto 212: };
213:
1.52 tom 214: #ifndef nitems
215: #define nitems(a) (sizeof((a)) / sizeof((a)[0]))
216: #endif
1.1 otto 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.52 tom 239: for (i = 0; i < nitems(jump_table); i++)
1.1 otto 240: jump_table[i] = unknown;
1.52 tom 241:
242: for (i = 0; i < nitems(jump_table_data); i++) {
243: if ((unsigned int)jump_table_data[i].ch >= nitems(jump_table))
244: errx(1, "opcode '%c' overflows jump table",
245: jump_table_data[i].ch);
246: if (jump_table[jump_table_data[i].ch] != unknown)
247: errx(1, "opcode '%c' already assigned",
248: jump_table_data[i].ch);
1.1 otto 249: jump_table[jump_table_data[i].ch] = jump_table_data[i].f;
1.52 tom 250: }
1.1 otto 251:
252: stack_init(&bmachine.stack);
253:
1.18 otto 254: for (i = 0; i < bmachine.reg_array_size; i++)
1.1 otto 255: stack_init(&bmachine.reg[i]);
256:
1.27 otto 257: bmachine.readstack_sz = READSTACK_SIZE;
1.35 deraadt 258: bmachine.readstack = calloc(sizeof(struct source),
1.27 otto 259: bmachine.readstack_sz);
260: if (bmachine.readstack == NULL)
261: err(1, NULL);
1.1 otto 262: bmachine.obase = bmachine.ibase = 10;
1.31 otto 263: (void)signal(SIGINT, sighandler);
1.1 otto 264: }
265:
1.45 otto 266: u_int
267: bmachine_scale(void)
268: {
269: return bmachine.scale;
270: }
271:
1.1 otto 272: /* Reset the things needed before processing a (new) file */
273: void
274: reset_bmachine(struct source *src)
275: {
276: bmachine.readsp = 0;
277: bmachine.readstack[0] = *src;
278: }
279:
280: static __inline int
281: readch(void)
282: {
283: struct source *src = &bmachine.readstack[bmachine.readsp];
284:
285: return src->vtable->readchar(src);
286: }
287:
1.31 otto 288: static __inline void
1.1 otto 289: unreadch(void)
290: {
291: struct source *src = &bmachine.readstack[bmachine.readsp];
292:
1.31 otto 293: src->vtable->unreadchar(src);
1.1 otto 294: }
295:
296: static __inline char *
297: readline(void)
298: {
299: struct source *src = &bmachine.readstack[bmachine.readsp];
300:
301: return src->vtable->readline(src);
302: }
303:
304: static __inline void
305: src_free(void)
306: {
307: struct source *src = &bmachine.readstack[bmachine.readsp];
308:
309: src->vtable->free(src);
310: }
311:
1.10 otto 312: #ifdef DEBUGGING
1.1 otto 313: void
1.28 deraadt 314: pn(const char *str, const struct number *n)
1.1 otto 315: {
316: char *p = BN_bn2dec(n->number);
317: if (p == NULL)
318: err(1, "BN_bn2dec failed");
1.31 otto 319: (void)fputs(str, stderr);
320: (void)fprintf(stderr, " %s (%u)\n" , p, n->scale);
1.1 otto 321: OPENSSL_free(p);
322: }
323:
324: void
1.28 deraadt 325: pbn(const char *str, const BIGNUM *n)
1.1 otto 326: {
327: char *p = BN_bn2dec(n);
328: if (p == NULL)
329: err(1, "BN_bn2dec failed");
1.31 otto 330: (void)fputs(str, stderr);
331: (void)fprintf(stderr, " %s\n", p);
1.1 otto 332: OPENSSL_free(p);
333: }
334:
335: #endif
336:
337: static __inline u_int
338: max(u_int a, u_int b)
339: {
340: return a > b ? a : b;
341: }
342:
343: static unsigned long factors[] = {
344: 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
345: 100000000, 1000000000
346: };
347:
348: void
349: scale_number(BIGNUM *n, int s)
350: {
351: int abs_scale;
352:
353: if (s == 0)
354: return;
355:
356: abs_scale = s > 0 ? s : -s;
357:
358: if (abs_scale < sizeof(factors)/sizeof(factors[0])) {
359: if (s > 0)
360: bn_check(BN_mul_word(n, factors[abs_scale]));
361: else
1.31 otto 362: (void)BN_div_word(n, factors[abs_scale]);
1.1 otto 363: } else {
364: BIGNUM *a, *p;
365: BN_CTX *ctx;
366:
367: a = BN_new();
368: bn_checkp(a);
369: p = BN_new();
370: bn_checkp(p);
371: ctx = BN_CTX_new();
372: bn_checkp(ctx);
373:
374: bn_check(BN_set_word(a, 10));
375: bn_check(BN_set_word(p, abs_scale));
376: bn_check(BN_exp(a, a, p, ctx));
377: if (s > 0)
378: bn_check(BN_mul(n, n, a, ctx));
379: else
380: bn_check(BN_div(n, NULL, n, a, ctx));
381: BN_CTX_free(ctx);
382: BN_free(a);
383: BN_free(p);
384: }
385: }
386:
387: void
388: split_number(const struct number *n, BIGNUM *i, BIGNUM *f)
389: {
390: u_long rem;
391:
392: bn_checkp(BN_copy(i, n->number));
393:
394: if (n->scale == 0 && f != NULL)
1.51 otto 395: bn_check(BN_set_word(f, 0));
1.1 otto 396: else if (n->scale < sizeof(factors)/sizeof(factors[0])) {
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: {
701: struct number *int_part, *fract_part;
702: u_int i;
703:
704: if (BN_is_zero(n->number))
1.42 otto 705: return n->scale ? n->scale : 1;
1.1 otto 706:
707: int_part = new_number();
708: fract_part = new_number();
709: fract_part->scale = n->scale;
710: split_number(n, int_part->number, fract_part->number);
711:
712: i = 0;
713: while (!BN_is_zero(int_part->number)) {
1.31 otto 714: (void)BN_div_word(int_part->number, 10);
1.1 otto 715: i++;
716: }
717: free_number(int_part);
718: free_number(fract_part);
719: return i + n->scale;
720: }
721:
722: static void
723: num_digits(void)
724: {
725: struct value *value;
1.34 otto 726: size_t digits;
1.14 otto 727: struct number *n = NULL;
1.1 otto 728:
729: value = pop();
730: if (value != NULL) {
731: switch (value->type) {
732: case BCODE_NONE:
1.14 otto 733: return;
1.1 otto 734: case BCODE_NUMBER:
735: digits = count_digits(value->u.num);
736: n = new_number();
737: bn_check(BN_set_word(n->number, digits));
738: break;
739: case BCODE_STRING:
740: digits = strlen(value->u.string);
741: n = new_number();
742: bn_check(BN_set_word(n->number, digits));
743: break;
744: }
1.14 otto 745: stack_free_value(value);
746: push_number(n);
747: }
748: }
749:
750: static void
751: to_ascii(void)
752: {
753: char str[2];
754: struct value *value;
755: struct number *n;
756:
757: value = pop();
758: if (value != NULL) {
759: str[1] = '\0';
760: switch (value->type) {
761: case BCODE_NONE:
762: return;
763: case BCODE_NUMBER:
764: n = value->u.num;
765: normalize(n, 0);
766: if (BN_num_bits(n->number) > 8)
767: bn_check(BN_mask_bits(n->number, 8));
1.33 otto 768: str[0] = (char)BN_get_word(n->number);
1.14 otto 769: break;
770: case BCODE_STRING:
771: str[0] = value->u.string[0];
772: break;
773: }
774: stack_free_value(value);
775: push_string(bstrdup(str));
1.1 otto 776: }
777: }
778:
1.18 otto 779: static int
780: readreg(void)
781: {
1.32 otto 782: int idx, ch1, ch2;
1.18 otto 783:
1.32 otto 784: idx = readch();
785: if (idx == 0xff && bmachine.extended_regs) {
1.18 otto 786: ch1 = readch();
787: ch2 = readch();
788: if (ch1 == EOF || ch2 == EOF) {
789: warnx("unexpected eof");
1.32 otto 790: idx = -1;
1.18 otto 791: } else
1.32 otto 792: idx = (ch1 << 8) + ch2 + UCHAR_MAX + 1;
1.18 otto 793: }
1.32 otto 794: if (idx < 0 || idx >= bmachine.reg_array_size) {
795: warnx("internal error: reg num = %d", idx);
796: idx = -1;
1.18 otto 797: }
1.32 otto 798: return idx;
1.18 otto 799: }
800:
1.1 otto 801: static void
802: load(void)
803: {
1.32 otto 804: int idx;
1.1 otto 805: struct value *v, copy;
1.5 otto 806: struct number *n;
1.1 otto 807:
1.32 otto 808: idx = readreg();
809: if (idx >= 0) {
810: v = stack_tos(&bmachine.reg[idx]);
1.5 otto 811: if (v == NULL) {
812: n = new_number();
1.51 otto 813: bn_check(BN_set_word(n->number, 0));
1.5 otto 814: push_number(n);
815: } else
1.1 otto 816: push(stack_dup_value(v, ©));
1.18 otto 817: }
1.1 otto 818: }
819:
820: static void
821: store(void)
822: {
1.32 otto 823: int idx;
1.1 otto 824: struct value *val;
825:
1.32 otto 826: idx = readreg();
827: if (idx >= 0) {
1.1 otto 828: val = pop();
829: if (val == NULL) {
830: return;
831: }
1.32 otto 832: stack_set_tos(&bmachine.reg[idx], val);
1.18 otto 833: }
1.1 otto 834: }
835:
836: static void
837: load_stack(void)
838: {
1.32 otto 839: int idx;
1.1 otto 840: struct stack *stack;
1.37 otto 841: struct value *value;
1.1 otto 842:
1.32 otto 843: idx = readreg();
844: if (idx >= 0) {
845: stack = &bmachine.reg[idx];
1.1 otto 846: value = NULL;
847: if (stack_size(stack) > 0) {
848: value = stack_pop(stack);
849: }
850: if (value != NULL)
1.37 otto 851: push(value);
1.1 otto 852: else
853: warnx("stack register '%c' (0%o) is empty",
1.32 otto 854: idx, idx);
1.18 otto 855: }
1.1 otto 856: }
857:
858: static void
859: store_stack(void)
860: {
1.32 otto 861: int idx;
1.1 otto 862: struct value *value;
863:
1.32 otto 864: idx = readreg();
865: if (idx >= 0) {
1.1 otto 866: value = pop();
867: if (value == NULL)
868: return;
1.32 otto 869: stack_push(&bmachine.reg[idx], value);
1.18 otto 870: }
1.1 otto 871: }
872:
873: static void
874: load_array(void)
875: {
876: int reg;
877: struct number *inumber, *n;
1.32 otto 878: u_long idx;
1.1 otto 879: struct stack *stack;
880: struct value *v, copy;
881:
1.18 otto 882: reg = readreg();
883: if (reg >= 0) {
1.1 otto 884: inumber = pop_number();
885: if (inumber == NULL)
886: return;
1.32 otto 887: idx = get_ulong(inumber);
1.44 otto 888: if (BN_is_negative(inumber->number))
1.32 otto 889: warnx("negative idx");
890: else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX)
891: warnx("idx too big");
1.1 otto 892: else {
893: stack = &bmachine.reg[reg];
1.32 otto 894: v = frame_retrieve(stack, idx);
1.39 otto 895: if (v == NULL || v->type == BCODE_NONE) {
1.1 otto 896: n = new_number();
1.51 otto 897: bn_check(BN_set_word(n->number, 0));
1.1 otto 898: push_number(n);
899: }
900: else
901: push(stack_dup_value(v, ©));
902: }
903: free_number(inumber);
1.18 otto 904: }
1.1 otto 905: }
906:
907: static void
908: store_array(void)
909: {
910: int reg;
911: struct number *inumber;
1.32 otto 912: u_long idx;
1.1 otto 913: struct value *value;
914: struct stack *stack;
915:
1.18 otto 916: reg = readreg();
917: if (reg >= 0) {
1.1 otto 918: inumber = pop_number();
1.6 otto 919: if (inumber == NULL)
920: return;
1.1 otto 921: value = pop();
1.6 otto 922: if (value == NULL) {
923: free_number(inumber);
1.1 otto 924: return;
925: }
1.32 otto 926: idx = get_ulong(inumber);
1.44 otto 927: if (BN_is_negative(inumber->number)) {
1.32 otto 928: warnx("negative idx");
1.1 otto 929: stack_free_value(value);
1.32 otto 930: } else if (idx == BN_MASK2 || idx > MAX_ARRAY_INDEX) {
931: warnx("idx too big");
1.1 otto 932: stack_free_value(value);
933: } else {
934: stack = &bmachine.reg[reg];
1.32 otto 935: frame_assign(stack, idx, value);
1.1 otto 936: }
937: free_number(inumber);
1.18 otto 938: }
1.1 otto 939: }
940:
941: static void
942: push_line(void)
943: {
944: push_string(read_string(&bmachine.readstack[bmachine.readsp]));
1.14 otto 945: }
946:
947: static void
948: comment(void)
949: {
950: free(readline());
1.1 otto 951: }
952:
953: static void
954: badd(void)
955: {
956: struct number *a, *b;
957: struct number *r;
958:
959: a = pop_number();
1.49 otto 960: if (a == NULL)
1.1 otto 961: return;
962: b = pop_number();
963: if (b == NULL) {
964: push_number(a);
965: return;
966: }
967:
968: r = new_number();
969: r->scale = max(a->scale, b->scale);
970: if (r->scale > a->scale)
971: normalize(a, r->scale);
972: else if (r->scale > b->scale)
973: normalize(b, r->scale);
974: bn_check(BN_add(r->number, a->number, b->number));
975: push_number(r);
976: free_number(a);
977: free_number(b);
978: }
979:
980: static void
981: bsub(void)
982: {
983: struct number *a, *b;
984: struct number *r;
985:
986: a = pop_number();
1.49 otto 987: if (a == NULL)
1.1 otto 988: return;
989: b = pop_number();
990: if (b == NULL) {
991: push_number(a);
992: return;
993: }
994:
995: r = new_number();
996:
997: r->scale = max(a->scale, b->scale);
998: if (r->scale > a->scale)
999: normalize(a, r->scale);
1000: else if (r->scale > b->scale)
1001: normalize(b, r->scale);
1002: bn_check(BN_sub(r->number, b->number, a->number));
1003: push_number(r);
1004: free_number(a);
1005: free_number(b);
1006: }
1007:
1008: void
1.45 otto 1009: bmul_number(struct number *r, struct number *a, struct number *b, u_int scale)
1.1 otto 1010: {
1011: BN_CTX *ctx;
1012:
1013: /* Create copies of the scales, since r might be equal to a or b */
1014: u_int ascale = a->scale;
1015: u_int bscale = b->scale;
1016: u_int rscale = ascale + bscale;
1017:
1018: ctx = BN_CTX_new();
1019: bn_checkp(ctx);
1020: bn_check(BN_mul(r->number, a->number, b->number, ctx));
1021: BN_CTX_free(ctx);
1022:
1.45 otto 1023: r->scale = rscale;
1024: if (rscale > bmachine.scale && rscale > ascale && rscale > bscale)
1025: normalize(r, max(scale, max(ascale, bscale)));
1.1 otto 1026: }
1027:
1028: static void
1029: bmul(void)
1030: {
1031: struct number *a, *b;
1032: struct number *r;
1033:
1034: a = pop_number();
1.49 otto 1035: if (a == NULL)
1.1 otto 1036: return;
1037: b = pop_number();
1038: if (b == NULL) {
1039: push_number(a);
1040: return;
1041: }
1042:
1043: r = new_number();
1.45 otto 1044: bmul_number(r, a, b, bmachine.scale);
1.1 otto 1045:
1046: push_number(r);
1047: free_number(a);
1048: free_number(b);
1049: }
1050:
1051: static void
1052: bdiv(void)
1053: {
1054: struct number *a, *b;
1055: struct number *r;
1056: u_int scale;
1057: BN_CTX *ctx;
1058:
1059: a = pop_number();
1.49 otto 1060: if (a == NULL)
1.1 otto 1061: return;
1062: b = pop_number();
1063: if (b == NULL) {
1064: push_number(a);
1065: return;
1066: }
1067:
1068: r = new_number();
1069: r->scale = bmachine.scale;
1070: scale = max(a->scale, b->scale);
1071:
1072: if (BN_is_zero(a->number))
1073: warnx("divide by zero");
1074: else {
1075: normalize(a, scale);
1076: normalize(b, scale + r->scale);
1077:
1078: ctx = BN_CTX_new();
1079: bn_checkp(ctx);
1080: bn_check(BN_div(r->number, NULL, b->number, a->number, ctx));
1081: BN_CTX_free(ctx);
1082: }
1083: push_number(r);
1084: free_number(a);
1085: free_number(b);
1086: }
1087:
1088: static void
1089: bmod(void)
1090: {
1091: struct number *a, *b;
1092: struct number *r;
1093: u_int scale;
1094: BN_CTX *ctx;
1095:
1096: a = pop_number();
1.49 otto 1097: if (a == NULL)
1.1 otto 1098: return;
1099: b = pop_number();
1100: if (b == NULL) {
1101: push_number(a);
1102: return;
1103: }
1104:
1105: r = new_number();
1106: scale = max(a->scale, b->scale);
1107: r->scale = max(b->scale, a->scale + bmachine.scale);
1108:
1109: if (BN_is_zero(a->number))
1110: warnx("remainder by zero");
1111: else {
1112: normalize(a, scale);
1113: normalize(b, scale + bmachine.scale);
1114:
1115: ctx = BN_CTX_new();
1116: bn_checkp(ctx);
1117: bn_check(BN_mod(r->number, b->number, a->number, ctx));
1118: BN_CTX_free(ctx);
1119: }
1120: push_number(r);
1.8 otto 1121: free_number(a);
1122: free_number(b);
1123: }
1124:
1125: static void
1126: bdivmod(void)
1127: {
1128: struct number *a, *b;
1129: struct number *rdiv, *rmod;
1130: u_int scale;
1131: BN_CTX *ctx;
1132:
1133: a = pop_number();
1.49 otto 1134: if (a == NULL)
1.8 otto 1135: return;
1136: b = pop_number();
1137: if (b == NULL) {
1138: push_number(a);
1139: return;
1140: }
1141:
1142: rdiv = new_number();
1143: rmod = new_number();
1144: rdiv->scale = bmachine.scale;
1145: rmod->scale = max(b->scale, a->scale + bmachine.scale);
1146: scale = max(a->scale, b->scale);
1147:
1148: if (BN_is_zero(a->number))
1149: warnx("divide by zero");
1150: else {
1151: normalize(a, scale);
1152: normalize(b, scale + bmachine.scale);
1153:
1154: ctx = BN_CTX_new();
1155: bn_checkp(ctx);
1156: bn_check(BN_div(rdiv->number, rmod->number,
1157: b->number, a->number, ctx));
1158: BN_CTX_free(ctx);
1159: }
1160: push_number(rdiv);
1161: push_number(rmod);
1.1 otto 1162: free_number(a);
1163: free_number(b);
1164: }
1165:
1166: static void
1167: bexp(void)
1168: {
1169: struct number *a, *p;
1170: struct number *r;
1171: bool neg;
1.45 otto 1172: u_int rscale;
1.1 otto 1173:
1174: p = pop_number();
1.49 otto 1175: if (p == NULL)
1.1 otto 1176: return;
1177: a = pop_number();
1178: if (a == NULL) {
1179: push_number(p);
1180: return;
1181: }
1182:
1.43 otto 1183: if (p->scale != 0) {
1184: BIGNUM *i, *f;
1185: i = BN_new();
1186: bn_checkp(i);
1187: f = BN_new();
1188: bn_checkp(f);
1189: split_number(p, i, f);
1190: if (!BN_is_zero(f))
1191: warnx("Runtime warning: non-zero fractional part in exponent");
1192: BN_free(i);
1193: BN_free(f);
1194: }
1195:
1.1 otto 1196: normalize(p, 0);
1197:
1198: neg = false;
1.43 otto 1199: if (BN_is_negative(p->number)) {
1.1 otto 1200: neg = true;
1201: negate(p);
1.45 otto 1202: rscale = bmachine.scale;
1.1 otto 1203: } else {
1.53 otto 1204: /* Posix bc says min(a.scale * b, max(a.scale, scale)) */
1.1 otto 1205: u_long b;
1206: u_int m;
1207:
1208: b = BN_get_word(p->number);
1209: m = max(a->scale, bmachine.scale);
1.45 otto 1210: rscale = a->scale * (u_int)b;
1211: if (rscale > m || (a->scale > 0 && (b == BN_MASK2 ||
1.34 otto 1212: b > UINT_MAX)))
1.45 otto 1213: rscale = m;
1.1 otto 1214: }
1.2 deraadt 1215:
1.1 otto 1216: if (BN_is_zero(p->number)) {
1217: r = new_number();
1218: bn_check(BN_one(r->number));
1.45 otto 1219: normalize(r, rscale);
1.1 otto 1220: } else {
1.45 otto 1221: u_int ascale, mscale;
1222:
1223: ascale = a->scale;
1.1 otto 1224: while (!BN_is_bit_set(p->number, 0)) {
1.45 otto 1225: ascale *= 2;
1226: bmul_number(a, a, a, ascale);
1.1 otto 1227: bn_check(BN_rshift1(p->number, p->number));
1228: }
1229:
1230: r = dup_number(a);
1231: bn_check(BN_rshift1(p->number, p->number));
1232:
1.45 otto 1233: mscale = ascale;
1.1 otto 1234: while (!BN_is_zero(p->number)) {
1.45 otto 1235: ascale *= 2;
1236: bmul_number(a, a, a, ascale);
1237: if (BN_is_bit_set(p->number, 0)) {
1238: mscale += ascale;
1239: bmul_number(r, r, a, mscale);
1240: }
1.1 otto 1241: bn_check(BN_rshift1(p->number, p->number));
1242: }
1243:
1244: if (neg) {
1245: BN_CTX *ctx;
1246: BIGNUM *one;
1247:
1248: one = BN_new();
1249: bn_checkp(one);
1.31 otto 1250: bn_check(BN_one(one));
1.1 otto 1251: ctx = BN_CTX_new();
1252: bn_checkp(ctx);
1.45 otto 1253: scale_number(one, r->scale + rscale);
1.43 otto 1254:
1255: if (BN_is_zero(r->number))
1256: warnx("divide by zero");
1257: else
1258: bn_check(BN_div(r->number, NULL, one,
1259: r->number, ctx));
1.1 otto 1260: BN_free(one);
1261: BN_CTX_free(ctx);
1.45 otto 1262: r->scale = rscale;
1.29 otto 1263: } else
1.45 otto 1264: normalize(r, rscale);
1.1 otto 1265: }
1266: push_number(r);
1267: free_number(a);
1268: free_number(p);
1269: }
1270:
1271: static bool
1.25 otto 1272: bsqrt_stop(const BIGNUM *x, const BIGNUM *y, u_int *onecount)
1.1 otto 1273: {
1274: BIGNUM *r;
1275: bool ret;
1276:
1277: r = BN_new();
1278: bn_checkp(r);
1279: bn_check(BN_sub(r, x, y));
1.25 otto 1280: if (BN_is_one(r))
1281: (*onecount)++;
1282: ret = BN_is_zero(r);
1.1 otto 1283: BN_free(r);
1.25 otto 1284: return ret || *onecount > 1;
1.1 otto 1285: }
1286:
1287: static void
1288: bsqrt(void)
1289: {
1290: struct number *n;
1291: struct number *r;
1292: BIGNUM *x, *y;
1.25 otto 1293: u_int scale, onecount;
1.1 otto 1294: BN_CTX *ctx;
1295:
1.25 otto 1296: onecount = 0;
1.1 otto 1297: n = pop_number();
1.49 otto 1298: if (n == NULL)
1.1 otto 1299: return;
1300: if (BN_is_zero(n->number)) {
1301: r = new_number();
1302: push_number(r);
1.44 otto 1303: } else if (BN_is_negative(n->number))
1.1 otto 1304: warnx("square root of negative number");
1305: else {
1306: scale = max(bmachine.scale, n->scale);
1307: normalize(n, 2*scale);
1308: x = BN_dup(n->number);
1309: bn_checkp(x);
1310: bn_check(BN_rshift(x, x, BN_num_bits(x)/2));
1311: y = BN_new();
1312: bn_checkp(y);
1313: ctx = BN_CTX_new();
1314: bn_checkp(ctx);
1315: for (;;) {
1316: bn_checkp(BN_copy(y, x));
1317: bn_check(BN_div(x, NULL, n->number, x, ctx));
1318: bn_check(BN_add(x, x, y));
1319: bn_check(BN_rshift1(x, x));
1.25 otto 1320: if (bsqrt_stop(x, y, &onecount))
1.1 otto 1321: break;
1322: }
1323: r = bmalloc(sizeof(*r));
1324: r->scale = scale;
1325: r->number = y;
1326: BN_free(x);
1327: BN_CTX_free(ctx);
1328: push_number(r);
1329: }
1330:
1331: free_number(n);
1332: }
1333:
1334: static void
1.16 otto 1335: not(void)
1336: {
1337: struct number *a;
1338:
1339: a = pop_number();
1.49 otto 1340: if (a == NULL)
1.16 otto 1341: return;
1342: a->scale = 0;
1343: bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1));
1344: push_number(a);
1345: }
1346:
1347: static void
1.1 otto 1348: equal(void)
1349: {
1350: compare(BCODE_EQUAL);
1351: }
1352:
1353: static void
1.16 otto 1354: equal_numbers(void)
1355: {
1356: struct number *a, *b, *r;
1357:
1358: a = pop_number();
1.49 otto 1359: if (a == NULL)
1.16 otto 1360: return;
1361: b = pop_number();
1362: if (b == NULL) {
1363: push_number(a);
1364: return;
1365: }
1366: r = new_number();
1367: bn_check(BN_set_word(r->number,
1368: compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0));
1369: push_number(r);
1370: }
1371:
1372: static void
1373: less_numbers(void)
1374: {
1375: struct number *a, *b, *r;
1376:
1377: a = pop_number();
1.49 otto 1378: if (a == NULL)
1.16 otto 1379: return;
1380: b = pop_number();
1381: if (b == NULL) {
1382: push_number(a);
1383: return;
1384: }
1385: r = new_number();
1386: bn_check(BN_set_word(r->number,
1387: compare_numbers(BCODE_LESS, a, b) ? 1 : 0));
1388: push_number(r);
1389: }
1390:
1391: static void
1392: lesseq_numbers(void)
1393: {
1394: struct number *a, *b, *r;
1395:
1396: a = pop_number();
1.49 otto 1397: if (a == NULL)
1.16 otto 1398: return;
1399: b = pop_number();
1400: if (b == NULL) {
1401: push_number(a);
1402: return;
1403: }
1404: r = new_number();
1405: bn_check(BN_set_word(r->number,
1406: compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
1407: push_number(r);
1408: }
1409:
1410: static void
1.1 otto 1411: less(void)
1412: {
1413: compare(BCODE_LESS);
1414: }
1415:
1416: static void
1417: not_compare(void)
1418: {
1419: switch (readch()) {
1420: case '<':
1.53 otto 1421: compare(BCODE_NOT_LESS);
1.1 otto 1422: break;
1423: case '>':
1.53 otto 1424: compare(BCODE_NOT_GREATER);
1.1 otto 1425: break;
1426: case '=':
1.53 otto 1427: compare(BCODE_NOT_EQUAL);
1.1 otto 1428: break;
1.2 deraadt 1429: default:
1.1 otto 1430: unreadch();
1.55 ! otto 1431: warnx("! command is deprecated");
1.1 otto 1432: break;
1433: }
1434: }
1435:
1436: static void
1437: greater(void)
1438: {
1439: compare(BCODE_GREATER);
1440: }
1441:
1.16 otto 1442: static bool
1443: compare_numbers(enum bcode_compare type, struct number *a, struct number *b)
1444: {
1445: u_int scale;
1446: int cmp;
1447:
1448: scale = max(a->scale, b->scale);
1449:
1450: if (scale > a->scale)
1451: normalize(a, scale);
1.30 otto 1452: else if (scale > b->scale)
1.16 otto 1453: normalize(b, scale);
1454:
1455: cmp = BN_cmp(a->number, b->number);
1456:
1457: free_number(a);
1458: free_number(b);
1459:
1460: switch (type) {
1461: case BCODE_EQUAL:
1462: return cmp == 0;
1463: case BCODE_NOT_EQUAL:
1464: return cmp != 0;
1465: case BCODE_LESS:
1466: return cmp < 0;
1467: case BCODE_NOT_LESS:
1468: return cmp >= 0;
1469: case BCODE_GREATER:
1470: return cmp > 0;
1471: case BCODE_NOT_GREATER:
1472: return cmp <= 0;
1473: }
1474: return false;
1475: }
1476:
1.1 otto 1477: static void
1478: compare(enum bcode_compare type)
1479: {
1.32 otto 1480: int idx, elseidx;
1.1 otto 1481: struct number *a, *b;
1482: bool ok;
1483: struct value *v;
1484:
1.32 otto 1485: elseidx = NO_ELSE;
1486: idx = readreg();
1.11 otto 1487: if (readch() == 'e')
1.32 otto 1488: elseidx = readreg();
1.11 otto 1489: else
1490: unreadch();
1.1 otto 1491:
1492: a = pop_number();
1.11 otto 1493: if (a == NULL)
1.1 otto 1494: return;
1495: b = pop_number();
1496: if (b == NULL) {
1497: push_number(a);
1498: return;
1499: }
1500:
1.16 otto 1501: ok = compare_numbers(type, a, b);
1.1 otto 1502:
1.32 otto 1503: if (!ok && elseidx != NO_ELSE)
1504: idx = elseidx;
1.11 otto 1505:
1.32 otto 1506: if (idx >= 0 && (ok || (!ok && elseidx != NO_ELSE))) {
1507: v = stack_tos(&bmachine.reg[idx]);
1.1 otto 1508: if (v == NULL)
1.32 otto 1509: warnx("register '%c' (0%o) is empty", idx, idx);
1.1 otto 1510: else {
1511: switch(v->type) {
1512: case BCODE_NONE:
1.32 otto 1513: warnx("register '%c' (0%o) is empty", idx, idx);
1.1 otto 1514: break;
1515: case BCODE_NUMBER:
1516: warn("eval called with non-string argument");
1517: break;
1518: case BCODE_STRING:
1519: eval_string(bstrdup(v->u.string));
1520: break;
1521: }
1522: }
1523: }
1524: }
1525:
1526:
1527: static void
1528: nop(void)
1529: {
1530: }
1531:
1.2 deraadt 1532: static void
1.1 otto 1533: quit(void)
1534: {
1.2 deraadt 1535: if (bmachine.readsp < 2)
1.1 otto 1536: exit(0);
1537: src_free();
1538: bmachine.readsp--;
1539: src_free();
1540: bmachine.readsp--;
1541: }
1542:
1543: static void
1544: quitN(void)
1545: {
1546: struct number *n;
1547: u_long i;
1548:
1549: n = pop_number();
1550: if (n == NULL)
1551: return;
1552: i = get_ulong(n);
1.37 otto 1553: free_number(n);
1.1 otto 1554: if (i == BN_MASK2 || i == 0)
1555: warnx("Q command requires a number >= 1");
1556: else if (bmachine.readsp < i)
1557: warnx("Q command argument exceeded string execution depth");
1558: else {
1559: while (i-- > 0) {
1560: src_free();
1561: bmachine.readsp--;
1562: }
1563: }
1564: }
1565:
1566: static void
1.9 otto 1567: skipN(void)
1568: {
1569: struct number *n;
1570: u_long i;
1571:
1572: n = pop_number();
1573: if (n == NULL)
1574: return;
1575: i = get_ulong(n);
1576: if (i == BN_MASK2)
1577: warnx("J command requires a number >= 0");
1578: else if (i > 0 && bmachine.readsp < i)
1579: warnx("J command argument exceeded string execution depth");
1580: else {
1581: while (i-- > 0) {
1582: src_free();
1583: bmachine.readsp--;
1584: }
1585: skip_until_mark();
1586: }
1587: }
1588:
1589: static void
1590: skip_until_mark(void)
1591: {
1592: for (;;) {
1.54 otto 1593: switch (readch()) {
1.9 otto 1594: case 'M':
1595: return;
1596: case EOF:
1597: errx(1, "mark not found");
1598: return;
1599: case 'l':
1600: case 'L':
1601: case 's':
1602: case 'S':
1603: case ':':
1604: case ';':
1605: case '<':
1606: case '>':
1607: case '=':
1.31 otto 1608: (void)readreg();
1.12 otto 1609: if (readch() == 'e')
1.31 otto 1610: (void)readreg();
1.12 otto 1611: else
1612: unreadch();
1.9 otto 1613: break;
1614: case '[':
1615: free(read_string(&bmachine.readstack[bmachine.readsp]));
1616: break;
1617: case '!':
1.54 otto 1618: switch (readch()) {
1.9 otto 1619: case '<':
1620: case '>':
1621: case '=':
1.31 otto 1622: (void)readreg();
1.12 otto 1623: if (readch() == 'e')
1.31 otto 1624: (void)readreg();
1.12 otto 1625: else
1626: unreadch();
1.9 otto 1627: break;
1628: default:
1629: free(readline());
1630: break;
1631: }
1632: break;
1633: default:
1634: break;
1635: }
1636: }
1637: }
1638:
1639: static void
1.1 otto 1640: parse_number(void)
1641: {
1642: unreadch();
1643: push_number(readnumber(&bmachine.readstack[bmachine.readsp],
1644: bmachine.ibase));
1645: }
1646:
1647: static void
1648: unknown(void)
1649: {
1650: int ch = bmachine.readstack[bmachine.readsp].lastchar;
1651: warnx("%c (0%o) is unimplemented", ch, ch);
1652: }
1653:
1654: static void
1655: eval_string(char *p)
1656: {
1657: int ch;
1658:
1659: if (bmachine.readsp > 0) {
1660: /* Check for tail call. Do not recurse in that case. */
1661: ch = readch();
1662: if (ch == EOF) {
1663: src_free();
1664: src_setstring(&bmachine.readstack[bmachine.readsp], p);
1665: return;
1666: } else
1667: unreadch();
1668: }
1.27 otto 1669: if (bmachine.readsp == bmachine.readstack_sz - 1) {
1670: size_t newsz = bmachine.readstack_sz * 2;
1671: struct source *stack;
1.46 doug 1672: stack = reallocarray(bmachine.readstack, newsz,
1.27 otto 1673: sizeof(struct source));
1674: if (stack == NULL)
1675: err(1, "recursion too deep");
1676: bmachine.readstack_sz = newsz;
1677: bmachine.readstack = stack;
1678: }
1.1 otto 1679: src_setstring(&bmachine.readstack[++bmachine.readsp], p);
1680: }
1681:
1682: static void
1683: eval_line(void)
1684: {
1685: /* Always read from stdin */
1686: struct source in;
1687: char *p;
1688:
1.38 otto 1689: clearerr(stdin);
1.1 otto 1690: src_setstream(&in, stdin);
1691: p = (*in.vtable->readline)(&in);
1692: eval_string(p);
1693: }
1694:
1695: static void
1696: eval_tos(void)
1697: {
1698: char *p;
1699:
1700: p = pop_string();
1.49 otto 1701: if (p != NULL)
1702: eval_string(p);
1.1 otto 1703: }
1704:
1705: void
1706: eval(void)
1707: {
1708: int ch;
1709:
1710: for (;;) {
1711: ch = readch();
1712: if (ch == EOF) {
1713: if (bmachine.readsp == 0)
1.24 otto 1714: return;
1.1 otto 1715: src_free();
1716: bmachine.readsp--;
1717: continue;
1.20 otto 1718: }
1719: if (bmachine.interrupted) {
1720: if (bmachine.readsp > 0) {
1721: src_free();
1722: bmachine.readsp--;
1723: continue;
1.22 otto 1724: } else
1.20 otto 1725: bmachine.interrupted = false;
1.1 otto 1726: }
1.9 otto 1727: #ifdef DEBUGGING
1.31 otto 1728: (void)fprintf(stderr, "# %c\n", ch);
1.9 otto 1729: stack_print(stderr, &bmachine.stack, "* ",
1730: bmachine.obase);
1.36 otto 1731: (void)fprintf(stderr, "%zd =>\n", bmachine.readsp);
1.9 otto 1732: #endif
1.1 otto 1733:
1.52 tom 1734: if (0 <= ch && ch < nitems(jump_table))
1.1 otto 1735: (*jump_table[ch])();
1736: else
1.52 tom 1737: unknown();
1.1 otto 1738:
1.9 otto 1739: #ifdef DEBUGGING
1740: stack_print(stderr, &bmachine.stack, "* ",
1741: bmachine.obase);
1.36 otto 1742: (void)fprintf(stderr, "%zd ==\n", bmachine.readsp);
1.9 otto 1743: #endif
1.1 otto 1744: }
1745: }