expr.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:26k
- /* mpexpr_evaluate -- shared code for simple expression evaluation
- Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
- This file is part of the GNU MP Library.
- The GNU MP Library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
- The GNU MP Library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include "gmp.h"
- #include "expr-impl.h"
- /* Change this to "#define TRACE(x) x" to get some traces. The trace
- printfs junk up the code a bit, but it's very hard to tell what's going
- on without them. Set MPX_TRACE to a suitable output function for the
- mpz/mpq/mpf being run (if you have the wrong trace function it'll
- probably segv). */
- #define TRACE(x)
- #define MPX_TRACE mpz_trace
- /* A few helper macros copied from gmp-impl.h */
- #define ALLOCATE_FUNC_TYPE(n,type)
- ((type *) (*allocate_func) ((n) * sizeof (type)))
- #define ALLOCATE_FUNC_LIMBS(n) ALLOCATE_FUNC_TYPE (n, mp_limb_t)
- #define REALLOCATE_FUNC_TYPE(p, old_size, new_size, type)
- ((type *) (*reallocate_func)
- (p, (old_size) * sizeof (type), (new_size) * sizeof (type)))
- #define REALLOCATE_FUNC_LIMBS(p, old_size, new_size)
- REALLOCATE_FUNC_TYPE(p, old_size, new_size, mp_limb_t)
- #define FREE_FUNC_TYPE(p,n,type) (*free_func) (p, (n) * sizeof (type))
- #define FREE_FUNC_LIMBS(p,n) FREE_FUNC_TYPE (p, n, mp_limb_t)
- #define ASSERT(x)
- /* All the error strings are just for diagnostic traces. Only the error
- code is actually returned. */
- #define ERROR(str,code)
- {
- TRACE (printf ("%sn", str));
- p->error_code = (code);
- goto done;
- }
- #define REALLOC(ptr, alloc, incr, type)
- do {
- int new_alloc = (alloc) + (incr);
- ptr = REALLOCATE_FUNC_TYPE (ptr, alloc, new_alloc, type);
- (alloc) = new_alloc;
- } while (0)
- /* data stack top element */
- #define SP (p->data_stack + p->data_top)
- /* Make sure there's room for another data element above current top.
- reallocate_func is fetched for when this macro is used in lookahead(). */
- #define DATA_SPACE()
- do {
- if (p->data_top + 1 >= p->data_alloc)
- {
- void *(*reallocate_func) (void *, size_t, size_t);
- mp_get_memory_functions (NULL, &reallocate_func, NULL);
- TRACE (printf ("grow stack from %dn", p->data_alloc));
- REALLOC (p->data_stack, p->data_alloc, 20, union mpX_t);
- }
- ASSERT (p->data_top + 1 <= p->data_inited);
- if (p->data_top + 1 == p->data_inited)
- {
- TRACE (printf ("initialize %dn", p->data_top + 1));
- (*p->mpX_init) (&p->data_stack[p->data_top + 1], p->prec);
- p->data_inited++;
- }
- } while (0)
- #define DATA_PUSH()
- do {
- p->data_top++;
- ASSERT (p->data_top < p->data_alloc);
- ASSERT (p->data_top < p->data_inited);
- } while (0)
- /* the last stack entry is never popped, so top>=0 will be true */
- #define DATA_POP(n)
- do {
- p->data_top -= (n);
- ASSERT (p->data_top >= 0);
- } while (0)
- /* lookahead() parses the next token. Return 1 if successful, with some
- extra data. Return 0 if fail, with reason in p->error_code.
- "prefix" is MPEXPR_TYPE_PREFIX if an operator with that attribute is
- preferred, or 0 if an operator without is preferred. */
- #define TOKEN_EOF -1 /* no extra data */
- #define TOKEN_VALUE -2 /* pushed onto data stack */
- #define TOKEN_OPERATOR -3 /* stored in p->token_op */
- #define TOKEN_FUNCTION -4 /* stored in p->token_op */
- #define TOKEN_NAME(n)
- ((n) == TOKEN_EOF ? "TOKEN_EOF"
- : (n) == TOKEN_VALUE ? "TOKEN_VALUE"
- : (n) == TOKEN_OPERATOR ? "TOKEN_OPERATOR"
- : (n) == TOKEN_VALUE ? "TOKEN_FUNCTION"
- : "UNKNOWN TOKEN")
- /* Functions default to being parsed as whole words, operators to match just
- at the start of the string. The type flags override this. */
- #define WHOLEWORD(op)
- (op->precedence == 0
- ? (! (op->type & MPEXPR_TYPE_OPERATOR))
- : (op->type & MPEXPR_TYPE_WHOLEWORD))
- #define isasciispace(c) (isascii (c) && isspace (c))
- static int
- lookahead (struct mpexpr_parse_t *p, int prefix)
- {
- __gmp_const struct mpexpr_operator_t *op, *op_found;
- size_t oplen, oplen_found, wlen;
- int i;
- /* skip white space */
- while (p->elen > 0 && isasciispace (*p->e))
- p->e++, p->elen--;
- if (p->elen == 0)
- {
- TRACE (printf ("lookahead EOFn"));
- p->token = TOKEN_EOF;
- return 1;
- }
- DATA_SPACE ();
- /* Get extent of whole word. */
- for (wlen = 0; wlen < p->elen; wlen++)
- if (! isasciicsym (p->e[wlen]))
- break;
- TRACE (printf ("lookahead at: "%.*s" length %u, word %un",
- (int) p->elen, p->e, p->elen, wlen));
- op_found = NULL;
- oplen_found = 0;
- for (op = p->table; op->name != NULL; op++)
- {
- if (op->type == MPEXPR_TYPE_NEW_TABLE)
- {
- printf ("newn");
- op = (struct mpexpr_operator_t *) op->name - 1;
- continue;
- }
- oplen = strlen (op->name);
- if (! ((WHOLEWORD (op) ? wlen == oplen : p->elen >= oplen)
- && memcmp (p->e, op->name, oplen) == 0))
- continue;
- /* Shorter matches don't replace longer previous ones. */
- if (op_found && oplen < oplen_found)
- continue;
- /* On a match of equal length to a previous one, the old match isn't
- replaced if it has the preferred prefix, and if it doesn't then
- it's not replaced if the new one also doesn't. */
- if (op_found && oplen == oplen_found
- && ((op_found->type & MPEXPR_TYPE_PREFIX) == prefix
- || (op->type & MPEXPR_TYPE_PREFIX) != prefix))
- continue;
- /* This is now either the first match seen, or a longer than previous
- match, or an equal to previous one but with a preferred prefix. */
- op_found = op;
- oplen_found = oplen;
- }
- if (op_found)
- {
- p->e += oplen_found, p->elen -= oplen_found;
- if (op_found->type == MPEXPR_TYPE_VARIABLE)
- {
- if (p->elen == 0)
- ERROR ("end of string expecting a variable",
- MPEXPR_RESULT_PARSE_ERROR);
- i = p->e[0] - 'a';
- if (i < 0 || i >= MPEXPR_VARIABLES)
- ERROR ("bad variable name", MPEXPR_RESULT_BAD_VARIABLE);
- goto variable;
- }
- if (op_found->precedence == 0)
- {
- TRACE (printf ("lookahead function: %sn", op_found->name));
- p->token = TOKEN_FUNCTION;
- p->token_op = op_found;
- return 1;
- }
- else
- {
- TRACE (printf ("lookahead operator: %sn", op_found->name));
- p->token = TOKEN_OPERATOR;
- p->token_op = op_found;
- return 1;
- }
- }
- oplen = (*p->mpX_number) (SP+1, p->e, p->elen, p->base);
- if (oplen != 0)
- {
- p->e += oplen, p->elen -= oplen;
- p->token = TOKEN_VALUE;
- DATA_PUSH ();
- TRACE (MPX_TRACE ("lookahead number", SP));
- return 1;
- }
- /* Maybe an unprefixed one character variable */
- i = p->e[0] - 'a';
- if (wlen == 1 && i >= 0 && i < MPEXPR_VARIABLES)
- {
- variable:
- p->e++, p->elen--;
- if (p->var[i] == NULL)
- ERROR ("NULL variable", MPEXPR_RESULT_BAD_VARIABLE);
- TRACE (printf ("lookahead variable: var[%d] = ", i);
- MPX_TRACE ("", p->var[i]));
- p->token = TOKEN_VALUE;
- DATA_PUSH ();
- (*p->mpX_set) (SP, p->var[i]);
- return 1;
- }
- ERROR ("no token matched", MPEXPR_RESULT_PARSE_ERROR);
- done:
- return 0;
- }
- /* control stack current top element */
- #define CP (p->control_stack + p->control_top)
- /* make sure there's room for another control element above current top */
- #define CONTROL_SPACE()
- do {
- if (p->control_top + 1 >= p->control_alloc)
- {
- TRACE (printf ("grow control stack from %dn", p->control_alloc));
- REALLOC (p->control_stack, p->control_alloc, 20,
- struct mpexpr_control_t);
- }
- } while (0)
- /* Push an operator on the control stack, claiming currently to have the
- given number of args ready. Local variable "op" is used in case opptr is
- a reference through CP. */
- #define CONTROL_PUSH(opptr,args)
- do {
- __gmp_const struct mpexpr_operator_t *op = opptr;
- struct mpexpr_control_t *cp;
- CONTROL_SPACE ();
- p->control_top++;
- ASSERT (p->control_top < p->control_alloc);
- cp = CP;
- cp->op = op;
- cp->argcount = (args);
- TRACE_CONTROL("control stack push:");
- } while (0)
- /* The special operator_done is never popped, so top>=0 will hold. */
- #define CONTROL_POP()
- do {
- p->control_top--;
- ASSERT (p->control_top >= 0);
- TRACE_CONTROL ("control stack pop:");
- } while (0)
- #define TRACE_CONTROL(str)
- TRACE ({
- int i;
- printf ("%s depth %d:", str, p->control_top);
- for (i = 0; i <= p->control_top; i++)
- printf (" "%s"(%d)",
- p->control_stack[i].op->name,
- p->control_stack[i].argcount);
- printf ("n");
- });
- #define LOOKAHEAD(prefix)
- do {
- if (! lookahead (p, prefix))
- goto done;
- } while (0)
- #define CHECK_UI(n)
- do {
- if (! (*p->mpX_ulong_p) (n))
- ERROR ("operand doesn't fit ulong", MPEXPR_RESULT_NOT_UI);
- } while (0)
- #define CHECK_ARGCOUNT(str,n)
- do {
- if (CP->argcount != (n))
- {
- TRACE (printf ("wrong number of arguments for %s, got %d want %d",
- str, CP->argcount, n));
- ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
- }
- } while (0)
- /* There's two basic states here. In both p->token is the next token.
- "another_expr" is when a whole expression should be parsed. This means a
- literal or variable value possibly followed by an operator, or a function
- or prefix operator followed by a further whole expression.
- "another_operator" is when an expression has been parsed and its value is
- on the top of the data stack (SP) and an optional further postfix or
- infix operator should be parsed.
- In "another_operator" precedences determine whether to push the operator
- onto the control stack, or instead go to "apply_control" to reduce the
- operator currently on top of the control stack.
- When an operator has both a prefix and postfix/infix form, a LOOKAHEAD()
- for "another_expr" will seek the prefix form, a LOOKAHEAD() for
- "another_operator" will seek the postfix/infix form. The grammar is
- simple enough that the next state is known before reading the next token.
- Argument count checking guards against functions consuming the wrong
- number of operands from the data stack. The same checks are applied to
- operators, but will always pass since a UNARY or BINARY will only ever
- parse with the correct operands. */
- int
- mpexpr_evaluate (struct mpexpr_parse_t *p)
- {
- void *(*allocate_func) (size_t);
- void *(*reallocate_func) (void *, size_t, size_t);
- void (*free_func) (void *, size_t);
- mp_get_memory_functions (&allocate_func, &reallocate_func, &free_func);
- TRACE (printf ("mpexpr_evaluate() base %d "%.*s"n",
- p->base, (int) p->elen, p->e));
- /* "done" is a special sentinel at the bottom of the control stack,
- precedence -1 is lower than any normal operator. */
- {
- static __gmp_const struct mpexpr_operator_t operator_done
- = { "DONE", NULL, MPEXPR_TYPE_DONE, -1 };
- p->control_alloc = 20;
- p->control_stack = ALLOCATE_FUNC_TYPE (p->control_alloc,
- struct mpexpr_control_t);
- p->control_top = 0;
- CP->op = &operator_done;
- CP->argcount = 1;
- }
- p->data_inited = 0;
- p->data_alloc = 20;
- p->data_stack = ALLOCATE_FUNC_TYPE (p->data_alloc, union mpX_t);
- p->data_top = -1;
- p->error_code = MPEXPR_RESULT_OK;
- another_expr_lookahead:
- LOOKAHEAD (MPEXPR_TYPE_PREFIX);
- TRACE (printf ("another exprn"));
- /*another_expr:*/
- switch (p->token) {
- case TOKEN_VALUE:
- goto another_operator_lookahead;
- case TOKEN_OPERATOR:
- TRACE (printf ("operator %sn", p->token_op->name));
- if (! (p->token_op->type & MPEXPR_TYPE_PREFIX))
- ERROR ("expected a prefix operator", MPEXPR_RESULT_PARSE_ERROR);
- CONTROL_PUSH (p->token_op, 1);
- goto another_expr_lookahead;
- case TOKEN_FUNCTION:
- CONTROL_PUSH (p->token_op, 1);
- if (p->token_op->type & MPEXPR_TYPE_CONSTANT)
- goto apply_control_lookahead;
- LOOKAHEAD (MPEXPR_TYPE_PREFIX);
- if (! (p->token == TOKEN_OPERATOR
- && p->token_op->type == MPEXPR_TYPE_OPENPAREN))
- ERROR ("expected open paren for function", MPEXPR_RESULT_PARSE_ERROR);
- TRACE (printf ("open paren for function "%s"n", CP->op->name));
- if ((CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) == MPEXPR_TYPE_NARY(0))
- {
- LOOKAHEAD (0);
- if (! (p->token == TOKEN_OPERATOR
- && p->token_op->type == MPEXPR_TYPE_CLOSEPAREN))
- ERROR ("expected close paren for 0ary function",
- MPEXPR_RESULT_PARSE_ERROR);
- goto apply_control_lookahead;
- }
- goto another_expr_lookahead;
- }
- ERROR ("unrecognised start of expression", MPEXPR_RESULT_PARSE_ERROR);
- another_operator_lookahead:
- LOOKAHEAD (0);
- another_operator:
- TRACE (printf ("another operator maybe: %sn", TOKEN_NAME(p->token)));
- switch (p->token) {
- case TOKEN_EOF:
- goto apply_control;
- case TOKEN_OPERATOR:
- /* The next operator is compared to the one on top of the control stack.
- If the next is lower precedence, or the same precedence and not
- right-associative, then reduce using the control stack and look at
- the next operator again later. */
- #define PRECEDENCE_TEST_REDUCE(tprec,cprec,ttype,ctype)
- ((tprec) < (cprec)
- || ((tprec) == (cprec) && ! ((ttype) & MPEXPR_TYPE_RIGHTASSOC)))
- if (PRECEDENCE_TEST_REDUCE (p->token_op->precedence, CP->op->precedence,
- p->token_op->type, CP->op->type))
- {
- TRACE (printf ("defer operator: %s (prec %d vs %d, type 0x%X)n",
- p->token_op->name,
- p->token_op->precedence, CP->op->precedence,
- p->token_op->type));
- goto apply_control;
- }
- /* An argsep is a binary operator, but is never pushed on the control
- stack, it just accumulates an extra argument for a function. */
- if (p->token_op->type == MPEXPR_TYPE_ARGSEP)
- {
- if (CP->op->precedence != 0)
- ERROR ("ARGSEP not in a function call", MPEXPR_RESULT_PARSE_ERROR);
- TRACE (printf ("argsep for function "%s"(%d)n",
- CP->op->name, CP->argcount));
- #define IS_PAIRWISE(type)
- (((type) & (MPEXPR_TYPE_MASK_ARGCOUNT | MPEXPR_TYPE_PAIRWISE))
- == (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_PAIRWISE))
- if (IS_PAIRWISE (CP->op->type) && CP->argcount >= 2)
- {
- TRACE (printf (" will reduce pairwise nown"));
- CP->argcount--;
- CONTROL_PUSH (CP->op, 2);
- goto apply_control;
- }
- CP->argcount++;
- goto another_expr_lookahead;
- }
- switch (p->token_op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
- case MPEXPR_TYPE_NARY(1):
- /* Postfix unary operators can always be applied immediately. The
- easiest way to do this is just push it on the control stack and go
- to the normal control stack reduction code. */
- TRACE (printf ("postfix unary operator: %sn", p->token_op->name));
- if (p->token_op->type & MPEXPR_TYPE_PREFIX)
- ERROR ("prefix unary operator used postfix",
- MPEXPR_RESULT_PARSE_ERROR);
- CONTROL_PUSH (p->token_op, 1);
- goto apply_control_lookahead;
- case MPEXPR_TYPE_NARY(2):
- CONTROL_PUSH (p->token_op, 2);
- goto another_expr_lookahead;
- case MPEXPR_TYPE_NARY(3):
- CONTROL_PUSH (p->token_op, 1);
- goto another_expr_lookahead;
- }
- TRACE (printf ("unrecognised operator "%s" type: 0x%X",
- CP->op->name, CP->op->type));
- ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
- break;
- default:
- TRACE (printf ("expecting an operator, got token %d", p->token));
- ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
- }
- apply_control_lookahead:
- LOOKAHEAD (0);
- apply_control:
- /* Apply the top element CP of the control stack. Data values are SP,
- SP-1, etc. Result is left as stack top SP after popping consumed
- values.
- The use of sp as a duplicate of SP will help compilers that can't
- otherwise recognise the various uses of SP as common subexpressions. */
- TRACE (printf ("apply control: nested %d, "%s" 0x%X, %d argsn",
- p->control_top, CP->op->name, CP->op->type, CP->argcount));
- TRACE (printf ("apply 0x%X-aryn",
- CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT));
- switch (CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
- case MPEXPR_TYPE_NARY(0):
- {
- mpX_ptr sp;
- DATA_SPACE ();
- DATA_PUSH ();
- sp = SP;
- switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
- case 0:
- (* (mpexpr_fun_0ary_t) CP->op->fun) (sp);
- break;
- case MPEXPR_TYPE_RESULT_INT:
- (*p->mpX_set_si) (sp, (long) (* (mpexpr_fun_i_0ary_t) CP->op->fun) ());
- break;
- default:
- ERROR ("unrecognised 0ary argument calling style",
- MPEXPR_RESULT_BAD_TABLE);
- }
- }
- break;
- case MPEXPR_TYPE_NARY(1):
- {
- mpX_ptr sp = SP;
- CHECK_ARGCOUNT ("unary", 1);
- TRACE (MPX_TRACE ("before", sp));
- switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
- case 0:
- /* not a special */
- break;
- case MPEXPR_TYPE_DONE & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special donen"));
- goto done;
- case MPEXPR_TYPE_LOGICAL_NOT & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special logical notn"));
- (*p->mpX_set_si)
- (sp, (long) ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp) == 0));
- goto apply_control_done;
- case MPEXPR_TYPE_CLOSEPAREN & MPEXPR_TYPE_MASK_SPECIAL:
- CONTROL_POP ();
- if (CP->op->type == MPEXPR_TYPE_OPENPAREN)
- {
- TRACE (printf ("close paren matching open parenn"));
- CONTROL_POP ();
- goto another_operator;
- }
- if (CP->op->precedence == 0)
- {
- TRACE (printf ("close paren for functionn"));
- goto apply_control;
- }
- ERROR ("unexpected close paren", MPEXPR_RESULT_PARSE_ERROR);
- default:
- TRACE (printf ("unrecognised special unary operator 0x%X",
- CP->op->type & MPEXPR_TYPE_MASK_SPECIAL));
- ERROR ("", MPEXPR_RESULT_BAD_TABLE);
- }
- switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
- case 0:
- (* (mpexpr_fun_unary_t) CP->op->fun) (sp, sp);
- break;
- case MPEXPR_TYPE_LAST_UI:
- CHECK_UI (sp);
- (* (mpexpr_fun_unary_ui_t) CP->op->fun)
- (sp, (*p->mpX_get_ui) (sp));
- break;
- case MPEXPR_TYPE_RESULT_INT:
- (*p->mpX_set_si)
- (sp, (long) (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp));
- break;
- case MPEXPR_TYPE_RESULT_INT | MPEXPR_TYPE_LAST_UI:
- CHECK_UI (sp);
- (*p->mpX_set_si)
- (sp,
- (long) (* (mpexpr_fun_i_unary_ui_t) CP->op->fun)
- ((*p->mpX_get_ui) (sp)));
- break;
- default:
- ERROR ("unrecognised unary argument calling style",
- MPEXPR_RESULT_BAD_TABLE);
- }
- }
- break;
- case MPEXPR_TYPE_NARY(2):
- {
- mpX_ptr sp;
- /* pairwise functions are allowed to have just one argument */
- if ((CP->op->type & MPEXPR_TYPE_PAIRWISE)
- && CP->op->precedence == 0
- && CP->argcount == 1)
- goto apply_control_done;
- CHECK_ARGCOUNT ("binary", 2);
- DATA_POP (1);
- sp = SP;
- TRACE (MPX_TRACE ("lhs", sp);
- MPX_TRACE ("rhs", sp+1));
- if (CP->op->type & MPEXPR_TYPE_MASK_CMP)
- {
- int type = CP->op->type;
- int cmp = (* (mpexpr_fun_i_binary_t) CP->op->fun)
- (sp, sp+1);
- (*p->mpX_set_si)
- (sp,
- (long)
- (( (cmp < 0) & ((type & MPEXPR_TYPE_MASK_CMP_LT) != 0))
- | ((cmp == 0) & ((type & MPEXPR_TYPE_MASK_CMP_EQ) != 0))
- | ((cmp > 0) & ((type & MPEXPR_TYPE_MASK_CMP_GT) != 0))));
- goto apply_control_done;
- }
- switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
- case 0:
- /* not a special */
- break;
- case MPEXPR_TYPE_QUESTION & MPEXPR_TYPE_MASK_SPECIAL:
- ERROR ("'?' without ':'", MPEXPR_RESULT_PARSE_ERROR);
- case MPEXPR_TYPE_COLON & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special colonn"));
- CONTROL_POP ();
- if (CP->op->type != MPEXPR_TYPE_QUESTION)
- ERROR ("':' without '?'", MPEXPR_RESULT_PARSE_ERROR);
- CP->argcount--;
- DATA_POP (1);
- sp--;
- TRACE (MPX_TRACE ("query", sp);
- MPX_TRACE ("true", sp+1);
- MPX_TRACE ("false", sp+2));
- (*p->mpX_set)
- (sp, (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
- ? sp+1 : sp+2);
- goto apply_control_done;
- case MPEXPR_TYPE_LOGICAL_AND & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special logical andn"));
- (*p->mpX_set_si)
- (sp,
- (long)
- ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
- && (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
- goto apply_control_done;
- case MPEXPR_TYPE_LOGICAL_OR & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special logical andn"));
- (*p->mpX_set_si)
- (sp,
- (long)
- ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
- || (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
- goto apply_control_done;
- case MPEXPR_TYPE_MAX & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special maxn"));
- if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) < 0)
- (*p->mpX_swap) (sp, sp+1);
- goto apply_control_done;
- case MPEXPR_TYPE_MIN & MPEXPR_TYPE_MASK_SPECIAL:
- TRACE (printf ("special minn"));
- if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) > 0)
- (*p->mpX_swap) (sp, sp+1);
- goto apply_control_done;
- default:
- ERROR ("unrecognised special binary operator",
- MPEXPR_RESULT_BAD_TABLE);
- }
- switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
- case 0:
- (* (mpexpr_fun_binary_t) CP->op->fun) (sp, sp, sp+1);
- break;
- case MPEXPR_TYPE_LAST_UI:
- CHECK_UI (sp+1);
- (* (mpexpr_fun_binary_ui_t) CP->op->fun)
- (sp, sp, (*p->mpX_get_ui) (sp+1));
- break;
- case MPEXPR_TYPE_RESULT_INT:
- (*p->mpX_set_si)
- (sp,
- (long) (* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1));
- break;
- case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
- CHECK_UI (sp+1);
- (*p->mpX_set_si)
- (sp,
- (long) (* (mpexpr_fun_i_binary_ui_t) CP->op->fun)
- (sp, (*p->mpX_get_ui) (sp+1)));
- break;
- default:
- ERROR ("unrecognised binary argument calling style",
- MPEXPR_RESULT_BAD_TABLE);
- }
- }
- break;
- case MPEXPR_TYPE_NARY(3):
- {
- mpX_ptr sp;
- CHECK_ARGCOUNT ("ternary", 3);
- DATA_POP (2);
- sp = SP;
- TRACE (MPX_TRACE ("arg1", sp);
- MPX_TRACE ("arg2", sp+1);
- MPX_TRACE ("arg3", sp+1));
- switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
- case 0:
- (* (mpexpr_fun_ternary_t) CP->op->fun) (sp, sp, sp+1, sp+2);
- break;
- case MPEXPR_TYPE_LAST_UI:
- CHECK_UI (sp+2);
- (* (mpexpr_fun_ternary_ui_t) CP->op->fun)
- (sp, sp, sp+1, (*p->mpX_get_ui) (sp+2));
- break;
- case MPEXPR_TYPE_RESULT_INT:
- (*p->mpX_set_si)
- (sp,
- (long) (* (mpexpr_fun_i_ternary_t) CP->op->fun)
- (sp, sp+1, sp+2));
- break;
- case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
- CHECK_UI (sp+2);
- (*p->mpX_set_si)
- (sp,
- (long) (* (mpexpr_fun_i_ternary_ui_t) CP->op->fun)
- (sp, sp+1, (*p->mpX_get_ui) (sp+2)));
- break;
- default:
- ERROR ("unrecognised binary argument calling style",
- MPEXPR_RESULT_BAD_TABLE);
- }
- }
- break;
- default:
- TRACE (printf ("unrecognised operator type: 0x%Xn", CP->op->type));
- ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
- }
- apply_control_done:
- TRACE (MPX_TRACE ("result", SP));
- CONTROL_POP ();
- goto another_operator;
- done:
- if (p->error_code == MPEXPR_RESULT_OK)
- {
- if (p->data_top != 0)
- {
- TRACE (printf ("data stack want top at 0, got %dn", p->data_top));
- p->error_code = MPEXPR_RESULT_PARSE_ERROR;
- }
- else
- (*p->mpX_set_or_swap) (p->res, SP);
- }
- {
- int i;
- for (i = 0; i < p->data_inited; i++)
- {
- TRACE (printf ("clear %dn", i));
- (*p->mpX_clear) (p->data_stack+i);
- }
- }
- FREE_FUNC_TYPE (p->data_stack, p->data_alloc, union mpX_t);
- FREE_FUNC_TYPE (p->control_stack, p->control_alloc, struct mpexpr_control_t);
- return p->error_code;
- }