1*658eb9e1SMichael Kruse /*
2*658eb9e1SMichael Kruse Name: imcalc.c
3*658eb9e1SMichael Kruse Purpose: Simple RPN calculator based on IMath library.
4*658eb9e1SMichael Kruse Author: M. J. Fromberger
5*658eb9e1SMichael Kruse
6*658eb9e1SMichael Kruse This is a very simplistic RPN calculator that will let you test the features
7*658eb9e1SMichael Kruse of the IMath built-in functions.
8*658eb9e1SMichael Kruse
9*658eb9e1SMichael Kruse Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
10*658eb9e1SMichael Kruse
11*658eb9e1SMichael Kruse Permission is hereby granted, free of charge, to any person obtaining a copy
12*658eb9e1SMichael Kruse of this software and associated documentation files (the "Software"), to deal
13*658eb9e1SMichael Kruse in the Software without restriction, including without limitation the rights
14*658eb9e1SMichael Kruse to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15*658eb9e1SMichael Kruse copies of the Software, and to permit persons to whom the Software is
16*658eb9e1SMichael Kruse furnished to do so, subject to the following conditions:
17*658eb9e1SMichael Kruse
18*658eb9e1SMichael Kruse The above copyright notice and this permission notice shall be included in
19*658eb9e1SMichael Kruse all copies or substantial portions of the Software.
20*658eb9e1SMichael Kruse
21*658eb9e1SMichael Kruse THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22*658eb9e1SMichael Kruse IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23*658eb9e1SMichael Kruse FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24*658eb9e1SMichael Kruse AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25*658eb9e1SMichael Kruse LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26*658eb9e1SMichael Kruse OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27*658eb9e1SMichael Kruse SOFTWARE.
28*658eb9e1SMichael Kruse */
29*658eb9e1SMichael Kruse
30*658eb9e1SMichael Kruse #include <assert.h>
31*658eb9e1SMichael Kruse #include <ctype.h>
32*658eb9e1SMichael Kruse #include <errno.h>
33*658eb9e1SMichael Kruse #include <limits.h>
34*658eb9e1SMichael Kruse #include <stdio.h>
35*658eb9e1SMichael Kruse #include <stdlib.h>
36*658eb9e1SMichael Kruse #include <string.h>
37*658eb9e1SMichael Kruse #include <strings.h> /* for strcasecmp */
38*658eb9e1SMichael Kruse
39*658eb9e1SMichael Kruse #include <getopt.h>
40*658eb9e1SMichael Kruse #include <unistd.h>
41*658eb9e1SMichael Kruse
42*658eb9e1SMichael Kruse #include "imath.h"
43*658eb9e1SMichael Kruse #include "imrat.h"
44*658eb9e1SMichael Kruse #include "iprime.h"
45*658eb9e1SMichael Kruse
46*658eb9e1SMichael Kruse /* A cstate_t represents a stack of operands; numeric operands are pushed on
47*658eb9e1SMichael Kruse the stack, and commands cause them to be consumed in various ways.
48*658eb9e1SMichael Kruse */
49*658eb9e1SMichael Kruse typedef struct {
50*658eb9e1SMichael Kruse /* Operand stack */
51*658eb9e1SMichael Kruse mp_int *elts;
52*658eb9e1SMichael Kruse mp_size alloc; /* number of slots available */
53*658eb9e1SMichael Kruse mp_size used; /* number of slots free */
54*658eb9e1SMichael Kruse
55*658eb9e1SMichael Kruse /* Named variables */
56*658eb9e1SMichael Kruse mp_int *mem; /* named memory slots */
57*658eb9e1SMichael Kruse char **names; /* names of memory slots */
58*658eb9e1SMichael Kruse mp_size mslots; /* number of memory slots */
59*658eb9e1SMichael Kruse mp_size mused; /* number of used memories */
60*658eb9e1SMichael Kruse
61*658eb9e1SMichael Kruse /* I/O components */
62*658eb9e1SMichael Kruse FILE *ifp; /* input file handle */
63*658eb9e1SMichael Kruse char *ibuf; /* input scratch buffer */
64*658eb9e1SMichael Kruse int buflen; /* size of scratch buffer */
65*658eb9e1SMichael Kruse } cstate_t;
66*658eb9e1SMichael Kruse
67*658eb9e1SMichael Kruse static mp_result state_init(cstate_t *sp, mp_size n_elts);
68*658eb9e1SMichael Kruse static void state_clear(cstate_t *sp);
69*658eb9e1SMichael Kruse static void stack_flush(cstate_t *sp);
70*658eb9e1SMichael Kruse static mp_result stack_push(cstate_t *sp, mp_int elt);
71*658eb9e1SMichael Kruse static mp_result stack_pop(cstate_t *sp);
72*658eb9e1SMichael Kruse static mp_result mem_insert(cstate_t *sp, const char *name, mp_int value);
73*658eb9e1SMichael Kruse static mp_result mem_recall(cstate_t *sp, const char *name, mp_int value);
74*658eb9e1SMichael Kruse static mp_result mem_clear(cstate_t *sp);
75*658eb9e1SMichael Kruse
76*658eb9e1SMichael Kruse typedef mp_result (*op_func)(cstate_t *);
77*658eb9e1SMichael Kruse
78*658eb9e1SMichael Kruse static mp_result cf_abs(cstate_t *sp);
79*658eb9e1SMichael Kruse static mp_result cf_neg(cstate_t *sp);
80*658eb9e1SMichael Kruse static mp_result cf_add(cstate_t *sp);
81*658eb9e1SMichael Kruse static mp_result cf_sub(cstate_t *sp);
82*658eb9e1SMichael Kruse static mp_result cf_mul(cstate_t *sp);
83*658eb9e1SMichael Kruse static mp_result cf_divmod(cstate_t *sp);
84*658eb9e1SMichael Kruse static mp_result cf_div(cstate_t *sp);
85*658eb9e1SMichael Kruse static mp_result cf_mod(cstate_t *sp);
86*658eb9e1SMichael Kruse static mp_result cf_expt(cstate_t *sp);
87*658eb9e1SMichael Kruse static mp_result cf_exptmod(cstate_t *sp);
88*658eb9e1SMichael Kruse static mp_result cf_square(cstate_t *sp);
89*658eb9e1SMichael Kruse static mp_result cf_invmod(cstate_t *sp);
90*658eb9e1SMichael Kruse static mp_result cf_gcd(cstate_t *sp);
91*658eb9e1SMichael Kruse static mp_result cf_xgcd(cstate_t *sp);
92*658eb9e1SMichael Kruse static mp_result cf_sqrt(cstate_t *sp);
93*658eb9e1SMichael Kruse static mp_result cf_root(cstate_t *sp);
94*658eb9e1SMichael Kruse static mp_result cf_cmplt(cstate_t *sp);
95*658eb9e1SMichael Kruse static mp_result cf_cmpgt(cstate_t *sp);
96*658eb9e1SMichael Kruse static mp_result cf_cmple(cstate_t *sp);
97*658eb9e1SMichael Kruse static mp_result cf_cmpge(cstate_t *sp);
98*658eb9e1SMichael Kruse static mp_result cf_cmpeq(cstate_t *sp);
99*658eb9e1SMichael Kruse static mp_result cf_cmpne(cstate_t *sp);
100*658eb9e1SMichael Kruse static mp_result cf_inc(cstate_t *sp);
101*658eb9e1SMichael Kruse static mp_result cf_dec(cstate_t *sp);
102*658eb9e1SMichael Kruse static mp_result cf_fact(cstate_t *sp);
103*658eb9e1SMichael Kruse static mp_result cf_pprint(cstate_t *sp);
104*658eb9e1SMichael Kruse static mp_result cf_print(cstate_t *sp);
105*658eb9e1SMichael Kruse static mp_result cf_pstack(cstate_t *sp);
106*658eb9e1SMichael Kruse static mp_result cf_clstk(cstate_t *sp);
107*658eb9e1SMichael Kruse static mp_result cf_pop(cstate_t *sp);
108*658eb9e1SMichael Kruse static mp_result cf_dup(cstate_t *sp);
109*658eb9e1SMichael Kruse static mp_result cf_copy(cstate_t *sp);
110*658eb9e1SMichael Kruse static mp_result cf_swap(cstate_t *sp);
111*658eb9e1SMichael Kruse static mp_result cf_rot(cstate_t *sp);
112*658eb9e1SMichael Kruse static mp_result cf_pick(cstate_t *sp);
113*658eb9e1SMichael Kruse static mp_result cf_setr(cstate_t *sp);
114*658eb9e1SMichael Kruse static mp_result cf_setbin(cstate_t *sp);
115*658eb9e1SMichael Kruse static mp_result cf_help(cstate_t *sp);
116*658eb9e1SMichael Kruse static mp_result cf_store(cstate_t *sp);
117*658eb9e1SMichael Kruse static mp_result cf_recall(cstate_t *sp);
118*658eb9e1SMichael Kruse static mp_result cf_cmem(cstate_t *sp);
119*658eb9e1SMichael Kruse static mp_result cf_pmem(cstate_t *sp);
120*658eb9e1SMichael Kruse static mp_result cf_qrecall(cstate_t *sp);
121*658eb9e1SMichael Kruse
122*658eb9e1SMichael Kruse typedef struct {
123*658eb9e1SMichael Kruse char *name; /* The name of the operator. */
124*658eb9e1SMichael Kruse int stack_size; /* Number of stack arguments required. */
125*658eb9e1SMichael Kruse op_func handler; /* Function implementing operation. */
126*658eb9e1SMichael Kruse char *descript; /* Human-readable description. */
127*658eb9e1SMichael Kruse } calcop_t;
128*658eb9e1SMichael Kruse
129*658eb9e1SMichael Kruse static calcop_t g_ops[] = {
130*658eb9e1SMichael Kruse {"abs", 1, cf_abs, "x -- |x|"},
131*658eb9e1SMichael Kruse {"neg", 1, cf_neg, "x -- (-x)"},
132*658eb9e1SMichael Kruse {"+", 2, cf_add, "x y -- (x+y)"},
133*658eb9e1SMichael Kruse {"add", 2, cf_add, "x y -- (x+y)"},
134*658eb9e1SMichael Kruse {"-", 2, cf_sub, "x y -- (x-y)"},
135*658eb9e1SMichael Kruse {"sub", 2, cf_sub, "x y -- (x-y)"},
136*658eb9e1SMichael Kruse {"*", 2, cf_mul, "x y -- (x*y)"},
137*658eb9e1SMichael Kruse {"mul", 2, cf_mul, "x y -- (x*y)"},
138*658eb9e1SMichael Kruse {"/", 2, cf_divmod, "x y -- q r ; x = yq + r, 0 <= r < y"},
139*658eb9e1SMichael Kruse {"//", 2, cf_div, "x y -- (x div y)"},
140*658eb9e1SMichael Kruse {"div", 2, cf_div, "x y -- (x div y)"},
141*658eb9e1SMichael Kruse {"%", 2, cf_mod, "x y -- (x mod y)"},
142*658eb9e1SMichael Kruse {"mod", 2, cf_mod, "x y -- (x mod y)"},
143*658eb9e1SMichael Kruse {"^", 2, cf_expt, "x y -- (x^y)"},
144*658eb9e1SMichael Kruse {"expt", 2, cf_expt, "x y -- (x^y)"},
145*658eb9e1SMichael Kruse {"^^", 3, cf_exptmod, "x y m -- (x^y mod m)"},
146*658eb9e1SMichael Kruse {"emod", 3, cf_exptmod, "x y m -- (x^y mod m)"},
147*658eb9e1SMichael Kruse {"sqr", 1, cf_square, "x -- (x*x)"},
148*658eb9e1SMichael Kruse {"inv", 2, cf_invmod, "x m -- (1/x mod m)"},
149*658eb9e1SMichael Kruse {"gcd", 2, cf_gcd, "x y -- gcd(x, y)"},
150*658eb9e1SMichael Kruse {"xgcd", 2, cf_xgcd, "x y -- g u v ; g = ux + vy"},
151*658eb9e1SMichael Kruse {"sqrt", 1, cf_sqrt, "x -- floor(sqrt(x))"},
152*658eb9e1SMichael Kruse {"root", 2, cf_root, "x y -- floor(x^{1/y}) ; y > 0"},
153*658eb9e1SMichael Kruse {"<", 2, cf_cmplt, "x y -- (x<y)"},
154*658eb9e1SMichael Kruse {">", 2, cf_cmpgt, "x y -- (x>y)"},
155*658eb9e1SMichael Kruse {"<=", 2, cf_cmple, "x y -- (x<=y)"},
156*658eb9e1SMichael Kruse {">=", 2, cf_cmpge, "x y -- (x>=y)"},
157*658eb9e1SMichael Kruse {"=", 2, cf_cmpeq, "x y -- (x=y)"},
158*658eb9e1SMichael Kruse {"<>", 2, cf_cmpne, "x y -- (x<>y)"},
159*658eb9e1SMichael Kruse {"inc", 1, cf_inc, "x -- (x+1)"},
160*658eb9e1SMichael Kruse {"dec", 1, cf_dec, "x -- (x-1)"},
161*658eb9e1SMichael Kruse {"!", 1, cf_fact, "x -- x!"},
162*658eb9e1SMichael Kruse {"fact", 1, cf_fact, "x -- x!"},
163*658eb9e1SMichael Kruse
164*658eb9e1SMichael Kruse {".", 1, cf_pprint, "x -- ; print x in current output mode"},
165*658eb9e1SMichael Kruse {";", 1, cf_print, "x -- x ; print x in current output mode"},
166*658eb9e1SMichael Kruse {"?", 0, cf_pstack, "-- ; print stack"},
167*658eb9e1SMichael Kruse {"cls", 0, cf_clstk, "... -- ; clear stack"},
168*658eb9e1SMichael Kruse {"$", 1, cf_pop, "x --"},
169*658eb9e1SMichael Kruse {"drop", 1, cf_pop, "x --"},
170*658eb9e1SMichael Kruse {"dup", 1, cf_dup, "x -- x x"},
171*658eb9e1SMichael Kruse {"copy", 2, cf_copy, "vn ... v1 v0 n -- vn ... v0 vn ... v0"},
172*658eb9e1SMichael Kruse {"swap", 2, cf_swap, "x y -- y x"},
173*658eb9e1SMichael Kruse {"rot", 3, cf_rot, "a b c -- b c a"},
174*658eb9e1SMichael Kruse {"pick", 2, cf_pick, "... v2 v1 v0 n -- ... v2 v1 v0 vn"},
175*658eb9e1SMichael Kruse
176*658eb9e1SMichael Kruse {">>", 1, cf_store, "x -- ; save in named variable"},
177*658eb9e1SMichael Kruse {"<<", 0, cf_recall, "-- x ; recall from named variable"},
178*658eb9e1SMichael Kruse {"clm", 0, cf_cmem, "-- ; clear memory"},
179*658eb9e1SMichael Kruse {"??", 0, cf_pmem, "-- ; print memory"},
180*658eb9e1SMichael Kruse
181*658eb9e1SMichael Kruse {"out", 1, cf_setr, "r -- ; set output radix to r"},
182*658eb9e1SMichael Kruse {"bin", 0, cf_setbin, "-- ; set output format to binary"},
183*658eb9e1SMichael Kruse {"help", 0, cf_help, "-- ; print help message"},
184*658eb9e1SMichael Kruse
185*658eb9e1SMichael Kruse /* This is the end-marker, but it is also used to catch implicit
186*658eb9e1SMichael Kruse variable lookups from memory.
187*658eb9e1SMichael Kruse */
188*658eb9e1SMichael Kruse {NULL, 0, cf_qrecall, "-- x ; recall from named variable"},
189*658eb9e1SMichael Kruse };
190*658eb9e1SMichael Kruse
191*658eb9e1SMichael Kruse #define BUFFER_SIZE 16384 /* max. length of input values, in chars */
192*658eb9e1SMichael Kruse
193*658eb9e1SMichael Kruse /* Token types from the primitive lexical analyzer */
194*658eb9e1SMichael Kruse typedef enum { t_eof, t_symbol, t_number, t_error } token_t;
195*658eb9e1SMichael Kruse
196*658eb9e1SMichael Kruse static token_t next_token(FILE *ifp, char *buf, int size);
197*658eb9e1SMichael Kruse static mp_result read_number(char *buf, mp_int *out);
198*658eb9e1SMichael Kruse static int find_command(cstate_t *ops);
199*658eb9e1SMichael Kruse static void print_value(mp_int v);
200*658eb9e1SMichael Kruse static mp_result run_file(FILE *ifp, cstate_t *op_state);
201*658eb9e1SMichael Kruse
202*658eb9e1SMichael Kruse /* Error code used internally to signal input problems. */
203*658eb9e1SMichael Kruse static mp_result MP_INPUT;
204*658eb9e1SMichael Kruse
205*658eb9e1SMichael Kruse static int g_output_radix = 10; /* output radix */
206*658eb9e1SMichael Kruse static FILE *g_output_file = NULL;
207*658eb9e1SMichael Kruse
main(int argc,char * argv[])208*658eb9e1SMichael Kruse int main(int argc, char *argv[]) {
209*658eb9e1SMichael Kruse extern char *optarg;
210*658eb9e1SMichael Kruse extern int optind;
211*658eb9e1SMichael Kruse
212*658eb9e1SMichael Kruse int opt, errs = 0;
213*658eb9e1SMichael Kruse FILE *ifp;
214*658eb9e1SMichael Kruse
215*658eb9e1SMichael Kruse cstate_t op_state;
216*658eb9e1SMichael Kruse mp_result res;
217*658eb9e1SMichael Kruse
218*658eb9e1SMichael Kruse MP_INPUT = MP_MINERR - 1;
219*658eb9e1SMichael Kruse
220*658eb9e1SMichael Kruse g_output_file = stdout;
221*658eb9e1SMichael Kruse while ((opt = getopt(argc, argv, "ho:")) != EOF) {
222*658eb9e1SMichael Kruse switch (opt) {
223*658eb9e1SMichael Kruse case 'h':
224*658eb9e1SMichael Kruse fprintf(
225*658eb9e1SMichael Kruse stderr,
226*658eb9e1SMichael Kruse "Usage: imcalc [-h] [-o <output>] input*\n\n"
227*658eb9e1SMichael Kruse "Options:\n"
228*658eb9e1SMichael Kruse " -h : display this help message.\n"
229*658eb9e1SMichael Kruse " -o <output> : send output to file.\n\n"
230*658eb9e1SMichael Kruse
231*658eb9e1SMichael Kruse "If no input files are given, the standard input is read. The\n"
232*658eb9e1SMichael Kruse "special file name \"-\" is interpreted to mean the standard "
233*658eb9e1SMichael Kruse "input.\n"
234*658eb9e1SMichael Kruse "Output goes to standard output unless \"-o\" is used.\n\n");
235*658eb9e1SMichael Kruse return 0;
236*658eb9e1SMichael Kruse
237*658eb9e1SMichael Kruse case 'o':
238*658eb9e1SMichael Kruse if ((g_output_file = fopen(optarg, "wt")) == NULL) {
239*658eb9e1SMichael Kruse fprintf(stderr, "Unable to open \"%s\" for writing: %s\n", optarg,
240*658eb9e1SMichael Kruse strerror(errno));
241*658eb9e1SMichael Kruse return 1;
242*658eb9e1SMichael Kruse }
243*658eb9e1SMichael Kruse break;
244*658eb9e1SMichael Kruse
245*658eb9e1SMichael Kruse default:
246*658eb9e1SMichael Kruse fprintf(stderr,
247*658eb9e1SMichael Kruse "Usage: imcalc [-h] [-o <output>] input*\n"
248*658eb9e1SMichael Kruse " [use \"imcalc -h\" to get help]\n\n");
249*658eb9e1SMichael Kruse return 1;
250*658eb9e1SMichael Kruse }
251*658eb9e1SMichael Kruse }
252*658eb9e1SMichael Kruse
253*658eb9e1SMichael Kruse if ((res = state_init(&op_state, 1)) != MP_OK) {
254*658eb9e1SMichael Kruse fprintf(stderr, "Error: state_init: %s\n", mp_error_string(res));
255*658eb9e1SMichael Kruse return 1;
256*658eb9e1SMichael Kruse }
257*658eb9e1SMichael Kruse
258*658eb9e1SMichael Kruse if (optind < argc) {
259*658eb9e1SMichael Kruse int ix;
260*658eb9e1SMichael Kruse
261*658eb9e1SMichael Kruse for (ix = optind; ix < argc; ++ix) {
262*658eb9e1SMichael Kruse if (strcmp(argv[ix], "-") == 0)
263*658eb9e1SMichael Kruse ifp = stdin;
264*658eb9e1SMichael Kruse else if ((ifp = fopen(argv[optind], "rt")) == NULL) {
265*658eb9e1SMichael Kruse fprintf(stderr, "Unable to open \"%s\" for reading: %s\n", argv[optind],
266*658eb9e1SMichael Kruse strerror(errno));
267*658eb9e1SMichael Kruse return 1;
268*658eb9e1SMichael Kruse }
269*658eb9e1SMichael Kruse
270*658eb9e1SMichael Kruse if (run_file(ifp, &op_state) != MP_OK) ++errs;
271*658eb9e1SMichael Kruse }
272*658eb9e1SMichael Kruse
273*658eb9e1SMichael Kruse state_clear(&op_state);
274*658eb9e1SMichael Kruse return errs > 0;
275*658eb9e1SMichael Kruse } else {
276*658eb9e1SMichael Kruse int rv = 1 - (run_file(stdin, &op_state) == MP_OK);
277*658eb9e1SMichael Kruse state_clear(&op_state);
278*658eb9e1SMichael Kruse return rv;
279*658eb9e1SMichael Kruse }
280*658eb9e1SMichael Kruse }
281*658eb9e1SMichael Kruse
next_token(FILE * ifp,char * buf,int size)282*658eb9e1SMichael Kruse static token_t next_token(FILE *ifp, char *buf, int size) {
283*658eb9e1SMichael Kruse int ch, pos = 0;
284*658eb9e1SMichael Kruse token_t res;
285*658eb9e1SMichael Kruse
286*658eb9e1SMichael Kruse assert(buf != NULL && size > 0);
287*658eb9e1SMichael Kruse
288*658eb9e1SMichael Kruse while ((ch = fgetc(ifp)) != EOF && isspace(ch)) /* empty */
289*658eb9e1SMichael Kruse ;
290*658eb9e1SMichael Kruse
291*658eb9e1SMichael Kruse if (ch == EOF) {
292*658eb9e1SMichael Kruse buf[0] = '\0';
293*658eb9e1SMichael Kruse return t_eof;
294*658eb9e1SMichael Kruse }
295*658eb9e1SMichael Kruse
296*658eb9e1SMichael Kruse if (ch == '-') {
297*658eb9e1SMichael Kruse int next = fgetc(ifp);
298*658eb9e1SMichael Kruse if (next == EOF || !isdigit(next))
299*658eb9e1SMichael Kruse res = t_symbol;
300*658eb9e1SMichael Kruse else
301*658eb9e1SMichael Kruse res = t_number;
302*658eb9e1SMichael Kruse ungetc(next, ifp);
303*658eb9e1SMichael Kruse } else if (isdigit(ch) || ch == '#')
304*658eb9e1SMichael Kruse res = t_number;
305*658eb9e1SMichael Kruse else
306*658eb9e1SMichael Kruse res = t_symbol;
307*658eb9e1SMichael Kruse
308*658eb9e1SMichael Kruse buf[pos++] = ch;
309*658eb9e1SMichael Kruse while ((ch = fgetc(ifp)) != EOF) {
310*658eb9e1SMichael Kruse if ((res == t_number && ispunct(ch) && ch != '-') ||
311*658eb9e1SMichael Kruse (res == t_symbol && isdigit(ch)) || isspace(ch)) {
312*658eb9e1SMichael Kruse ungetc(ch, ifp);
313*658eb9e1SMichael Kruse break;
314*658eb9e1SMichael Kruse } else if (pos + 1 >= size) {
315*658eb9e1SMichael Kruse res = t_error;
316*658eb9e1SMichael Kruse break;
317*658eb9e1SMichael Kruse }
318*658eb9e1SMichael Kruse buf[pos++] = ch;
319*658eb9e1SMichael Kruse }
320*658eb9e1SMichael Kruse
321*658eb9e1SMichael Kruse buf[pos] = '\0';
322*658eb9e1SMichael Kruse return res;
323*658eb9e1SMichael Kruse }
324*658eb9e1SMichael Kruse
read_number(char * buf,mp_int * out)325*658eb9e1SMichael Kruse static mp_result read_number(char *buf, mp_int *out) {
326*658eb9e1SMichael Kruse int radix = 10, pos = 0;
327*658eb9e1SMichael Kruse mp_result res;
328*658eb9e1SMichael Kruse mp_int value;
329*658eb9e1SMichael Kruse
330*658eb9e1SMichael Kruse assert(buf != NULL && out != NULL);
331*658eb9e1SMichael Kruse
332*658eb9e1SMichael Kruse if (buf[pos] == '#') {
333*658eb9e1SMichael Kruse switch (buf[1]) {
334*658eb9e1SMichael Kruse case 'b':
335*658eb9e1SMichael Kruse case 'B':
336*658eb9e1SMichael Kruse radix = 2;
337*658eb9e1SMichael Kruse break;
338*658eb9e1SMichael Kruse case 'd':
339*658eb9e1SMichael Kruse case 'D':
340*658eb9e1SMichael Kruse radix = 10;
341*658eb9e1SMichael Kruse break;
342*658eb9e1SMichael Kruse case 'o':
343*658eb9e1SMichael Kruse case 'O':
344*658eb9e1SMichael Kruse radix = 8;
345*658eb9e1SMichael Kruse break;
346*658eb9e1SMichael Kruse case 'x':
347*658eb9e1SMichael Kruse case 'X':
348*658eb9e1SMichael Kruse radix = 16;
349*658eb9e1SMichael Kruse break;
350*658eb9e1SMichael Kruse default:
351*658eb9e1SMichael Kruse return MP_BADARG;
352*658eb9e1SMichael Kruse }
353*658eb9e1SMichael Kruse
354*658eb9e1SMichael Kruse pos += 2;
355*658eb9e1SMichael Kruse }
356*658eb9e1SMichael Kruse
357*658eb9e1SMichael Kruse if ((value = mp_int_alloc()) == NULL) {
358*658eb9e1SMichael Kruse *out = NULL;
359*658eb9e1SMichael Kruse return MP_MEMORY;
360*658eb9e1SMichael Kruse }
361*658eb9e1SMichael Kruse
362*658eb9e1SMichael Kruse if ((res = mp_int_read_string(value, radix, buf + pos)) != MP_OK) {
363*658eb9e1SMichael Kruse mp_int_free(value);
364*658eb9e1SMichael Kruse *out = NULL;
365*658eb9e1SMichael Kruse return res;
366*658eb9e1SMichael Kruse }
367*658eb9e1SMichael Kruse
368*658eb9e1SMichael Kruse *out = value;
369*658eb9e1SMichael Kruse return res;
370*658eb9e1SMichael Kruse }
371*658eb9e1SMichael Kruse
find_command(cstate_t * op)372*658eb9e1SMichael Kruse static int find_command(cstate_t *op) {
373*658eb9e1SMichael Kruse int ix, jx;
374*658eb9e1SMichael Kruse char *buf = op->ibuf;
375*658eb9e1SMichael Kruse
376*658eb9e1SMichael Kruse /* First, try to find the command by name */
377*658eb9e1SMichael Kruse for (ix = 0; g_ops[ix].name != NULL; ++ix) {
378*658eb9e1SMichael Kruse if (strcasecmp(buf, g_ops[ix].name) == 0) return ix;
379*658eb9e1SMichael Kruse }
380*658eb9e1SMichael Kruse
381*658eb9e1SMichael Kruse /* If we don't find the command, try a variable lookup */
382*658eb9e1SMichael Kruse for (jx = 0; (mp_size)jx < op->mused; ++jx) {
383*658eb9e1SMichael Kruse if (strcmp(buf, op->names[jx]) == 0) return ix; /* sentinel */
384*658eb9e1SMichael Kruse }
385*658eb9e1SMichael Kruse
386*658eb9e1SMichael Kruse /* If variable lookup fails, report command not found */
387*658eb9e1SMichael Kruse return -1;
388*658eb9e1SMichael Kruse }
389*658eb9e1SMichael Kruse
print_value(mp_int v)390*658eb9e1SMichael Kruse static void print_value(mp_int v) {
391*658eb9e1SMichael Kruse if (g_output_radix == 0) {
392*658eb9e1SMichael Kruse mp_result len = mp_int_binary_len(v);
393*658eb9e1SMichael Kruse unsigned char *buf = malloc(len);
394*658eb9e1SMichael Kruse int ix;
395*658eb9e1SMichael Kruse
396*658eb9e1SMichael Kruse if (buf != NULL) {
397*658eb9e1SMichael Kruse mp_int_to_binary(v, buf, len);
398*658eb9e1SMichael Kruse for (ix = 0; ix < len - 1; ++ix) {
399*658eb9e1SMichael Kruse fprintf(g_output_file, "%02x.", buf[ix]);
400*658eb9e1SMichael Kruse }
401*658eb9e1SMichael Kruse fprintf(g_output_file, "%02x\n", buf[ix]);
402*658eb9e1SMichael Kruse free(buf);
403*658eb9e1SMichael Kruse } else {
404*658eb9e1SMichael Kruse fprintf(g_output_file, "<insufficient memory to print>\n");
405*658eb9e1SMichael Kruse }
406*658eb9e1SMichael Kruse } else {
407*658eb9e1SMichael Kruse mp_result len = mp_int_string_len(v, g_output_radix);
408*658eb9e1SMichael Kruse char *buf = malloc(len);
409*658eb9e1SMichael Kruse
410*658eb9e1SMichael Kruse if (buf != NULL) {
411*658eb9e1SMichael Kruse mp_int_to_string(v, g_output_radix, buf, len);
412*658eb9e1SMichael Kruse fputs(buf, g_output_file);
413*658eb9e1SMichael Kruse fputc('\n', g_output_file);
414*658eb9e1SMichael Kruse free(buf);
415*658eb9e1SMichael Kruse } else {
416*658eb9e1SMichael Kruse fprintf(g_output_file, "<insufficient memory to print>\n");
417*658eb9e1SMichael Kruse }
418*658eb9e1SMichael Kruse }
419*658eb9e1SMichael Kruse }
420*658eb9e1SMichael Kruse
run_file(FILE * ifp,cstate_t * op_state)421*658eb9e1SMichael Kruse static mp_result run_file(FILE *ifp, cstate_t *op_state) {
422*658eb9e1SMichael Kruse mp_result res = MP_OK;
423*658eb9e1SMichael Kruse token_t next;
424*658eb9e1SMichael Kruse
425*658eb9e1SMichael Kruse op_state->ifp = ifp;
426*658eb9e1SMichael Kruse while ((next = next_token(ifp, op_state->ibuf, op_state->buflen)) != t_eof) {
427*658eb9e1SMichael Kruse mp_int value = NULL;
428*658eb9e1SMichael Kruse int cpos;
429*658eb9e1SMichael Kruse
430*658eb9e1SMichael Kruse switch (next) {
431*658eb9e1SMichael Kruse case t_number:
432*658eb9e1SMichael Kruse if ((res = read_number(op_state->ibuf, &value)) != MP_OK)
433*658eb9e1SMichael Kruse fprintf(stderr, "error: invalid number syntax: %s\n", op_state->ibuf);
434*658eb9e1SMichael Kruse else if ((res = stack_push(op_state, value)) != MP_OK)
435*658eb9e1SMichael Kruse goto EXIT;
436*658eb9e1SMichael Kruse break;
437*658eb9e1SMichael Kruse case t_symbol:
438*658eb9e1SMichael Kruse if ((cpos = find_command(op_state)) < 0) {
439*658eb9e1SMichael Kruse fprintf(stderr, "error: command not understood: %s\n",
440*658eb9e1SMichael Kruse op_state->ibuf);
441*658eb9e1SMichael Kruse } else if (op_state->used < (mp_size)g_ops[cpos].stack_size) {
442*658eb9e1SMichael Kruse fprintf(stderr, "error: not enough arguments (have %d, want %d)\n",
443*658eb9e1SMichael Kruse op_state->used, g_ops[cpos].stack_size);
444*658eb9e1SMichael Kruse } else if ((res = (g_ops[cpos].handler)(op_state)) != MP_OK) {
445*658eb9e1SMichael Kruse if (res == MP_INPUT) {
446*658eb9e1SMichael Kruse fprintf(stderr, "error: incorrect input format\n");
447*658eb9e1SMichael Kruse } else {
448*658eb9e1SMichael Kruse fprintf(stderr, "error: %s\n", mp_error_string(res));
449*658eb9e1SMichael Kruse }
450*658eb9e1SMichael Kruse }
451*658eb9e1SMichael Kruse break;
452*658eb9e1SMichael Kruse default:
453*658eb9e1SMichael Kruse fprintf(stderr, "error: invalid input token: %s\n", op_state->ibuf);
454*658eb9e1SMichael Kruse res = MP_BADARG;
455*658eb9e1SMichael Kruse goto EXIT;
456*658eb9e1SMichael Kruse }
457*658eb9e1SMichael Kruse }
458*658eb9e1SMichael Kruse
459*658eb9e1SMichael Kruse EXIT:
460*658eb9e1SMichael Kruse return res;
461*658eb9e1SMichael Kruse }
462*658eb9e1SMichael Kruse
state_init(cstate_t * sp,mp_size n_elts)463*658eb9e1SMichael Kruse static mp_result state_init(cstate_t *sp, mp_size n_elts) {
464*658eb9e1SMichael Kruse int ix;
465*658eb9e1SMichael Kruse
466*658eb9e1SMichael Kruse assert(sp != NULL && n_elts > 0);
467*658eb9e1SMichael Kruse
468*658eb9e1SMichael Kruse if ((sp->elts = malloc(n_elts * sizeof(*(sp->elts)))) == NULL)
469*658eb9e1SMichael Kruse return MP_MEMORY;
470*658eb9e1SMichael Kruse if ((sp->mem = malloc(n_elts * sizeof(*(sp->mem)))) == NULL) {
471*658eb9e1SMichael Kruse free(sp->elts);
472*658eb9e1SMichael Kruse return MP_MEMORY;
473*658eb9e1SMichael Kruse }
474*658eb9e1SMichael Kruse if ((sp->names = malloc(n_elts * sizeof(*(sp->names)))) == NULL) {
475*658eb9e1SMichael Kruse free(sp->mem);
476*658eb9e1SMichael Kruse free(sp->elts);
477*658eb9e1SMichael Kruse return MP_MEMORY;
478*658eb9e1SMichael Kruse }
479*658eb9e1SMichael Kruse if ((sp->ibuf = malloc(BUFFER_SIZE * sizeof(char))) == NULL) {
480*658eb9e1SMichael Kruse free(sp->names);
481*658eb9e1SMichael Kruse free(sp->mem);
482*658eb9e1SMichael Kruse free(sp->elts);
483*658eb9e1SMichael Kruse return MP_MEMORY;
484*658eb9e1SMichael Kruse }
485*658eb9e1SMichael Kruse
486*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < n_elts; ++ix) {
487*658eb9e1SMichael Kruse sp->elts[ix] = NULL;
488*658eb9e1SMichael Kruse sp->mem[ix] = NULL;
489*658eb9e1SMichael Kruse sp->names[ix] = NULL;
490*658eb9e1SMichael Kruse }
491*658eb9e1SMichael Kruse
492*658eb9e1SMichael Kruse sp->alloc = n_elts;
493*658eb9e1SMichael Kruse sp->used = 0;
494*658eb9e1SMichael Kruse sp->mslots = n_elts;
495*658eb9e1SMichael Kruse sp->mused = 0;
496*658eb9e1SMichael Kruse sp->buflen = BUFFER_SIZE;
497*658eb9e1SMichael Kruse
498*658eb9e1SMichael Kruse return MP_OK;
499*658eb9e1SMichael Kruse }
500*658eb9e1SMichael Kruse
state_clear(cstate_t * sp)501*658eb9e1SMichael Kruse static void state_clear(cstate_t *sp) {
502*658eb9e1SMichael Kruse assert(sp != NULL);
503*658eb9e1SMichael Kruse
504*658eb9e1SMichael Kruse if (sp->elts != NULL) {
505*658eb9e1SMichael Kruse int ix;
506*658eb9e1SMichael Kruse
507*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->used; ++ix) {
508*658eb9e1SMichael Kruse mp_int_clear(sp->elts[ix]);
509*658eb9e1SMichael Kruse sp->elts[ix] = NULL;
510*658eb9e1SMichael Kruse }
511*658eb9e1SMichael Kruse
512*658eb9e1SMichael Kruse free(sp->elts);
513*658eb9e1SMichael Kruse sp->elts = NULL;
514*658eb9e1SMichael Kruse sp->alloc = 0;
515*658eb9e1SMichael Kruse sp->used = 0;
516*658eb9e1SMichael Kruse }
517*658eb9e1SMichael Kruse if (sp->mem != NULL) {
518*658eb9e1SMichael Kruse int ix;
519*658eb9e1SMichael Kruse
520*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->mused; ++ix) {
521*658eb9e1SMichael Kruse mp_int_free(sp->mem[ix]);
522*658eb9e1SMichael Kruse sp->mem[ix] = NULL;
523*658eb9e1SMichael Kruse free(sp->names[ix]);
524*658eb9e1SMichael Kruse sp->names[ix] = NULL;
525*658eb9e1SMichael Kruse }
526*658eb9e1SMichael Kruse
527*658eb9e1SMichael Kruse free(sp->mem);
528*658eb9e1SMichael Kruse sp->mem = NULL;
529*658eb9e1SMichael Kruse free(sp->names);
530*658eb9e1SMichael Kruse sp->names = NULL;
531*658eb9e1SMichael Kruse
532*658eb9e1SMichael Kruse sp->mslots = 0;
533*658eb9e1SMichael Kruse sp->mused = 0;
534*658eb9e1SMichael Kruse }
535*658eb9e1SMichael Kruse if (sp->ibuf != NULL) {
536*658eb9e1SMichael Kruse free(sp->ibuf);
537*658eb9e1SMichael Kruse sp->buflen = 0;
538*658eb9e1SMichael Kruse }
539*658eb9e1SMichael Kruse if (sp->ifp != NULL) {
540*658eb9e1SMichael Kruse fclose(sp->ifp);
541*658eb9e1SMichael Kruse sp->ifp = NULL;
542*658eb9e1SMichael Kruse }
543*658eb9e1SMichael Kruse }
544*658eb9e1SMichael Kruse
stack_flush(cstate_t * sp)545*658eb9e1SMichael Kruse static void stack_flush(cstate_t *sp) {
546*658eb9e1SMichael Kruse int ix;
547*658eb9e1SMichael Kruse
548*658eb9e1SMichael Kruse assert(sp != NULL && sp->elts != NULL);
549*658eb9e1SMichael Kruse
550*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->used; ++ix) {
551*658eb9e1SMichael Kruse mp_int_clear(sp->elts[ix]);
552*658eb9e1SMichael Kruse sp->elts[ix] = NULL;
553*658eb9e1SMichael Kruse }
554*658eb9e1SMichael Kruse
555*658eb9e1SMichael Kruse sp->used = 0;
556*658eb9e1SMichael Kruse }
557*658eb9e1SMichael Kruse
stack_push(cstate_t * sp,mp_int elt)558*658eb9e1SMichael Kruse static mp_result stack_push(cstate_t *sp, mp_int elt) {
559*658eb9e1SMichael Kruse if (sp->used >= sp->alloc) {
560*658eb9e1SMichael Kruse mp_size nsize = 2 * sp->alloc;
561*658eb9e1SMichael Kruse mp_int *tmp;
562*658eb9e1SMichael Kruse int ix;
563*658eb9e1SMichael Kruse
564*658eb9e1SMichael Kruse if ((tmp = malloc(nsize * sizeof(*(sp->elts)))) == NULL) return MP_MEMORY;
565*658eb9e1SMichael Kruse
566*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->used; ++ix) {
567*658eb9e1SMichael Kruse tmp[ix] = sp->elts[ix];
568*658eb9e1SMichael Kruse }
569*658eb9e1SMichael Kruse
570*658eb9e1SMichael Kruse free(sp->elts);
571*658eb9e1SMichael Kruse sp->elts = tmp;
572*658eb9e1SMichael Kruse sp->alloc = nsize;
573*658eb9e1SMichael Kruse }
574*658eb9e1SMichael Kruse
575*658eb9e1SMichael Kruse sp->elts[sp->used++] = elt;
576*658eb9e1SMichael Kruse return MP_OK;
577*658eb9e1SMichael Kruse }
578*658eb9e1SMichael Kruse
stack_pop(cstate_t * sp)579*658eb9e1SMichael Kruse static mp_result stack_pop(cstate_t *sp) {
580*658eb9e1SMichael Kruse assert(sp != NULL && sp->elts != NULL);
581*658eb9e1SMichael Kruse
582*658eb9e1SMichael Kruse if (sp->used == 0) return MP_UNDEF;
583*658eb9e1SMichael Kruse
584*658eb9e1SMichael Kruse sp->used -= 1;
585*658eb9e1SMichael Kruse mp_int_clear(sp->elts[sp->used]);
586*658eb9e1SMichael Kruse sp->elts[sp->used] = NULL;
587*658eb9e1SMichael Kruse
588*658eb9e1SMichael Kruse return MP_OK;
589*658eb9e1SMichael Kruse }
590*658eb9e1SMichael Kruse
mem_insert(cstate_t * sp,const char * name,mp_int value)591*658eb9e1SMichael Kruse static mp_result mem_insert(cstate_t *sp, const char *name, mp_int value) {
592*658eb9e1SMichael Kruse int ix;
593*658eb9e1SMichael Kruse
594*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->mused; ++ix) {
595*658eb9e1SMichael Kruse if (strcmp(name, sp->names[ix]) == 0) break;
596*658eb9e1SMichael Kruse }
597*658eb9e1SMichael Kruse
598*658eb9e1SMichael Kruse /* Two cases:
599*658eb9e1SMichael Kruse ix < sp->mused ==> replacing existing entry.
600*658eb9e1SMichael Kruse otherwise ==> adding new entry, may need to grow dictionary.
601*658eb9e1SMichael Kruse */
602*658eb9e1SMichael Kruse if ((mp_size)ix < sp->mused) {
603*658eb9e1SMichael Kruse mp_int_free(sp->mem[ix]); /* fall through to the end */
604*658eb9e1SMichael Kruse } else {
605*658eb9e1SMichael Kruse if (sp->mused >= sp->mslots) {
606*658eb9e1SMichael Kruse mp_size nsize = 2 * sp->mslots;
607*658eb9e1SMichael Kruse mp_int *tz;
608*658eb9e1SMichael Kruse char **tc;
609*658eb9e1SMichael Kruse int jx;
610*658eb9e1SMichael Kruse
611*658eb9e1SMichael Kruse if ((tz = malloc(nsize * sizeof(*(sp->mem)))) == NULL) return MP_MEMORY;
612*658eb9e1SMichael Kruse if ((tc = malloc(nsize * sizeof(*(sp->names)))) == NULL) {
613*658eb9e1SMichael Kruse free(tz);
614*658eb9e1SMichael Kruse return MP_MEMORY;
615*658eb9e1SMichael Kruse }
616*658eb9e1SMichael Kruse
617*658eb9e1SMichael Kruse for (jx = 0; (mp_size)jx < sp->mused; ++jx) {
618*658eb9e1SMichael Kruse tz[jx] = sp->mem[jx];
619*658eb9e1SMichael Kruse tc[jx] = sp->names[jx];
620*658eb9e1SMichael Kruse }
621*658eb9e1SMichael Kruse
622*658eb9e1SMichael Kruse free(sp->mem);
623*658eb9e1SMichael Kruse sp->mem = tz;
624*658eb9e1SMichael Kruse free(sp->names);
625*658eb9e1SMichael Kruse sp->names = tc;
626*658eb9e1SMichael Kruse
627*658eb9e1SMichael Kruse sp->mslots = nsize;
628*658eb9e1SMichael Kruse }
629*658eb9e1SMichael Kruse
630*658eb9e1SMichael Kruse sp->mused += 1;
631*658eb9e1SMichael Kruse sp->names[ix] = malloc(1 + strlen(name));
632*658eb9e1SMichael Kruse strcpy(sp->names[ix], name);
633*658eb9e1SMichael Kruse }
634*658eb9e1SMichael Kruse
635*658eb9e1SMichael Kruse sp->mem[ix] = mp_int_alloc();
636*658eb9e1SMichael Kruse return mp_int_copy(value, sp->mem[ix]);
637*658eb9e1SMichael Kruse }
638*658eb9e1SMichael Kruse
mem_recall(cstate_t * sp,const char * name,mp_int value)639*658eb9e1SMichael Kruse static mp_result mem_recall(cstate_t *sp, const char *name, mp_int value) {
640*658eb9e1SMichael Kruse int ix;
641*658eb9e1SMichael Kruse
642*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->mused; ++ix) {
643*658eb9e1SMichael Kruse if (strcmp(name, sp->names[ix]) == 0) {
644*658eb9e1SMichael Kruse return mp_int_copy(sp->mem[ix], value);
645*658eb9e1SMichael Kruse }
646*658eb9e1SMichael Kruse }
647*658eb9e1SMichael Kruse
648*658eb9e1SMichael Kruse return MP_UNDEF; /* not found */
649*658eb9e1SMichael Kruse }
650*658eb9e1SMichael Kruse
mem_clear(cstate_t * sp)651*658eb9e1SMichael Kruse static mp_result mem_clear(cstate_t *sp) {
652*658eb9e1SMichael Kruse int ix;
653*658eb9e1SMichael Kruse
654*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->mused; ++ix) {
655*658eb9e1SMichael Kruse mp_int_free(sp->mem[ix]);
656*658eb9e1SMichael Kruse free(sp->names[ix]);
657*658eb9e1SMichael Kruse }
658*658eb9e1SMichael Kruse sp->mused = 0;
659*658eb9e1SMichael Kruse
660*658eb9e1SMichael Kruse return MP_OK;
661*658eb9e1SMichael Kruse }
662*658eb9e1SMichael Kruse
cf_abs(cstate_t * sp)663*658eb9e1SMichael Kruse static mp_result cf_abs(cstate_t *sp) {
664*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
665*658eb9e1SMichael Kruse
666*658eb9e1SMichael Kruse return mp_int_abs(a, a);
667*658eb9e1SMichael Kruse }
668*658eb9e1SMichael Kruse
cf_neg(cstate_t * sp)669*658eb9e1SMichael Kruse static mp_result cf_neg(cstate_t *sp) {
670*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
671*658eb9e1SMichael Kruse
672*658eb9e1SMichael Kruse return mp_int_neg(a, a);
673*658eb9e1SMichael Kruse }
674*658eb9e1SMichael Kruse
cf_add(cstate_t * sp)675*658eb9e1SMichael Kruse static mp_result cf_add(cstate_t *sp) {
676*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
677*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
678*658eb9e1SMichael Kruse mp_result res = mp_int_add(a, b, a);
679*658eb9e1SMichael Kruse
680*658eb9e1SMichael Kruse if (res == MP_OK) stack_pop(sp);
681*658eb9e1SMichael Kruse
682*658eb9e1SMichael Kruse return res;
683*658eb9e1SMichael Kruse }
684*658eb9e1SMichael Kruse
cf_sub(cstate_t * sp)685*658eb9e1SMichael Kruse static mp_result cf_sub(cstate_t *sp) {
686*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
687*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
688*658eb9e1SMichael Kruse mp_result res = mp_int_sub(a, b, a);
689*658eb9e1SMichael Kruse
690*658eb9e1SMichael Kruse if (res == MP_OK) stack_pop(sp);
691*658eb9e1SMichael Kruse
692*658eb9e1SMichael Kruse return res;
693*658eb9e1SMichael Kruse }
694*658eb9e1SMichael Kruse
cf_mul(cstate_t * sp)695*658eb9e1SMichael Kruse static mp_result cf_mul(cstate_t *sp) {
696*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
697*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
698*658eb9e1SMichael Kruse mp_result res = mp_int_mul(a, b, a);
699*658eb9e1SMichael Kruse
700*658eb9e1SMichael Kruse if (res == MP_OK) stack_pop(sp);
701*658eb9e1SMichael Kruse
702*658eb9e1SMichael Kruse return res;
703*658eb9e1SMichael Kruse }
704*658eb9e1SMichael Kruse
cf_divmod(cstate_t * sp)705*658eb9e1SMichael Kruse static mp_result cf_divmod(cstate_t *sp) {
706*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
707*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
708*658eb9e1SMichael Kruse
709*658eb9e1SMichael Kruse return mp_int_div(a, b, a, b);
710*658eb9e1SMichael Kruse }
711*658eb9e1SMichael Kruse
cf_div(cstate_t * sp)712*658eb9e1SMichael Kruse static mp_result cf_div(cstate_t *sp) {
713*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
714*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
715*658eb9e1SMichael Kruse mp_result res = mp_int_div(a, b, a, NULL);
716*658eb9e1SMichael Kruse
717*658eb9e1SMichael Kruse if (res == MP_OK) stack_pop(sp);
718*658eb9e1SMichael Kruse
719*658eb9e1SMichael Kruse return res;
720*658eb9e1SMichael Kruse }
721*658eb9e1SMichael Kruse
cf_mod(cstate_t * sp)722*658eb9e1SMichael Kruse static mp_result cf_mod(cstate_t *sp) {
723*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
724*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
725*658eb9e1SMichael Kruse mp_result res = mp_int_mod(a, b, a);
726*658eb9e1SMichael Kruse
727*658eb9e1SMichael Kruse if (res == MP_OK) stack_pop(sp);
728*658eb9e1SMichael Kruse
729*658eb9e1SMichael Kruse return res;
730*658eb9e1SMichael Kruse }
731*658eb9e1SMichael Kruse
cf_expt(cstate_t * sp)732*658eb9e1SMichael Kruse static mp_result cf_expt(cstate_t *sp) {
733*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
734*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
735*658eb9e1SMichael Kruse mp_result res;
736*658eb9e1SMichael Kruse mp_small bval;
737*658eb9e1SMichael Kruse
738*658eb9e1SMichael Kruse if ((res = mp_int_to_int(b, &bval)) != MP_OK) return res;
739*658eb9e1SMichael Kruse
740*658eb9e1SMichael Kruse stack_pop(sp);
741*658eb9e1SMichael Kruse return mp_int_expt(a, bval, a);
742*658eb9e1SMichael Kruse }
743*658eb9e1SMichael Kruse
cf_exptmod(cstate_t * sp)744*658eb9e1SMichael Kruse static mp_result cf_exptmod(cstate_t *sp) {
745*658eb9e1SMichael Kruse mp_int m = sp->elts[sp->used - 1];
746*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 2];
747*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 3];
748*658eb9e1SMichael Kruse mp_result res = mp_int_exptmod(a, b, m, a);
749*658eb9e1SMichael Kruse
750*658eb9e1SMichael Kruse if (res == MP_OK) {
751*658eb9e1SMichael Kruse stack_pop(sp);
752*658eb9e1SMichael Kruse stack_pop(sp);
753*658eb9e1SMichael Kruse }
754*658eb9e1SMichael Kruse
755*658eb9e1SMichael Kruse return res;
756*658eb9e1SMichael Kruse }
757*658eb9e1SMichael Kruse
cf_square(cstate_t * sp)758*658eb9e1SMichael Kruse static mp_result cf_square(cstate_t *sp) {
759*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
760*658eb9e1SMichael Kruse
761*658eb9e1SMichael Kruse return mp_int_sqr(a, a);
762*658eb9e1SMichael Kruse }
763*658eb9e1SMichael Kruse
cf_invmod(cstate_t * sp)764*658eb9e1SMichael Kruse static mp_result cf_invmod(cstate_t *sp) {
765*658eb9e1SMichael Kruse mp_int m = sp->elts[sp->used - 1];
766*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
767*658eb9e1SMichael Kruse mp_result res = mp_int_invmod(a, m, a);
768*658eb9e1SMichael Kruse
769*658eb9e1SMichael Kruse stack_pop(sp);
770*658eb9e1SMichael Kruse
771*658eb9e1SMichael Kruse return res;
772*658eb9e1SMichael Kruse }
773*658eb9e1SMichael Kruse
cf_gcd(cstate_t * sp)774*658eb9e1SMichael Kruse static mp_result cf_gcd(cstate_t *sp) {
775*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
776*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
777*658eb9e1SMichael Kruse mp_result res = mp_int_gcd(a, b, a);
778*658eb9e1SMichael Kruse
779*658eb9e1SMichael Kruse if (res == MP_OK) stack_pop(sp);
780*658eb9e1SMichael Kruse
781*658eb9e1SMichael Kruse return res;
782*658eb9e1SMichael Kruse }
783*658eb9e1SMichael Kruse
cf_xgcd(cstate_t * sp)784*658eb9e1SMichael Kruse static mp_result cf_xgcd(cstate_t *sp) {
785*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
786*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
787*658eb9e1SMichael Kruse mp_int t;
788*658eb9e1SMichael Kruse mp_result res;
789*658eb9e1SMichael Kruse
790*658eb9e1SMichael Kruse if ((t = mp_int_alloc()) == NULL) return MP_MEMORY;
791*658eb9e1SMichael Kruse if ((res = mp_int_egcd(a, b, a, b, t)) != MP_OK) {
792*658eb9e1SMichael Kruse mp_int_free(t);
793*658eb9e1SMichael Kruse return res;
794*658eb9e1SMichael Kruse }
795*658eb9e1SMichael Kruse
796*658eb9e1SMichael Kruse if ((res = stack_push(sp, t)) != MP_OK) mp_int_free(t);
797*658eb9e1SMichael Kruse
798*658eb9e1SMichael Kruse return res;
799*658eb9e1SMichael Kruse }
800*658eb9e1SMichael Kruse
cf_sqrt(cstate_t * sp)801*658eb9e1SMichael Kruse static mp_result cf_sqrt(cstate_t *sp) {
802*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
803*658eb9e1SMichael Kruse
804*658eb9e1SMichael Kruse return mp_int_sqrt(a, a);
805*658eb9e1SMichael Kruse }
806*658eb9e1SMichael Kruse
cf_root(cstate_t * sp)807*658eb9e1SMichael Kruse static mp_result cf_root(cstate_t *sp) {
808*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
809*658eb9e1SMichael Kruse mp_int bp = sp->elts[sp->used - 1];
810*658eb9e1SMichael Kruse mp_small b;
811*658eb9e1SMichael Kruse mp_result res;
812*658eb9e1SMichael Kruse
813*658eb9e1SMichael Kruse if ((res = mp_int_to_int(bp, &b)) != MP_OK) return res;
814*658eb9e1SMichael Kruse
815*658eb9e1SMichael Kruse stack_pop(sp);
816*658eb9e1SMichael Kruse return mp_int_root(a, b, a);
817*658eb9e1SMichael Kruse }
818*658eb9e1SMichael Kruse
cf_cmplt(cstate_t * sp)819*658eb9e1SMichael Kruse static mp_result cf_cmplt(cstate_t *sp) {
820*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
821*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
822*658eb9e1SMichael Kruse mp_result res;
823*658eb9e1SMichael Kruse
824*658eb9e1SMichael Kruse res = mp_int_set_value(a, (mp_int_compare(a, b) < 0));
825*658eb9e1SMichael Kruse stack_pop(sp);
826*658eb9e1SMichael Kruse return res;
827*658eb9e1SMichael Kruse }
828*658eb9e1SMichael Kruse
cf_cmpgt(cstate_t * sp)829*658eb9e1SMichael Kruse static mp_result cf_cmpgt(cstate_t *sp) {
830*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
831*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
832*658eb9e1SMichael Kruse mp_result res;
833*658eb9e1SMichael Kruse
834*658eb9e1SMichael Kruse res = mp_int_set_value(a, (mp_int_compare(a, b) > 0));
835*658eb9e1SMichael Kruse stack_pop(sp);
836*658eb9e1SMichael Kruse return res;
837*658eb9e1SMichael Kruse }
838*658eb9e1SMichael Kruse
cf_cmple(cstate_t * sp)839*658eb9e1SMichael Kruse static mp_result cf_cmple(cstate_t *sp) {
840*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
841*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
842*658eb9e1SMichael Kruse mp_result res;
843*658eb9e1SMichael Kruse
844*658eb9e1SMichael Kruse res = mp_int_set_value(a, (mp_int_compare(a, b) <= 0));
845*658eb9e1SMichael Kruse stack_pop(sp);
846*658eb9e1SMichael Kruse return res;
847*658eb9e1SMichael Kruse }
848*658eb9e1SMichael Kruse
cf_cmpge(cstate_t * sp)849*658eb9e1SMichael Kruse static mp_result cf_cmpge(cstate_t *sp) {
850*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
851*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
852*658eb9e1SMichael Kruse mp_result res;
853*658eb9e1SMichael Kruse
854*658eb9e1SMichael Kruse res = mp_int_set_value(a, (mp_int_compare(a, b) >= 0));
855*658eb9e1SMichael Kruse stack_pop(sp);
856*658eb9e1SMichael Kruse return res;
857*658eb9e1SMichael Kruse }
858*658eb9e1SMichael Kruse
cf_cmpeq(cstate_t * sp)859*658eb9e1SMichael Kruse static mp_result cf_cmpeq(cstate_t *sp) {
860*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
861*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
862*658eb9e1SMichael Kruse mp_result res;
863*658eb9e1SMichael Kruse
864*658eb9e1SMichael Kruse res = mp_int_set_value(a, (mp_int_compare(a, b) == 0));
865*658eb9e1SMichael Kruse stack_pop(sp);
866*658eb9e1SMichael Kruse return res;
867*658eb9e1SMichael Kruse }
868*658eb9e1SMichael Kruse
cf_cmpne(cstate_t * sp)869*658eb9e1SMichael Kruse static mp_result cf_cmpne(cstate_t *sp) {
870*658eb9e1SMichael Kruse mp_int b = sp->elts[sp->used - 1];
871*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 2];
872*658eb9e1SMichael Kruse mp_result res;
873*658eb9e1SMichael Kruse
874*658eb9e1SMichael Kruse res = mp_int_set_value(a, (mp_int_compare(a, b) != 0));
875*658eb9e1SMichael Kruse stack_pop(sp);
876*658eb9e1SMichael Kruse return res;
877*658eb9e1SMichael Kruse }
878*658eb9e1SMichael Kruse
cf_inc(cstate_t * sp)879*658eb9e1SMichael Kruse static mp_result cf_inc(cstate_t *sp) {
880*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
881*658eb9e1SMichael Kruse
882*658eb9e1SMichael Kruse return mp_int_add_value(a, 1, a);
883*658eb9e1SMichael Kruse }
884*658eb9e1SMichael Kruse
cf_dec(cstate_t * sp)885*658eb9e1SMichael Kruse static mp_result cf_dec(cstate_t *sp) {
886*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
887*658eb9e1SMichael Kruse
888*658eb9e1SMichael Kruse return mp_int_sub_value(a, 1, a);
889*658eb9e1SMichael Kruse }
890*658eb9e1SMichael Kruse
cf_fact(cstate_t * sp)891*658eb9e1SMichael Kruse static mp_result cf_fact(cstate_t *sp) {
892*658eb9e1SMichael Kruse mpz_t tmp;
893*658eb9e1SMichael Kruse mp_int x = sp->elts[sp->used - 1];
894*658eb9e1SMichael Kruse mp_result res = MP_OK;
895*658eb9e1SMichael Kruse
896*658eb9e1SMichael Kruse if (mp_int_compare_zero(x) < 0) return MP_UNDEF;
897*658eb9e1SMichael Kruse
898*658eb9e1SMichael Kruse (void)mp_int_init_value(&tmp, 1);
899*658eb9e1SMichael Kruse
900*658eb9e1SMichael Kruse while (mp_int_compare_value(x, 1) > 0) {
901*658eb9e1SMichael Kruse if ((res = mp_int_mul(&tmp, x, &tmp)) != MP_OK) goto CLEANUP;
902*658eb9e1SMichael Kruse if ((res = mp_int_sub_value(x, 1, x)) != MP_OK) goto CLEANUP;
903*658eb9e1SMichael Kruse }
904*658eb9e1SMichael Kruse
905*658eb9e1SMichael Kruse res = mp_int_copy(&tmp, x);
906*658eb9e1SMichael Kruse
907*658eb9e1SMichael Kruse CLEANUP:
908*658eb9e1SMichael Kruse mp_int_clear(&tmp);
909*658eb9e1SMichael Kruse return res;
910*658eb9e1SMichael Kruse }
911*658eb9e1SMichael Kruse
cf_pprint(cstate_t * sp)912*658eb9e1SMichael Kruse static mp_result cf_pprint(cstate_t *sp) {
913*658eb9e1SMichael Kruse print_value(sp->elts[sp->used - 1]);
914*658eb9e1SMichael Kruse stack_pop(sp);
915*658eb9e1SMichael Kruse return MP_OK;
916*658eb9e1SMichael Kruse }
917*658eb9e1SMichael Kruse
cf_print(cstate_t * sp)918*658eb9e1SMichael Kruse static mp_result cf_print(cstate_t *sp) {
919*658eb9e1SMichael Kruse print_value(sp->elts[sp->used - 1]);
920*658eb9e1SMichael Kruse return MP_OK;
921*658eb9e1SMichael Kruse }
922*658eb9e1SMichael Kruse
cf_pstack(cstate_t * sp)923*658eb9e1SMichael Kruse static mp_result cf_pstack(cstate_t *sp) {
924*658eb9e1SMichael Kruse int ix;
925*658eb9e1SMichael Kruse
926*658eb9e1SMichael Kruse if (sp->used == 0) {
927*658eb9e1SMichael Kruse fprintf(g_output_file, "<stack empty>\n");
928*658eb9e1SMichael Kruse } else {
929*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->used; ++ix) {
930*658eb9e1SMichael Kruse fprintf(g_output_file, "%2d: ", ix);
931*658eb9e1SMichael Kruse print_value(sp->elts[sp->used - 1 - ix]);
932*658eb9e1SMichael Kruse }
933*658eb9e1SMichael Kruse }
934*658eb9e1SMichael Kruse
935*658eb9e1SMichael Kruse return MP_OK;
936*658eb9e1SMichael Kruse }
937*658eb9e1SMichael Kruse
cf_clstk(cstate_t * sp)938*658eb9e1SMichael Kruse static mp_result cf_clstk(cstate_t *sp) {
939*658eb9e1SMichael Kruse stack_flush(sp);
940*658eb9e1SMichael Kruse
941*658eb9e1SMichael Kruse return MP_OK;
942*658eb9e1SMichael Kruse }
943*658eb9e1SMichael Kruse
cf_pop(cstate_t * sp)944*658eb9e1SMichael Kruse static mp_result cf_pop(cstate_t *sp) { return stack_pop(sp); }
945*658eb9e1SMichael Kruse
cf_dup(cstate_t * sp)946*658eb9e1SMichael Kruse static mp_result cf_dup(cstate_t *sp) {
947*658eb9e1SMichael Kruse mp_int cp = mp_int_alloc();
948*658eb9e1SMichael Kruse mp_result res;
949*658eb9e1SMichael Kruse
950*658eb9e1SMichael Kruse if (cp == NULL) return MP_MEMORY;
951*658eb9e1SMichael Kruse
952*658eb9e1SMichael Kruse if ((res = mp_int_copy(sp->elts[sp->used - 1], cp)) != MP_OK) {
953*658eb9e1SMichael Kruse mp_int_free(cp);
954*658eb9e1SMichael Kruse return res;
955*658eb9e1SMichael Kruse }
956*658eb9e1SMichael Kruse
957*658eb9e1SMichael Kruse if ((res = stack_push(sp, cp)) != MP_OK) mp_int_free(cp);
958*658eb9e1SMichael Kruse
959*658eb9e1SMichael Kruse return res;
960*658eb9e1SMichael Kruse }
961*658eb9e1SMichael Kruse
cf_copy(cstate_t * sp)962*658eb9e1SMichael Kruse static mp_result cf_copy(cstate_t *sp) {
963*658eb9e1SMichael Kruse mp_int n = sp->elts[sp->used - 1];
964*658eb9e1SMichael Kruse mp_result res;
965*658eb9e1SMichael Kruse mp_small ncopy;
966*658eb9e1SMichael Kruse int ix;
967*658eb9e1SMichael Kruse
968*658eb9e1SMichael Kruse if ((res = mp_int_to_int(n, &ncopy)) != MP_OK) return res;
969*658eb9e1SMichael Kruse
970*658eb9e1SMichael Kruse if (ncopy < 1 || ncopy >= sp->used) return MP_RANGE;
971*658eb9e1SMichael Kruse
972*658eb9e1SMichael Kruse stack_pop(sp);
973*658eb9e1SMichael Kruse
974*658eb9e1SMichael Kruse for (ix = 0; ix < ncopy; ++ix) {
975*658eb9e1SMichael Kruse mp_int old = sp->elts[sp->used - ncopy];
976*658eb9e1SMichael Kruse mp_int new = mp_int_alloc();
977*658eb9e1SMichael Kruse
978*658eb9e1SMichael Kruse if (new == NULL) return MP_MEMORY;
979*658eb9e1SMichael Kruse
980*658eb9e1SMichael Kruse if ((res = mp_int_copy(old, new)) != MP_OK) {
981*658eb9e1SMichael Kruse mp_int_free(new);
982*658eb9e1SMichael Kruse return res;
983*658eb9e1SMichael Kruse }
984*658eb9e1SMichael Kruse if ((res = stack_push(sp, new)) != MP_OK) return res;
985*658eb9e1SMichael Kruse }
986*658eb9e1SMichael Kruse
987*658eb9e1SMichael Kruse return MP_OK;
988*658eb9e1SMichael Kruse }
989*658eb9e1SMichael Kruse
cf_swap(cstate_t * sp)990*658eb9e1SMichael Kruse static mp_result cf_swap(cstate_t *sp) {
991*658eb9e1SMichael Kruse mp_int t = sp->elts[sp->used - 1];
992*658eb9e1SMichael Kruse
993*658eb9e1SMichael Kruse sp->elts[sp->used - 1] = sp->elts[sp->used - 2];
994*658eb9e1SMichael Kruse sp->elts[sp->used - 2] = t;
995*658eb9e1SMichael Kruse
996*658eb9e1SMichael Kruse return MP_OK;
997*658eb9e1SMichael Kruse }
998*658eb9e1SMichael Kruse
cf_rot(cstate_t * sp)999*658eb9e1SMichael Kruse static mp_result cf_rot(cstate_t *sp) {
1000*658eb9e1SMichael Kruse mp_int t = sp->elts[sp->used - 3];
1001*658eb9e1SMichael Kruse
1002*658eb9e1SMichael Kruse sp->elts[sp->used - 3] = sp->elts[sp->used - 2];
1003*658eb9e1SMichael Kruse sp->elts[sp->used - 2] = sp->elts[sp->used - 1];
1004*658eb9e1SMichael Kruse sp->elts[sp->used - 1] = t;
1005*658eb9e1SMichael Kruse
1006*658eb9e1SMichael Kruse return MP_OK;
1007*658eb9e1SMichael Kruse }
1008*658eb9e1SMichael Kruse
cf_pick(cstate_t * sp)1009*658eb9e1SMichael Kruse static mp_result cf_pick(cstate_t *sp) {
1010*658eb9e1SMichael Kruse mp_int n = sp->elts[sp->used - 1];
1011*658eb9e1SMichael Kruse mp_result res;
1012*658eb9e1SMichael Kruse mp_small pos = 0;
1013*658eb9e1SMichael Kruse
1014*658eb9e1SMichael Kruse if ((res = mp_int_to_int(n, &pos)) != MP_OK) return res;
1015*658eb9e1SMichael Kruse
1016*658eb9e1SMichael Kruse if (pos < 0 || pos >= sp->used - 1) return MP_RANGE;
1017*658eb9e1SMichael Kruse
1018*658eb9e1SMichael Kruse return mp_int_copy(sp->elts[sp->used - 2 - pos], n);
1019*658eb9e1SMichael Kruse }
1020*658eb9e1SMichael Kruse
cf_setr(cstate_t * sp)1021*658eb9e1SMichael Kruse static mp_result cf_setr(cstate_t *sp) {
1022*658eb9e1SMichael Kruse mp_int a = sp->elts[sp->used - 1];
1023*658eb9e1SMichael Kruse mp_result res;
1024*658eb9e1SMichael Kruse mp_small rdx = 0;
1025*658eb9e1SMichael Kruse
1026*658eb9e1SMichael Kruse if ((res = mp_int_to_int(a, &rdx)) != MP_OK) return res;
1027*658eb9e1SMichael Kruse
1028*658eb9e1SMichael Kruse if (rdx < MP_MIN_RADIX || rdx > MP_MAX_RADIX) return MP_RANGE;
1029*658eb9e1SMichael Kruse
1030*658eb9e1SMichael Kruse g_output_radix = rdx;
1031*658eb9e1SMichael Kruse stack_pop(sp);
1032*658eb9e1SMichael Kruse return MP_OK;
1033*658eb9e1SMichael Kruse }
1034*658eb9e1SMichael Kruse
cf_setbin(cstate_t * sp)1035*658eb9e1SMichael Kruse static mp_result cf_setbin(cstate_t *sp) {
1036*658eb9e1SMichael Kruse g_output_radix = 0;
1037*658eb9e1SMichael Kruse return MP_OK;
1038*658eb9e1SMichael Kruse }
1039*658eb9e1SMichael Kruse
cf_help(cstate_t * sp)1040*658eb9e1SMichael Kruse static mp_result cf_help(cstate_t *sp) {
1041*658eb9e1SMichael Kruse int ix, maxlen = 10; /* minimum width */
1042*658eb9e1SMichael Kruse
1043*658eb9e1SMichael Kruse for (ix = 0; g_ops[ix].name != NULL; ++ix) {
1044*658eb9e1SMichael Kruse int len = strlen(g_ops[ix].name);
1045*658eb9e1SMichael Kruse
1046*658eb9e1SMichael Kruse if (len > maxlen) maxlen = len;
1047*658eb9e1SMichael Kruse }
1048*658eb9e1SMichael Kruse
1049*658eb9e1SMichael Kruse fprintf(stderr, "Operators understood:\n");
1050*658eb9e1SMichael Kruse for (ix = 0; g_ops[ix].name != NULL; ++ix) {
1051*658eb9e1SMichael Kruse int len = strlen(g_ops[ix].name);
1052*658eb9e1SMichael Kruse
1053*658eb9e1SMichael Kruse fputs(g_ops[ix].name, stderr);
1054*658eb9e1SMichael Kruse while (len++ <= maxlen) fputc(' ', stderr);
1055*658eb9e1SMichael Kruse
1056*658eb9e1SMichael Kruse fprintf(stderr, "%s\n", g_ops[ix].descript);
1057*658eb9e1SMichael Kruse }
1058*658eb9e1SMichael Kruse fputc('\n', stderr);
1059*658eb9e1SMichael Kruse
1060*658eb9e1SMichael Kruse return MP_OK;
1061*658eb9e1SMichael Kruse }
1062*658eb9e1SMichael Kruse
cf_store(cstate_t * sp)1063*658eb9e1SMichael Kruse static mp_result cf_store(cstate_t *sp) {
1064*658eb9e1SMichael Kruse mp_result res;
1065*658eb9e1SMichael Kruse
1066*658eb9e1SMichael Kruse if (next_token(sp->ifp, sp->ibuf, sp->buflen) != t_symbol) return MP_INPUT;
1067*658eb9e1SMichael Kruse
1068*658eb9e1SMichael Kruse if ((res = mem_insert(sp, sp->ibuf, sp->elts[sp->used - 1])) != MP_OK)
1069*658eb9e1SMichael Kruse return res;
1070*658eb9e1SMichael Kruse
1071*658eb9e1SMichael Kruse return stack_pop(sp);
1072*658eb9e1SMichael Kruse }
1073*658eb9e1SMichael Kruse
cf_recall(cstate_t * sp)1074*658eb9e1SMichael Kruse static mp_result cf_recall(cstate_t *sp) {
1075*658eb9e1SMichael Kruse mp_result res;
1076*658eb9e1SMichael Kruse mp_int val;
1077*658eb9e1SMichael Kruse
1078*658eb9e1SMichael Kruse if (next_token(sp->ifp, sp->ibuf, sp->buflen) != t_symbol) return MP_INPUT;
1079*658eb9e1SMichael Kruse
1080*658eb9e1SMichael Kruse if ((val = mp_int_alloc()) == NULL) return MP_MEMORY;
1081*658eb9e1SMichael Kruse if ((res = mem_recall(sp, sp->ibuf, val)) != MP_OK) {
1082*658eb9e1SMichael Kruse mp_int_free(val);
1083*658eb9e1SMichael Kruse return res;
1084*658eb9e1SMichael Kruse }
1085*658eb9e1SMichael Kruse
1086*658eb9e1SMichael Kruse return stack_push(sp, val);
1087*658eb9e1SMichael Kruse }
1088*658eb9e1SMichael Kruse
cf_cmem(cstate_t * sp)1089*658eb9e1SMichael Kruse static mp_result cf_cmem(cstate_t *sp) { return mem_clear(sp); }
1090*658eb9e1SMichael Kruse
cf_pmem(cstate_t * sp)1091*658eb9e1SMichael Kruse static mp_result cf_pmem(cstate_t *sp) {
1092*658eb9e1SMichael Kruse int ix, max_len = 0;
1093*658eb9e1SMichael Kruse
1094*658eb9e1SMichael Kruse if (sp->mused == 0) {
1095*658eb9e1SMichael Kruse fprintf(g_output_file, "<memory empty>\n");
1096*658eb9e1SMichael Kruse return MP_OK;
1097*658eb9e1SMichael Kruse }
1098*658eb9e1SMichael Kruse
1099*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->mused; ++ix) {
1100*658eb9e1SMichael Kruse int ln = strlen(sp->names[ix]);
1101*658eb9e1SMichael Kruse
1102*658eb9e1SMichael Kruse if (ln > max_len) max_len = ln;
1103*658eb9e1SMichael Kruse }
1104*658eb9e1SMichael Kruse
1105*658eb9e1SMichael Kruse max_len += 1; /* allow for a padding space */
1106*658eb9e1SMichael Kruse
1107*658eb9e1SMichael Kruse for (ix = 0; (mp_size)ix < sp->mused; ++ix) {
1108*658eb9e1SMichael Kruse int ln = strlen(sp->names[ix]);
1109*658eb9e1SMichael Kruse
1110*658eb9e1SMichael Kruse fprintf(g_output_file, "%s:", sp->names[ix]);
1111*658eb9e1SMichael Kruse
1112*658eb9e1SMichael Kruse while (ln++ < max_len) fputc(' ', g_output_file);
1113*658eb9e1SMichael Kruse
1114*658eb9e1SMichael Kruse print_value(sp->mem[ix]);
1115*658eb9e1SMichael Kruse }
1116*658eb9e1SMichael Kruse
1117*658eb9e1SMichael Kruse return MP_OK;
1118*658eb9e1SMichael Kruse }
1119*658eb9e1SMichael Kruse
cf_qrecall(cstate_t * sp)1120*658eb9e1SMichael Kruse static mp_result cf_qrecall(cstate_t *sp) {
1121*658eb9e1SMichael Kruse mp_result res;
1122*658eb9e1SMichael Kruse mp_int val;
1123*658eb9e1SMichael Kruse
1124*658eb9e1SMichael Kruse if ((val = mp_int_alloc()) == NULL) return MP_MEMORY;
1125*658eb9e1SMichael Kruse
1126*658eb9e1SMichael Kruse if ((res = mem_recall(sp, sp->ibuf, val)) != MP_OK) {
1127*658eb9e1SMichael Kruse mp_int_free(val);
1128*658eb9e1SMichael Kruse return res;
1129*658eb9e1SMichael Kruse }
1130*658eb9e1SMichael Kruse
1131*658eb9e1SMichael Kruse return stack_push(sp, val);
1132*658eb9e1SMichael Kruse }
1133*658eb9e1SMichael Kruse
1134*658eb9e1SMichael Kruse /* Here there be dragons */
1135