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