1
/* mpexpr_evaluate -- shared code for simple expression evaluation */
4
Copyright 2000, 2001 Free Software Foundation, Inc.
6
This file is part of the GNU MP Library.
8
The GNU MP Library is free software; you can redistribute it and/or modify
9
it under the terms of the GNU Lesser General Public License as published by
10
the Free Software Foundation; either version 2.1 of the License, or (at your
11
option) any later version.
13
The GNU MP Library is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16
License for more details.
18
You should have received a copy of the GNU Lesser General Public License
19
along with the GNU MP Library; see the file COPYING.LIB. If not, write to
20
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28
#include "expr-impl.h"
31
/* Change this to "#define TRACE(x) x" to get some traces. The trace
32
printfs junk up the code a bit, but it's very hard to tell what's going
33
on without them. Set MPX_TRACE to a suitable output function for the
34
mpz/mpq/mpf being run (if you have the wrong trace function it'll
38
#define MPX_TRACE mpfr_trace
44
/* Print "name=value\n" to stdout for an mpf_t value. */
46
mpfr_trace (__gmp_const char *name, mpfr_srcptr f)
48
mp_trace_start (name);
49
mpfr_out_str (stdout, mp_trace_base, 0, f, GMP_RNDZ);
55
/* A few helper macros copied from gmp-impl.h */
56
#define __GMP_ALLOCATE_FUNC_TYPE(n,type) \
57
((type *) (*__gmp_allocate_func) ((n) * sizeof (type)))
58
#define __GMP_ALLOCATE_FUNC_LIMBS(n) __GMP_ALLOCATE_FUNC_TYPE (n, mp_limb_t)
59
#define __GMP_REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \
60
((type *) (*__gmp_reallocate_func) \
61
(p, (old_size) * sizeof (type), (new_size) * sizeof (type)))
62
#define __GMP_REALLOCATE_FUNC_LIMBS(p, old_size, new_size) \
63
__GMP_REALLOCATE_FUNC_TYPE(p, old_size, new_size, mp_limb_t)
64
#define __GMP_FREE_FUNC_TYPE(p,n,type) (*__gmp_free_func) (p, (n) * sizeof (type))
65
#define __GMP_FREE_FUNC_LIMBS(p,n) __GMP_FREE_FUNC_TYPE (p, n, mp_limb_t)
70
/* All the error strings are just for diagnostic traces. Only the error
71
code is actually returned. */
72
#define ERROR(str,code) \
74
TRACE (printf ("%s\n", str)); \
75
p->error_code = (code); \
80
#define REALLOC(ptr, alloc, incr, type) \
82
int new_alloc = (alloc) + (incr); \
83
ptr = __GMP_REALLOCATE_FUNC_TYPE (ptr, alloc, new_alloc, type); \
84
(alloc) = new_alloc; \
88
/* data stack top element */
89
#define SP (p->data_stack + p->data_top)
91
/* make sure there's room for another data element above current top */
92
#define DATA_SPACE() \
94
if (p->data_top + 1 >= p->data_alloc) \
96
TRACE (printf ("grow stack from %d\n", p->data_alloc)); \
97
REALLOC (p->data_stack, p->data_alloc, 20, union mpX_t); \
99
ASSERT (p->data_top + 1 <= p->data_inited); \
100
if (p->data_top + 1 == p->data_inited) \
102
TRACE (printf ("initialize %d\n", p->data_top + 1)); \
103
(*p->mpX_init) (&p->data_stack[p->data_top + 1], p->prec); \
108
#define DATA_PUSH() \
111
ASSERT (p->data_top < p->data_alloc); \
112
ASSERT (p->data_top < p->data_inited); \
115
/* the last stack entry is never popped, so top>=0 will be true */
116
#define DATA_POP(n) \
118
p->data_top -= (n); \
119
ASSERT (p->data_top >= 0); \
123
/* lookahead() parses the next token. Return 1 if successful, with some
124
extra data. Return 0 if fail, with reason in p->error_code.
126
"prefix" is MPEXPR_TYPE_PREFIX if an operator with that attribute is
127
preferred, or 0 if an operator without is preferred. */
129
#define TOKEN_EOF -1 /* no extra data */
130
#define TOKEN_VALUE -2 /* pushed onto data stack */
131
#define TOKEN_OPERATOR -3 /* stored in p->token_op */
132
#define TOKEN_FUNCTION -4 /* stored in p->token_op */
134
#define TOKEN_NAME(n) \
135
((n) == TOKEN_EOF ? "TOKEN_EOF" \
136
: (n) == TOKEN_VALUE ? "TOKEN_VALUE" \
137
: (n) == TOKEN_OPERATOR ? "TOKEN_OPERATOR" \
138
: (n) == TOKEN_VALUE ? "TOKEN_FUNCTION" \
141
/* Functions default to being parsed as whole words, operators to match just
142
at the start of the string. The type flags override this. */
143
#define WHOLEWORD(op) \
144
(op->precedence == 0 \
145
? (! (op->type & MPEXPR_TYPE_OPERATOR)) \
146
: (op->type & MPEXPR_TYPE_WHOLEWORD))
148
#define isasciispace(c) (isascii (c) && isspace (c))
151
lookahead (struct mpexpr_parse_t *p, int prefix)
153
__gmp_const struct mpexpr_operator_t *op, *op_found;
154
size_t oplen, oplen_found, wlen;
157
/* skip white space */
158
while (p->elen > 0 && isasciispace (*p->e))
163
TRACE (printf ("lookahead EOF\n"));
164
p->token = TOKEN_EOF;
170
/* Get extent of whole word. */
171
for (wlen = 0; wlen < p->elen; wlen++)
172
if (! isasciicsym (p->e[wlen]))
175
TRACE (printf ("lookahead at: \"%.*s\" length %u, word %u\n",
176
(int) p->elen, p->e, p->elen, wlen));
180
for (op = p->table; op->name != NULL; op++)
182
if (op->type == MPEXPR_TYPE_NEW_TABLE)
185
op = (struct mpexpr_operator_t *) op->name - 1;
189
oplen = strlen (op->name);
190
if (! ((WHOLEWORD (op) ? wlen == oplen : p->elen >= oplen)
191
&& memcmp (p->e, op->name, oplen) == 0))
194
/* Shorter matches don't replace longer previous ones. */
195
if (op_found && oplen < oplen_found)
198
/* On a match of equal length to a previous one, the old match isn't
199
replaced if it has the preferred prefix, and if it doesn't then
200
it's not replaced if the new one also doesn't. */
201
if (op_found && oplen == oplen_found
202
&& ((op_found->type & MPEXPR_TYPE_PREFIX) == prefix
203
|| (op->type & MPEXPR_TYPE_PREFIX) != prefix))
206
/* This is now either the first match seen, or a longer than previous
207
match, or an equal to previous one but with a preferred prefix. */
214
p->e += oplen_found, p->elen -= oplen_found;
216
if (op_found->type == MPEXPR_TYPE_VARIABLE)
219
ERROR ("end of string expecting a variable",
220
MPEXPR_RESULT_PARSE_ERROR);
222
if (i < 0 || i >= MPEXPR_VARIABLES)
223
ERROR ("bad variable name", MPEXPR_RESULT_BAD_VARIABLE);
227
if (op_found->precedence == 0)
229
TRACE (printf ("lookahead function: %s\n", op_found->name));
230
p->token = TOKEN_FUNCTION;
231
p->token_op = op_found;
236
TRACE (printf ("lookahead operator: %s\n", op_found->name));
237
p->token = TOKEN_OPERATOR;
238
p->token_op = op_found;
243
oplen = (*p->mpX_number) (SP+1, p->e, p->elen, p->base);
246
p->e += oplen, p->elen -= oplen;
247
p->token = TOKEN_VALUE;
249
TRACE (MPX_TRACE ("lookahead number", SP));
253
/* Maybe an unprefixed one character variable */
255
if (wlen == 1 && i >= 0 && i < MPEXPR_VARIABLES)
259
if (p->var[i] == NULL)
260
ERROR ("NULL variable", MPEXPR_RESULT_BAD_VARIABLE);
261
TRACE (printf ("lookahead variable: var[%d] = ", i);
262
MPX_TRACE ("", p->var[i]));
263
p->token = TOKEN_VALUE;
265
(*p->mpX_set) (SP, p->var[i]);
269
ERROR ("no token matched", MPEXPR_RESULT_PARSE_ERROR);
276
/* control stack current top element */
277
#define CP (p->control_stack + p->control_top)
279
/* make sure there's room for another control element above current top */
280
#define CONTROL_SPACE() \
282
if (p->control_top + 1 >= p->control_alloc) \
284
TRACE (printf ("grow control stack from %d\n", p->control_alloc)); \
285
REALLOC (p->control_stack, p->control_alloc, 20, \
286
struct mpexpr_control_t); \
290
/* Push an operator on the control stack, claiming currently to have the
291
given number of args ready. Local variable "op" is used in case opptr is
292
a reference through CP. */
293
#define CONTROL_PUSH(opptr,args) \
295
__gmp_const struct mpexpr_operator_t *op = opptr; \
296
struct mpexpr_control_t *cp; \
299
ASSERT (p->control_top < p->control_alloc); \
302
cp->argcount = (args); \
303
TRACE_CONTROL("control stack push:"); \
306
/* The special operator_done is never popped, so top>=0 will hold. */
307
#define CONTROL_POP() \
310
ASSERT (p->control_top >= 0); \
311
TRACE_CONTROL ("control stack pop:"); \
314
#define TRACE_CONTROL(str) \
317
printf ("%s depth %d:", str, p->control_top); \
318
for (i = 0; i <= p->control_top; i++) \
319
printf (" \"%s\"(%d)", \
320
p->control_stack[i].op->name, \
321
p->control_stack[i].argcount); \
326
#define LOOKAHEAD(prefix) \
328
if (! lookahead (p, prefix)) \
332
#define CHECK_UI(n) \
334
if (! (*p->mpX_ulong_p) (n)) \
335
ERROR ("operand doesn't fit ulong", MPEXPR_RESULT_NOT_UI); \
338
#define CHECK_ARGCOUNT(str,n) \
340
if (CP->argcount != (n)) \
342
TRACE (printf ("wrong number of arguments for %s, got %d want %d", \
343
str, CP->argcount, n)); \
344
ERROR ("", MPEXPR_RESULT_PARSE_ERROR); \
349
/* There's two basic states here. In both p->token is the next token.
351
"another_expr" is when a whole expression should be parsed. This means a
352
literal or variable value possibly followed by an operator, or a function
353
or prefix operator followed by a further whole expression.
355
"another_operator" is when an expression has been parsed and its value is
356
on the top of the data stack (SP) and an optional further postfix or
357
infix operator should be parsed.
359
In "another_operator" precedences determine whether to push the operator
360
onto the control stack, or instead go to "apply_control" to reduce the
361
operator currently on top of the control stack.
363
When an operator has both a prefix and postfix/infix form, a LOOKAHEAD()
364
for "another_expr" will seek the prefix form, a LOOKAHEAD() for
365
"another_operator" will seek the postfix/infix form. The grammar is
366
simple enough that the next state is known before reading the next token.
368
Argument count checking guards against functions consuming the wrong
369
number of operands from the data stack. The same checks are applied to
370
operators, but will always pass since a UNARY or BINARY will only ever
371
parse with the correct operands. */
374
mpexpr_evaluate (struct mpexpr_parse_t *p)
376
TRACE (printf ("mpexpr_evaluate() base %d \"%.*s\"\n",
377
p->base, (int) p->elen, p->e));
379
/* "done" is a special sentinel at the bottom of the control stack,
380
precedence -1 is lower than any normal operator. */
382
static __gmp_const struct mpexpr_operator_t operator_done
383
= { "DONE", NULL, MPEXPR_TYPE_DONE, -1 };
385
p->control_alloc = 20;
386
p->control_stack = __GMP_ALLOCATE_FUNC_TYPE (p->control_alloc,
387
struct mpexpr_control_t);
389
CP->op = &operator_done;
395
p->data_stack = __GMP_ALLOCATE_FUNC_TYPE (p->data_alloc, union mpX_t);
398
p->error_code = MPEXPR_RESULT_OK;
401
another_expr_lookahead:
402
LOOKAHEAD (MPEXPR_TYPE_PREFIX);
403
TRACE (printf ("another expr\n"));
408
goto another_operator_lookahead;
411
TRACE (printf ("operator %s\n", p->token_op->name));
412
if (! (p->token_op->type & MPEXPR_TYPE_PREFIX))
413
ERROR ("expected a prefix operator", MPEXPR_RESULT_PARSE_ERROR);
415
CONTROL_PUSH (p->token_op, 1);
416
goto another_expr_lookahead;
419
CONTROL_PUSH (p->token_op, 1);
421
if (p->token_op->type & MPEXPR_TYPE_CONSTANT)
422
goto apply_control_lookahead;
424
LOOKAHEAD (MPEXPR_TYPE_PREFIX);
425
if (! (p->token == TOKEN_OPERATOR
426
&& p->token_op->type == MPEXPR_TYPE_OPENPAREN))
427
ERROR ("expected open paren for function", MPEXPR_RESULT_PARSE_ERROR);
429
TRACE (printf ("open paren for function \"%s\"\n", CP->op->name));
431
if ((CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) == MPEXPR_TYPE_NARY(0))
434
if (! (p->token == TOKEN_OPERATOR
435
&& p->token_op->type == MPEXPR_TYPE_CLOSEPAREN))
436
ERROR ("expected close paren for 0ary function",
437
MPEXPR_RESULT_PARSE_ERROR);
438
goto apply_control_lookahead;
441
goto another_expr_lookahead;
443
ERROR ("unrecognised start of expression", MPEXPR_RESULT_PARSE_ERROR);
446
another_operator_lookahead:
449
TRACE (printf ("another operator maybe: %s\n", TOKEN_NAME(p->token)));
456
/* The next operator is compared to the one on top of the control stack.
457
If the next is lower precedence, or the same precedence and not
458
right-associative, then reduce using the control stack and look at
459
the next operator again later. */
461
#define PRECEDENCE_TEST_REDUCE(tprec,cprec,ttype,ctype) \
463
|| ((tprec) == (cprec) && ! ((ttype) & MPEXPR_TYPE_RIGHTASSOC)))
465
if (PRECEDENCE_TEST_REDUCE (p->token_op->precedence, CP->op->precedence,
466
p->token_op->type, CP->op->type))
468
TRACE (printf ("defer operator: %s (prec %d vs %d, type 0x%X)\n",
470
p->token_op->precedence, CP->op->precedence,
475
/* An argsep is a binary operator, but is never pushed on the control
476
stack, it just accumulates an extra argument for a function. */
477
if (p->token_op->type == MPEXPR_TYPE_ARGSEP)
479
if (CP->op->precedence != 0)
480
ERROR ("ARGSEP not in a function call", MPEXPR_RESULT_PARSE_ERROR);
482
TRACE (printf ("argsep for function \"%s\"(%d)\n",
483
CP->op->name, CP->argcount));
485
#define IS_PAIRWISE(type) \
486
(((type) & (MPEXPR_TYPE_MASK_ARGCOUNT | MPEXPR_TYPE_PAIRWISE)) \
487
== (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_PAIRWISE))
489
if (IS_PAIRWISE (CP->op->type) && CP->argcount >= 2)
491
TRACE (printf (" will reduce pairwise now\n"));
493
CONTROL_PUSH (CP->op, 2);
498
goto another_expr_lookahead;
501
switch (p->token_op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
502
case MPEXPR_TYPE_NARY(1):
503
/* Postfix unary operators can always be applied immediately. The
504
easiest way to do this is just push it on the control stack and go
505
to the normal control stack reduction code. */
507
TRACE (printf ("postfix unary operator: %s\n", p->token_op->name));
508
if (p->token_op->type & MPEXPR_TYPE_PREFIX)
509
ERROR ("prefix unary operator used postfix",
510
MPEXPR_RESULT_PARSE_ERROR);
511
CONTROL_PUSH (p->token_op, 1);
512
goto apply_control_lookahead;
514
case MPEXPR_TYPE_NARY(2):
515
CONTROL_PUSH (p->token_op, 2);
516
goto another_expr_lookahead;
518
case MPEXPR_TYPE_NARY(3):
519
CONTROL_PUSH (p->token_op, 1);
520
goto another_expr_lookahead;
523
TRACE (printf ("unrecognised operator \"%s\" type: 0x%X",
524
CP->op->name, CP->op->type));
525
ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
529
TRACE (printf ("expecting an operator, got token %d", p->token));
530
ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
534
apply_control_lookahead:
537
/* Apply the top element CP of the control stack. Data values are SP,
538
SP-1, etc. Result is left as stack top SP after popping consumed
541
The use of sp as a duplicate of SP will help compilers that can't
542
otherwise recognise the various uses of SP as common subexpressions. */
544
TRACE (printf ("apply control: nested %d, \"%s\" 0x%X, %d args\n",
545
p->control_top, CP->op->name, CP->op->type, CP->argcount));
547
TRACE (printf ("apply 0x%X-ary\n",
548
CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT));
549
switch (CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
550
case MPEXPR_TYPE_NARY(0):
556
switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
558
(* (mpexpr_fun_0ary_t) CP->op->fun) (sp);
560
case MPEXPR_TYPE_RESULT_INT:
561
(*p->mpX_set_si) (sp, (long) (* (mpexpr_fun_i_0ary_t) CP->op->fun) ());
564
ERROR ("unrecognised 0ary argument calling style",
565
MPEXPR_RESULT_BAD_TABLE);
570
case MPEXPR_TYPE_NARY(1):
573
CHECK_ARGCOUNT ("unary", 1);
574
TRACE (MPX_TRACE ("before", sp));
576
switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
581
case MPEXPR_TYPE_DONE & MPEXPR_TYPE_MASK_SPECIAL:
582
TRACE (printf ("special done\n"));
585
case MPEXPR_TYPE_LOGICAL_NOT & MPEXPR_TYPE_MASK_SPECIAL:
586
TRACE (printf ("special logical not\n"));
588
(sp, (long) ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp) == 0));
589
goto apply_control_done;
591
case MPEXPR_TYPE_CLOSEPAREN & MPEXPR_TYPE_MASK_SPECIAL:
593
if (CP->op->type == MPEXPR_TYPE_OPENPAREN)
595
TRACE (printf ("close paren matching open paren\n"));
597
goto another_operator;
599
if (CP->op->precedence == 0)
601
TRACE (printf ("close paren for function\n"));
604
ERROR ("unexpected close paren", MPEXPR_RESULT_PARSE_ERROR);
607
TRACE (printf ("unrecognised special unary operator 0x%X",
608
CP->op->type & MPEXPR_TYPE_MASK_SPECIAL));
609
ERROR ("", MPEXPR_RESULT_BAD_TABLE);
612
switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
614
(* (mpexpr_fun_unary_t) CP->op->fun) (sp, sp);
616
case MPEXPR_TYPE_LAST_UI:
618
(* (mpexpr_fun_unary_ui_t) CP->op->fun)
619
(sp, (*p->mpX_get_ui) (sp));
621
case MPEXPR_TYPE_RESULT_INT:
623
(sp, (long) (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp));
625
case MPEXPR_TYPE_RESULT_INT | MPEXPR_TYPE_LAST_UI:
629
(long) (* (mpexpr_fun_i_unary_ui_t) CP->op->fun)
630
((*p->mpX_get_ui) (sp)));
633
ERROR ("unrecognised unary argument calling style",
634
MPEXPR_RESULT_BAD_TABLE);
639
case MPEXPR_TYPE_NARY(2):
643
/* pairwise functions are allowed to have just one argument */
644
if ((CP->op->type & MPEXPR_TYPE_PAIRWISE)
645
&& CP->op->precedence == 0
646
&& CP->argcount == 1)
647
goto apply_control_done;
649
CHECK_ARGCOUNT ("binary", 2);
652
TRACE (MPX_TRACE ("lhs", sp);
653
MPX_TRACE ("rhs", sp+1));
655
if (CP->op->type & MPEXPR_TYPE_MASK_CMP)
657
int type = CP->op->type;
658
int cmp = (* (mpexpr_fun_i_binary_t) CP->op->fun)
663
(( (cmp < 0) & ((type & MPEXPR_TYPE_MASK_CMP_LT) != 0))
664
| ((cmp == 0) & ((type & MPEXPR_TYPE_MASK_CMP_EQ) != 0))
665
| ((cmp > 0) & ((type & MPEXPR_TYPE_MASK_CMP_GT) != 0))));
666
goto apply_control_done;
669
switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
674
case MPEXPR_TYPE_QUESTION & MPEXPR_TYPE_MASK_SPECIAL:
675
ERROR ("'?' without ':'", MPEXPR_RESULT_PARSE_ERROR);
677
case MPEXPR_TYPE_COLON & MPEXPR_TYPE_MASK_SPECIAL:
678
TRACE (printf ("special colon\n"));
680
if (CP->op->type != MPEXPR_TYPE_QUESTION)
681
ERROR ("':' without '?'", MPEXPR_RESULT_PARSE_ERROR);
686
TRACE (MPX_TRACE ("query", sp);
687
MPX_TRACE ("true", sp+1);
688
MPX_TRACE ("false", sp+2));
690
(sp, (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
692
goto apply_control_done;
694
case MPEXPR_TYPE_LOGICAL_AND & MPEXPR_TYPE_MASK_SPECIAL:
695
TRACE (printf ("special logical and\n"));
699
((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
700
&& (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
701
goto apply_control_done;
703
case MPEXPR_TYPE_LOGICAL_OR & MPEXPR_TYPE_MASK_SPECIAL:
704
TRACE (printf ("special logical and\n"));
708
((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
709
|| (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
710
goto apply_control_done;
712
case MPEXPR_TYPE_MAX & MPEXPR_TYPE_MASK_SPECIAL:
713
TRACE (printf ("special max\n"));
714
if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) < 0)
715
(*p->mpX_swap) (sp, sp+1);
716
goto apply_control_done;
717
case MPEXPR_TYPE_MIN & MPEXPR_TYPE_MASK_SPECIAL:
718
TRACE (printf ("special min\n"));
719
if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) > 0)
720
(*p->mpX_swap) (sp, sp+1);
721
goto apply_control_done;
724
ERROR ("unrecognised special binary operator",
725
MPEXPR_RESULT_BAD_TABLE);
728
switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
730
(* (mpexpr_fun_binary_t) CP->op->fun) (sp, sp, sp+1);
732
case MPEXPR_TYPE_LAST_UI:
734
(* (mpexpr_fun_binary_ui_t) CP->op->fun)
735
(sp, sp, (*p->mpX_get_ui) (sp+1));
737
case MPEXPR_TYPE_RESULT_INT:
740
(long) (* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1));
742
case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
746
(long) (* (mpexpr_fun_i_binary_ui_t) CP->op->fun)
747
(sp, (*p->mpX_get_ui) (sp+1)));
750
ERROR ("unrecognised binary argument calling style",
751
MPEXPR_RESULT_BAD_TABLE);
756
case MPEXPR_TYPE_NARY(3):
760
CHECK_ARGCOUNT ("ternary", 3);
763
TRACE (MPX_TRACE ("arg1", sp);
764
MPX_TRACE ("arg2", sp+1);
765
MPX_TRACE ("arg3", sp+1));
767
switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
769
(* (mpexpr_fun_ternary_t) CP->op->fun) (sp, sp, sp+1, sp+2);
771
case MPEXPR_TYPE_LAST_UI:
773
(* (mpexpr_fun_ternary_ui_t) CP->op->fun)
774
(sp, sp, sp+1, (*p->mpX_get_ui) (sp+2));
776
case MPEXPR_TYPE_RESULT_INT:
779
(long) (* (mpexpr_fun_i_ternary_t) CP->op->fun)
782
case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
786
(long) (* (mpexpr_fun_i_ternary_ui_t) CP->op->fun)
787
(sp, sp+1, (*p->mpX_get_ui) (sp+2)));
790
ERROR ("unrecognised binary argument calling style",
791
MPEXPR_RESULT_BAD_TABLE);
797
TRACE (printf ("unrecognised operator type: 0x%X\n", CP->op->type));
798
ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
802
TRACE (MPX_TRACE ("result", SP));
804
goto another_operator;
807
if (p->error_code == MPEXPR_RESULT_OK)
809
if (p->data_top != 0)
811
TRACE (printf ("data stack want top at 0, got %d\n", p->data_top));
812
p->error_code = MPEXPR_RESULT_PARSE_ERROR;
815
(*p->mpX_set_or_swap) (p->res, SP);
820
for (i = 0; i < p->data_inited; i++)
822
TRACE (printf ("clear %d\n", i));
823
(*p->mpX_clear) (p->data_stack+i);
827
__GMP_FREE_FUNC_TYPE (p->data_stack, p->data_alloc, union mpX_t);
828
__GMP_FREE_FUNC_TYPE (p->control_stack, p->control_alloc,
829
struct mpexpr_control_t);
831
return p->error_code;