14a1767b4Smrg /* mpexpr_evaluate -- shared code for simple expression evaluation
24a1767b4Smrg
3*f81b1c5bSmrg Copyright 2000-2002, 2004 Free Software Foundation, Inc.
44a1767b4Smrg
54a1767b4Smrg This file is part of the GNU MP Library.
64a1767b4Smrg
74a1767b4Smrg The GNU MP Library is free software; you can redistribute it and/or modify
8*f81b1c5bSmrg it under the terms of either:
9*f81b1c5bSmrg
10*f81b1c5bSmrg * the GNU Lesser General Public License as published by the Free
11*f81b1c5bSmrg Software Foundation; either version 3 of the License, or (at your
124a1767b4Smrg option) any later version.
134a1767b4Smrg
14*f81b1c5bSmrg or
15*f81b1c5bSmrg
16*f81b1c5bSmrg * the GNU General Public License as published by the Free Software
17*f81b1c5bSmrg Foundation; either version 2 of the License, or (at your option) any
18*f81b1c5bSmrg later version.
19*f81b1c5bSmrg
20*f81b1c5bSmrg or both in parallel, as here.
21*f81b1c5bSmrg
224a1767b4Smrg The GNU MP Library is distributed in the hope that it will be useful, but
234a1767b4Smrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24*f81b1c5bSmrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25*f81b1c5bSmrg for more details.
264a1767b4Smrg
27*f81b1c5bSmrg You should have received copies of the GNU General Public License and the
28*f81b1c5bSmrg GNU Lesser General Public License along with the GNU MP Library. If not,
29*f81b1c5bSmrg see https://www.gnu.org/licenses/. */
304a1767b4Smrg
314a1767b4Smrg #include <ctype.h>
324a1767b4Smrg #include <stdio.h>
334a1767b4Smrg #include <string.h>
344a1767b4Smrg
354a1767b4Smrg #include "gmp.h"
364a1767b4Smrg #include "expr-impl.h"
374a1767b4Smrg
384a1767b4Smrg
394a1767b4Smrg /* Change this to "#define TRACE(x) x" to get some traces. The trace
404a1767b4Smrg printfs junk up the code a bit, but it's very hard to tell what's going
414a1767b4Smrg on without them. Set MPX_TRACE to a suitable output function for the
424a1767b4Smrg mpz/mpq/mpf being run (if you have the wrong trace function it'll
434a1767b4Smrg probably segv). */
444a1767b4Smrg
454a1767b4Smrg #define TRACE(x)
464a1767b4Smrg #define MPX_TRACE mpz_trace
474a1767b4Smrg
484a1767b4Smrg
494a1767b4Smrg /* A few helper macros copied from gmp-impl.h */
504a1767b4Smrg #define ALLOCATE_FUNC_TYPE(n,type) \
514a1767b4Smrg ((type *) (*allocate_func) ((n) * sizeof (type)))
524a1767b4Smrg #define ALLOCATE_FUNC_LIMBS(n) ALLOCATE_FUNC_TYPE (n, mp_limb_t)
534a1767b4Smrg #define REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \
544a1767b4Smrg ((type *) (*reallocate_func) \
554a1767b4Smrg (p, (old_size) * sizeof (type), (new_size) * sizeof (type)))
564a1767b4Smrg #define REALLOCATE_FUNC_LIMBS(p, old_size, new_size) \
574a1767b4Smrg REALLOCATE_FUNC_TYPE(p, old_size, new_size, mp_limb_t)
584a1767b4Smrg #define FREE_FUNC_TYPE(p,n,type) (*free_func) (p, (n) * sizeof (type))
594a1767b4Smrg #define FREE_FUNC_LIMBS(p,n) FREE_FUNC_TYPE (p, n, mp_limb_t)
604a1767b4Smrg #define ASSERT(x)
614a1767b4Smrg
624a1767b4Smrg
634a1767b4Smrg
644a1767b4Smrg /* All the error strings are just for diagnostic traces. Only the error
654a1767b4Smrg code is actually returned. */
664a1767b4Smrg #define ERROR(str,code) \
674a1767b4Smrg { \
684a1767b4Smrg TRACE (printf ("%s\n", str)); \
694a1767b4Smrg p->error_code = (code); \
704a1767b4Smrg goto done; \
714a1767b4Smrg }
724a1767b4Smrg
734a1767b4Smrg
744a1767b4Smrg #define REALLOC(ptr, alloc, incr, type) \
754a1767b4Smrg do { \
764a1767b4Smrg int new_alloc = (alloc) + (incr); \
774a1767b4Smrg ptr = REALLOCATE_FUNC_TYPE (ptr, alloc, new_alloc, type); \
784a1767b4Smrg (alloc) = new_alloc; \
794a1767b4Smrg } while (0)
804a1767b4Smrg
814a1767b4Smrg
824a1767b4Smrg /* data stack top element */
834a1767b4Smrg #define SP (p->data_stack + p->data_top)
844a1767b4Smrg
854a1767b4Smrg /* Make sure there's room for another data element above current top.
864a1767b4Smrg reallocate_func is fetched for when this macro is used in lookahead(). */
874a1767b4Smrg #define DATA_SPACE() \
884a1767b4Smrg do { \
894a1767b4Smrg if (p->data_top + 1 >= p->data_alloc) \
904a1767b4Smrg { \
914a1767b4Smrg void *(*reallocate_func) (void *, size_t, size_t); \
924a1767b4Smrg mp_get_memory_functions (NULL, &reallocate_func, NULL); \
934a1767b4Smrg TRACE (printf ("grow stack from %d\n", p->data_alloc)); \
944a1767b4Smrg REALLOC (p->data_stack, p->data_alloc, 20, union mpX_t); \
954a1767b4Smrg } \
964a1767b4Smrg ASSERT (p->data_top + 1 <= p->data_inited); \
974a1767b4Smrg if (p->data_top + 1 == p->data_inited) \
984a1767b4Smrg { \
994a1767b4Smrg TRACE (printf ("initialize %d\n", p->data_top + 1)); \
1004a1767b4Smrg (*p->mpX_init) (&p->data_stack[p->data_top + 1], p->prec); \
1014a1767b4Smrg p->data_inited++; \
1024a1767b4Smrg } \
1034a1767b4Smrg } while (0)
1044a1767b4Smrg
1054a1767b4Smrg #define DATA_PUSH() \
1064a1767b4Smrg do { \
1074a1767b4Smrg p->data_top++; \
1084a1767b4Smrg ASSERT (p->data_top < p->data_alloc); \
1094a1767b4Smrg ASSERT (p->data_top < p->data_inited); \
1104a1767b4Smrg } while (0)
1114a1767b4Smrg
1124a1767b4Smrg /* the last stack entry is never popped, so top>=0 will be true */
1134a1767b4Smrg #define DATA_POP(n) \
1144a1767b4Smrg do { \
1154a1767b4Smrg p->data_top -= (n); \
1164a1767b4Smrg ASSERT (p->data_top >= 0); \
1174a1767b4Smrg } while (0)
1184a1767b4Smrg
1194a1767b4Smrg
1204a1767b4Smrg /* lookahead() parses the next token. Return 1 if successful, with some
1214a1767b4Smrg extra data. Return 0 if fail, with reason in p->error_code.
1224a1767b4Smrg
1234a1767b4Smrg "prefix" is MPEXPR_TYPE_PREFIX if an operator with that attribute is
1244a1767b4Smrg preferred, or 0 if an operator without is preferred. */
1254a1767b4Smrg
1264a1767b4Smrg #define TOKEN_EOF -1 /* no extra data */
1274a1767b4Smrg #define TOKEN_VALUE -2 /* pushed onto data stack */
1284a1767b4Smrg #define TOKEN_OPERATOR -3 /* stored in p->token_op */
1294a1767b4Smrg #define TOKEN_FUNCTION -4 /* stored in p->token_op */
1304a1767b4Smrg
1314a1767b4Smrg #define TOKEN_NAME(n) \
1324a1767b4Smrg ((n) == TOKEN_EOF ? "TOKEN_EOF" \
1334a1767b4Smrg : (n) == TOKEN_VALUE ? "TOKEN_VALUE" \
1344a1767b4Smrg : (n) == TOKEN_OPERATOR ? "TOKEN_OPERATOR" \
1354a1767b4Smrg : (n) == TOKEN_VALUE ? "TOKEN_FUNCTION" \
1364a1767b4Smrg : "UNKNOWN TOKEN")
1374a1767b4Smrg
1384a1767b4Smrg /* Functions default to being parsed as whole words, operators to match just
1394a1767b4Smrg at the start of the string. The type flags override this. */
1404a1767b4Smrg #define WHOLEWORD(op) \
1414a1767b4Smrg (op->precedence == 0 \
1424a1767b4Smrg ? (! (op->type & MPEXPR_TYPE_OPERATOR)) \
1434a1767b4Smrg : (op->type & MPEXPR_TYPE_WHOLEWORD))
1444a1767b4Smrg
1454a1767b4Smrg #define isasciispace(c) (isascii (c) && isspace (c))
1464a1767b4Smrg
1474a1767b4Smrg static int
lookahead(struct mpexpr_parse_t * p,int prefix)1484a1767b4Smrg lookahead (struct mpexpr_parse_t *p, int prefix)
1494a1767b4Smrg {
150d25e02daSmrg const struct mpexpr_operator_t *op, *op_found;
1514a1767b4Smrg size_t oplen, oplen_found, wlen;
1524a1767b4Smrg int i;
1534a1767b4Smrg
1544a1767b4Smrg /* skip white space */
1554a1767b4Smrg while (p->elen > 0 && isasciispace (*p->e))
1564a1767b4Smrg p->e++, p->elen--;
1574a1767b4Smrg
1584a1767b4Smrg if (p->elen == 0)
1594a1767b4Smrg {
1604a1767b4Smrg TRACE (printf ("lookahead EOF\n"));
1614a1767b4Smrg p->token = TOKEN_EOF;
1624a1767b4Smrg return 1;
1634a1767b4Smrg }
1644a1767b4Smrg
1654a1767b4Smrg DATA_SPACE ();
1664a1767b4Smrg
1674a1767b4Smrg /* Get extent of whole word. */
1684a1767b4Smrg for (wlen = 0; wlen < p->elen; wlen++)
1694a1767b4Smrg if (! isasciicsym (p->e[wlen]))
1704a1767b4Smrg break;
1714a1767b4Smrg
1724a1767b4Smrg TRACE (printf ("lookahead at: \"%.*s\" length %u, word %u\n",
1734a1767b4Smrg (int) p->elen, p->e, p->elen, wlen));
1744a1767b4Smrg
1754a1767b4Smrg op_found = NULL;
1764a1767b4Smrg oplen_found = 0;
1774a1767b4Smrg for (op = p->table; op->name != NULL; op++)
1784a1767b4Smrg {
1794a1767b4Smrg if (op->type == MPEXPR_TYPE_NEW_TABLE)
1804a1767b4Smrg {
1814a1767b4Smrg printf ("new\n");
1824a1767b4Smrg op = (struct mpexpr_operator_t *) op->name - 1;
1834a1767b4Smrg continue;
1844a1767b4Smrg }
1854a1767b4Smrg
1864a1767b4Smrg oplen = strlen (op->name);
1874a1767b4Smrg if (! ((WHOLEWORD (op) ? wlen == oplen : p->elen >= oplen)
1884a1767b4Smrg && memcmp (p->e, op->name, oplen) == 0))
1894a1767b4Smrg continue;
1904a1767b4Smrg
1914a1767b4Smrg /* Shorter matches don't replace longer previous ones. */
1924a1767b4Smrg if (op_found && oplen < oplen_found)
1934a1767b4Smrg continue;
1944a1767b4Smrg
1954a1767b4Smrg /* On a match of equal length to a previous one, the old match isn't
1964a1767b4Smrg replaced if it has the preferred prefix, and if it doesn't then
1974a1767b4Smrg it's not replaced if the new one also doesn't. */
1984a1767b4Smrg if (op_found && oplen == oplen_found
1994a1767b4Smrg && ((op_found->type & MPEXPR_TYPE_PREFIX) == prefix
2004a1767b4Smrg || (op->type & MPEXPR_TYPE_PREFIX) != prefix))
2014a1767b4Smrg continue;
2024a1767b4Smrg
2034a1767b4Smrg /* This is now either the first match seen, or a longer than previous
2044a1767b4Smrg match, or an equal to previous one but with a preferred prefix. */
2054a1767b4Smrg op_found = op;
2064a1767b4Smrg oplen_found = oplen;
2074a1767b4Smrg }
2084a1767b4Smrg
2094a1767b4Smrg if (op_found)
2104a1767b4Smrg {
2114a1767b4Smrg p->e += oplen_found, p->elen -= oplen_found;
2124a1767b4Smrg
2134a1767b4Smrg if (op_found->type == MPEXPR_TYPE_VARIABLE)
2144a1767b4Smrg {
2154a1767b4Smrg if (p->elen == 0)
2164a1767b4Smrg ERROR ("end of string expecting a variable",
2174a1767b4Smrg MPEXPR_RESULT_PARSE_ERROR);
2184a1767b4Smrg i = p->e[0] - 'a';
2194a1767b4Smrg if (i < 0 || i >= MPEXPR_VARIABLES)
2204a1767b4Smrg ERROR ("bad variable name", MPEXPR_RESULT_BAD_VARIABLE);
2214a1767b4Smrg goto variable;
2224a1767b4Smrg }
2234a1767b4Smrg
2244a1767b4Smrg if (op_found->precedence == 0)
2254a1767b4Smrg {
2264a1767b4Smrg TRACE (printf ("lookahead function: %s\n", op_found->name));
2274a1767b4Smrg p->token = TOKEN_FUNCTION;
2284a1767b4Smrg p->token_op = op_found;
2294a1767b4Smrg return 1;
2304a1767b4Smrg }
2314a1767b4Smrg else
2324a1767b4Smrg {
2334a1767b4Smrg TRACE (printf ("lookahead operator: %s\n", op_found->name));
2344a1767b4Smrg p->token = TOKEN_OPERATOR;
2354a1767b4Smrg p->token_op = op_found;
2364a1767b4Smrg return 1;
2374a1767b4Smrg }
2384a1767b4Smrg }
2394a1767b4Smrg
2404a1767b4Smrg oplen = (*p->mpX_number) (SP+1, p->e, p->elen, p->base);
2414a1767b4Smrg if (oplen != 0)
2424a1767b4Smrg {
2434a1767b4Smrg p->e += oplen, p->elen -= oplen;
2444a1767b4Smrg p->token = TOKEN_VALUE;
2454a1767b4Smrg DATA_PUSH ();
2464a1767b4Smrg TRACE (MPX_TRACE ("lookahead number", SP));
2474a1767b4Smrg return 1;
2484a1767b4Smrg }
2494a1767b4Smrg
2504a1767b4Smrg /* Maybe an unprefixed one character variable */
2514a1767b4Smrg i = p->e[0] - 'a';
2524a1767b4Smrg if (wlen == 1 && i >= 0 && i < MPEXPR_VARIABLES)
2534a1767b4Smrg {
2544a1767b4Smrg variable:
2554a1767b4Smrg p->e++, p->elen--;
2564a1767b4Smrg if (p->var[i] == NULL)
2574a1767b4Smrg ERROR ("NULL variable", MPEXPR_RESULT_BAD_VARIABLE);
2584a1767b4Smrg TRACE (printf ("lookahead variable: var[%d] = ", i);
2594a1767b4Smrg MPX_TRACE ("", p->var[i]));
2604a1767b4Smrg p->token = TOKEN_VALUE;
2614a1767b4Smrg DATA_PUSH ();
2624a1767b4Smrg (*p->mpX_set) (SP, p->var[i]);
2634a1767b4Smrg return 1;
2644a1767b4Smrg }
2654a1767b4Smrg
2664a1767b4Smrg ERROR ("no token matched", MPEXPR_RESULT_PARSE_ERROR);
2674a1767b4Smrg
2684a1767b4Smrg done:
2694a1767b4Smrg return 0;
2704a1767b4Smrg }
2714a1767b4Smrg
2724a1767b4Smrg
2734a1767b4Smrg /* control stack current top element */
2744a1767b4Smrg #define CP (p->control_stack + p->control_top)
2754a1767b4Smrg
2764a1767b4Smrg /* make sure there's room for another control element above current top */
2774a1767b4Smrg #define CONTROL_SPACE() \
2784a1767b4Smrg do { \
2794a1767b4Smrg if (p->control_top + 1 >= p->control_alloc) \
2804a1767b4Smrg { \
2814a1767b4Smrg TRACE (printf ("grow control stack from %d\n", p->control_alloc)); \
2824a1767b4Smrg REALLOC (p->control_stack, p->control_alloc, 20, \
2834a1767b4Smrg struct mpexpr_control_t); \
2844a1767b4Smrg } \
2854a1767b4Smrg } while (0)
2864a1767b4Smrg
2874a1767b4Smrg /* Push an operator on the control stack, claiming currently to have the
2884a1767b4Smrg given number of args ready. Local variable "op" is used in case opptr is
2894a1767b4Smrg a reference through CP. */
2904a1767b4Smrg #define CONTROL_PUSH(opptr,args) \
2914a1767b4Smrg do { \
292d25e02daSmrg const struct mpexpr_operator_t *op = opptr; \
2934a1767b4Smrg struct mpexpr_control_t *cp; \
2944a1767b4Smrg CONTROL_SPACE (); \
2954a1767b4Smrg p->control_top++; \
2964a1767b4Smrg ASSERT (p->control_top < p->control_alloc); \
2974a1767b4Smrg cp = CP; \
2984a1767b4Smrg cp->op = op; \
2994a1767b4Smrg cp->argcount = (args); \
3004a1767b4Smrg TRACE_CONTROL("control stack push:"); \
3014a1767b4Smrg } while (0)
3024a1767b4Smrg
3034a1767b4Smrg /* The special operator_done is never popped, so top>=0 will hold. */
3044a1767b4Smrg #define CONTROL_POP() \
3054a1767b4Smrg do { \
3064a1767b4Smrg p->control_top--; \
3074a1767b4Smrg ASSERT (p->control_top >= 0); \
3084a1767b4Smrg TRACE_CONTROL ("control stack pop:"); \
3094a1767b4Smrg } while (0)
3104a1767b4Smrg
3114a1767b4Smrg #define TRACE_CONTROL(str) \
3124a1767b4Smrg TRACE ({ \
3134a1767b4Smrg int i; \
3144a1767b4Smrg printf ("%s depth %d:", str, p->control_top); \
3154a1767b4Smrg for (i = 0; i <= p->control_top; i++) \
3164a1767b4Smrg printf (" \"%s\"(%d)", \
3174a1767b4Smrg p->control_stack[i].op->name, \
3184a1767b4Smrg p->control_stack[i].argcount); \
3194a1767b4Smrg printf ("\n"); \
3204a1767b4Smrg });
3214a1767b4Smrg
3224a1767b4Smrg
3234a1767b4Smrg #define LOOKAHEAD(prefix) \
3244a1767b4Smrg do { \
3254a1767b4Smrg if (! lookahead (p, prefix)) \
3264a1767b4Smrg goto done; \
3274a1767b4Smrg } while (0)
3284a1767b4Smrg
3294a1767b4Smrg #define CHECK_UI(n) \
3304a1767b4Smrg do { \
3314a1767b4Smrg if (! (*p->mpX_ulong_p) (n)) \
3324a1767b4Smrg ERROR ("operand doesn't fit ulong", MPEXPR_RESULT_NOT_UI); \
3334a1767b4Smrg } while (0)
3344a1767b4Smrg
3354a1767b4Smrg #define CHECK_ARGCOUNT(str,n) \
3364a1767b4Smrg do { \
3374a1767b4Smrg if (CP->argcount != (n)) \
3384a1767b4Smrg { \
3394a1767b4Smrg TRACE (printf ("wrong number of arguments for %s, got %d want %d", \
3404a1767b4Smrg str, CP->argcount, n)); \
3414a1767b4Smrg ERROR ("", MPEXPR_RESULT_PARSE_ERROR); \
3424a1767b4Smrg } \
3434a1767b4Smrg } while (0)
3444a1767b4Smrg
3454a1767b4Smrg
3464a1767b4Smrg /* There's two basic states here. In both p->token is the next token.
3474a1767b4Smrg
3484a1767b4Smrg "another_expr" is when a whole expression should be parsed. This means a
3494a1767b4Smrg literal or variable value possibly followed by an operator, or a function
3504a1767b4Smrg or prefix operator followed by a further whole expression.
3514a1767b4Smrg
3524a1767b4Smrg "another_operator" is when an expression has been parsed and its value is
3534a1767b4Smrg on the top of the data stack (SP) and an optional further postfix or
3544a1767b4Smrg infix operator should be parsed.
3554a1767b4Smrg
3564a1767b4Smrg In "another_operator" precedences determine whether to push the operator
3574a1767b4Smrg onto the control stack, or instead go to "apply_control" to reduce the
3584a1767b4Smrg operator currently on top of the control stack.
3594a1767b4Smrg
3604a1767b4Smrg When an operator has both a prefix and postfix/infix form, a LOOKAHEAD()
3614a1767b4Smrg for "another_expr" will seek the prefix form, a LOOKAHEAD() for
3624a1767b4Smrg "another_operator" will seek the postfix/infix form. The grammar is
3634a1767b4Smrg simple enough that the next state is known before reading the next token.
3644a1767b4Smrg
3654a1767b4Smrg Argument count checking guards against functions consuming the wrong
3664a1767b4Smrg number of operands from the data stack. The same checks are applied to
3674a1767b4Smrg operators, but will always pass since a UNARY or BINARY will only ever
3684a1767b4Smrg parse with the correct operands. */
3694a1767b4Smrg
3704a1767b4Smrg int
mpexpr_evaluate(struct mpexpr_parse_t * p)3714a1767b4Smrg mpexpr_evaluate (struct mpexpr_parse_t *p)
3724a1767b4Smrg {
3734a1767b4Smrg void *(*allocate_func) (size_t);
3744a1767b4Smrg void *(*reallocate_func) (void *, size_t, size_t);
3754a1767b4Smrg void (*free_func) (void *, size_t);
3764a1767b4Smrg
3774a1767b4Smrg mp_get_memory_functions (&allocate_func, &reallocate_func, &free_func);
3784a1767b4Smrg
3794a1767b4Smrg TRACE (printf ("mpexpr_evaluate() base %d \"%.*s\"\n",
3804a1767b4Smrg p->base, (int) p->elen, p->e));
3814a1767b4Smrg
3824a1767b4Smrg /* "done" is a special sentinel at the bottom of the control stack,
3834a1767b4Smrg precedence -1 is lower than any normal operator. */
3844a1767b4Smrg {
385d25e02daSmrg static const struct mpexpr_operator_t operator_done
3864a1767b4Smrg = { "DONE", NULL, MPEXPR_TYPE_DONE, -1 };
3874a1767b4Smrg
3884a1767b4Smrg p->control_alloc = 20;
3894a1767b4Smrg p->control_stack = ALLOCATE_FUNC_TYPE (p->control_alloc,
3904a1767b4Smrg struct mpexpr_control_t);
3914a1767b4Smrg p->control_top = 0;
3924a1767b4Smrg CP->op = &operator_done;
3934a1767b4Smrg CP->argcount = 1;
3944a1767b4Smrg }
3954a1767b4Smrg
3964a1767b4Smrg p->data_inited = 0;
3974a1767b4Smrg p->data_alloc = 20;
3984a1767b4Smrg p->data_stack = ALLOCATE_FUNC_TYPE (p->data_alloc, union mpX_t);
3994a1767b4Smrg p->data_top = -1;
4004a1767b4Smrg
4014a1767b4Smrg p->error_code = MPEXPR_RESULT_OK;
4024a1767b4Smrg
4034a1767b4Smrg
4044a1767b4Smrg another_expr_lookahead:
4054a1767b4Smrg LOOKAHEAD (MPEXPR_TYPE_PREFIX);
4064a1767b4Smrg TRACE (printf ("another expr\n"));
4074a1767b4Smrg
4084a1767b4Smrg /*another_expr:*/
4094a1767b4Smrg switch (p->token) {
4104a1767b4Smrg case TOKEN_VALUE:
4114a1767b4Smrg goto another_operator_lookahead;
4124a1767b4Smrg
4134a1767b4Smrg case TOKEN_OPERATOR:
4144a1767b4Smrg TRACE (printf ("operator %s\n", p->token_op->name));
4154a1767b4Smrg if (! (p->token_op->type & MPEXPR_TYPE_PREFIX))
4164a1767b4Smrg ERROR ("expected a prefix operator", MPEXPR_RESULT_PARSE_ERROR);
4174a1767b4Smrg
4184a1767b4Smrg CONTROL_PUSH (p->token_op, 1);
4194a1767b4Smrg goto another_expr_lookahead;
4204a1767b4Smrg
4214a1767b4Smrg case TOKEN_FUNCTION:
4224a1767b4Smrg CONTROL_PUSH (p->token_op, 1);
4234a1767b4Smrg
4244a1767b4Smrg if (p->token_op->type & MPEXPR_TYPE_CONSTANT)
4254a1767b4Smrg goto apply_control_lookahead;
4264a1767b4Smrg
4274a1767b4Smrg LOOKAHEAD (MPEXPR_TYPE_PREFIX);
4284a1767b4Smrg if (! (p->token == TOKEN_OPERATOR
4294a1767b4Smrg && p->token_op->type == MPEXPR_TYPE_OPENPAREN))
4304a1767b4Smrg ERROR ("expected open paren for function", MPEXPR_RESULT_PARSE_ERROR);
4314a1767b4Smrg
4324a1767b4Smrg TRACE (printf ("open paren for function \"%s\"\n", CP->op->name));
4334a1767b4Smrg
4344a1767b4Smrg if ((CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) == MPEXPR_TYPE_NARY(0))
4354a1767b4Smrg {
4364a1767b4Smrg LOOKAHEAD (0);
4374a1767b4Smrg if (! (p->token == TOKEN_OPERATOR
4384a1767b4Smrg && p->token_op->type == MPEXPR_TYPE_CLOSEPAREN))
4394a1767b4Smrg ERROR ("expected close paren for 0ary function",
4404a1767b4Smrg MPEXPR_RESULT_PARSE_ERROR);
4414a1767b4Smrg goto apply_control_lookahead;
4424a1767b4Smrg }
4434a1767b4Smrg
4444a1767b4Smrg goto another_expr_lookahead;
4454a1767b4Smrg }
4464a1767b4Smrg ERROR ("unrecognised start of expression", MPEXPR_RESULT_PARSE_ERROR);
4474a1767b4Smrg
4484a1767b4Smrg
4494a1767b4Smrg another_operator_lookahead:
4504a1767b4Smrg LOOKAHEAD (0);
4514a1767b4Smrg another_operator:
4524a1767b4Smrg TRACE (printf ("another operator maybe: %s\n", TOKEN_NAME(p->token)));
4534a1767b4Smrg
4544a1767b4Smrg switch (p->token) {
4554a1767b4Smrg case TOKEN_EOF:
4564a1767b4Smrg goto apply_control;
4574a1767b4Smrg
4584a1767b4Smrg case TOKEN_OPERATOR:
4594a1767b4Smrg /* The next operator is compared to the one on top of the control stack.
4604a1767b4Smrg If the next is lower precedence, or the same precedence and not
4614a1767b4Smrg right-associative, then reduce using the control stack and look at
4624a1767b4Smrg the next operator again later. */
4634a1767b4Smrg
4644a1767b4Smrg #define PRECEDENCE_TEST_REDUCE(tprec,cprec,ttype,ctype) \
4654a1767b4Smrg ((tprec) < (cprec) \
4664a1767b4Smrg || ((tprec) == (cprec) && ! ((ttype) & MPEXPR_TYPE_RIGHTASSOC)))
4674a1767b4Smrg
4684a1767b4Smrg if (PRECEDENCE_TEST_REDUCE (p->token_op->precedence, CP->op->precedence,
4694a1767b4Smrg p->token_op->type, CP->op->type))
4704a1767b4Smrg {
4714a1767b4Smrg TRACE (printf ("defer operator: %s (prec %d vs %d, type 0x%X)\n",
4724a1767b4Smrg p->token_op->name,
4734a1767b4Smrg p->token_op->precedence, CP->op->precedence,
4744a1767b4Smrg p->token_op->type));
4754a1767b4Smrg goto apply_control;
4764a1767b4Smrg }
4774a1767b4Smrg
4784a1767b4Smrg /* An argsep is a binary operator, but is never pushed on the control
4794a1767b4Smrg stack, it just accumulates an extra argument for a function. */
4804a1767b4Smrg if (p->token_op->type == MPEXPR_TYPE_ARGSEP)
4814a1767b4Smrg {
4824a1767b4Smrg if (CP->op->precedence != 0)
4834a1767b4Smrg ERROR ("ARGSEP not in a function call", MPEXPR_RESULT_PARSE_ERROR);
4844a1767b4Smrg
4854a1767b4Smrg TRACE (printf ("argsep for function \"%s\"(%d)\n",
4864a1767b4Smrg CP->op->name, CP->argcount));
4874a1767b4Smrg
4884a1767b4Smrg #define IS_PAIRWISE(type) \
4894a1767b4Smrg (((type) & (MPEXPR_TYPE_MASK_ARGCOUNT | MPEXPR_TYPE_PAIRWISE)) \
4904a1767b4Smrg == (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_PAIRWISE))
4914a1767b4Smrg
4924a1767b4Smrg if (IS_PAIRWISE (CP->op->type) && CP->argcount >= 2)
4934a1767b4Smrg {
4944a1767b4Smrg TRACE (printf (" will reduce pairwise now\n"));
4954a1767b4Smrg CP->argcount--;
4964a1767b4Smrg CONTROL_PUSH (CP->op, 2);
4974a1767b4Smrg goto apply_control;
4984a1767b4Smrg }
4994a1767b4Smrg
5004a1767b4Smrg CP->argcount++;
5014a1767b4Smrg goto another_expr_lookahead;
5024a1767b4Smrg }
5034a1767b4Smrg
5044a1767b4Smrg switch (p->token_op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
5054a1767b4Smrg case MPEXPR_TYPE_NARY(1):
5064a1767b4Smrg /* Postfix unary operators can always be applied immediately. The
5074a1767b4Smrg easiest way to do this is just push it on the control stack and go
5084a1767b4Smrg to the normal control stack reduction code. */
5094a1767b4Smrg
5104a1767b4Smrg TRACE (printf ("postfix unary operator: %s\n", p->token_op->name));
5114a1767b4Smrg if (p->token_op->type & MPEXPR_TYPE_PREFIX)
5124a1767b4Smrg ERROR ("prefix unary operator used postfix",
5134a1767b4Smrg MPEXPR_RESULT_PARSE_ERROR);
5144a1767b4Smrg CONTROL_PUSH (p->token_op, 1);
5154a1767b4Smrg goto apply_control_lookahead;
5164a1767b4Smrg
5174a1767b4Smrg case MPEXPR_TYPE_NARY(2):
5184a1767b4Smrg CONTROL_PUSH (p->token_op, 2);
5194a1767b4Smrg goto another_expr_lookahead;
5204a1767b4Smrg
5214a1767b4Smrg case MPEXPR_TYPE_NARY(3):
5224a1767b4Smrg CONTROL_PUSH (p->token_op, 1);
5234a1767b4Smrg goto another_expr_lookahead;
5244a1767b4Smrg }
5254a1767b4Smrg
5264a1767b4Smrg TRACE (printf ("unrecognised operator \"%s\" type: 0x%X",
5274a1767b4Smrg CP->op->name, CP->op->type));
5284a1767b4Smrg ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
5294a1767b4Smrg break;
5304a1767b4Smrg
5314a1767b4Smrg default:
5324a1767b4Smrg TRACE (printf ("expecting an operator, got token %d", p->token));
5334a1767b4Smrg ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
5344a1767b4Smrg }
5354a1767b4Smrg
5364a1767b4Smrg
5374a1767b4Smrg apply_control_lookahead:
5384a1767b4Smrg LOOKAHEAD (0);
5394a1767b4Smrg apply_control:
5404a1767b4Smrg /* Apply the top element CP of the control stack. Data values are SP,
5414a1767b4Smrg SP-1, etc. Result is left as stack top SP after popping consumed
5424a1767b4Smrg values.
5434a1767b4Smrg
5444a1767b4Smrg The use of sp as a duplicate of SP will help compilers that can't
5454a1767b4Smrg otherwise recognise the various uses of SP as common subexpressions. */
5464a1767b4Smrg
5474a1767b4Smrg TRACE (printf ("apply control: nested %d, \"%s\" 0x%X, %d args\n",
5484a1767b4Smrg p->control_top, CP->op->name, CP->op->type, CP->argcount));
5494a1767b4Smrg
5504a1767b4Smrg TRACE (printf ("apply 0x%X-ary\n",
5514a1767b4Smrg CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT));
5524a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
5534a1767b4Smrg case MPEXPR_TYPE_NARY(0):
5544a1767b4Smrg {
5554a1767b4Smrg mpX_ptr sp;
5564a1767b4Smrg DATA_SPACE ();
5574a1767b4Smrg DATA_PUSH ();
5584a1767b4Smrg sp = SP;
5594a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
5604a1767b4Smrg case 0:
5614a1767b4Smrg (* (mpexpr_fun_0ary_t) CP->op->fun) (sp);
5624a1767b4Smrg break;
5634a1767b4Smrg case MPEXPR_TYPE_RESULT_INT:
5644a1767b4Smrg (*p->mpX_set_si) (sp, (long) (* (mpexpr_fun_i_0ary_t) CP->op->fun) ());
5654a1767b4Smrg break;
5664a1767b4Smrg default:
5674a1767b4Smrg ERROR ("unrecognised 0ary argument calling style",
5684a1767b4Smrg MPEXPR_RESULT_BAD_TABLE);
5694a1767b4Smrg }
5704a1767b4Smrg }
5714a1767b4Smrg break;
5724a1767b4Smrg
5734a1767b4Smrg case MPEXPR_TYPE_NARY(1):
5744a1767b4Smrg {
5754a1767b4Smrg mpX_ptr sp = SP;
5764a1767b4Smrg CHECK_ARGCOUNT ("unary", 1);
5774a1767b4Smrg TRACE (MPX_TRACE ("before", sp));
5784a1767b4Smrg
5794a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
5804a1767b4Smrg case 0:
5814a1767b4Smrg /* not a special */
5824a1767b4Smrg break;
5834a1767b4Smrg
5844a1767b4Smrg case MPEXPR_TYPE_DONE & MPEXPR_TYPE_MASK_SPECIAL:
5854a1767b4Smrg TRACE (printf ("special done\n"));
5864a1767b4Smrg goto done;
5874a1767b4Smrg
5884a1767b4Smrg case MPEXPR_TYPE_LOGICAL_NOT & MPEXPR_TYPE_MASK_SPECIAL:
5894a1767b4Smrg TRACE (printf ("special logical not\n"));
5904a1767b4Smrg (*p->mpX_set_si)
5914a1767b4Smrg (sp, (long) ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp) == 0));
5924a1767b4Smrg goto apply_control_done;
5934a1767b4Smrg
5944a1767b4Smrg case MPEXPR_TYPE_CLOSEPAREN & MPEXPR_TYPE_MASK_SPECIAL:
5954a1767b4Smrg CONTROL_POP ();
5964a1767b4Smrg if (CP->op->type == MPEXPR_TYPE_OPENPAREN)
5974a1767b4Smrg {
5984a1767b4Smrg TRACE (printf ("close paren matching open paren\n"));
5994a1767b4Smrg CONTROL_POP ();
6004a1767b4Smrg goto another_operator;
6014a1767b4Smrg }
6024a1767b4Smrg if (CP->op->precedence == 0)
6034a1767b4Smrg {
6044a1767b4Smrg TRACE (printf ("close paren for function\n"));
6054a1767b4Smrg goto apply_control;
6064a1767b4Smrg }
6074a1767b4Smrg ERROR ("unexpected close paren", MPEXPR_RESULT_PARSE_ERROR);
6084a1767b4Smrg
6094a1767b4Smrg default:
6104a1767b4Smrg TRACE (printf ("unrecognised special unary operator 0x%X",
6114a1767b4Smrg CP->op->type & MPEXPR_TYPE_MASK_SPECIAL));
6124a1767b4Smrg ERROR ("", MPEXPR_RESULT_BAD_TABLE);
6134a1767b4Smrg }
6144a1767b4Smrg
6154a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
6164a1767b4Smrg case 0:
6174a1767b4Smrg (* (mpexpr_fun_unary_t) CP->op->fun) (sp, sp);
6184a1767b4Smrg break;
6194a1767b4Smrg case MPEXPR_TYPE_LAST_UI:
6204a1767b4Smrg CHECK_UI (sp);
6214a1767b4Smrg (* (mpexpr_fun_unary_ui_t) CP->op->fun)
6224a1767b4Smrg (sp, (*p->mpX_get_ui) (sp));
6234a1767b4Smrg break;
6244a1767b4Smrg case MPEXPR_TYPE_RESULT_INT:
6254a1767b4Smrg (*p->mpX_set_si)
6264a1767b4Smrg (sp, (long) (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp));
6274a1767b4Smrg break;
6284a1767b4Smrg case MPEXPR_TYPE_RESULT_INT | MPEXPR_TYPE_LAST_UI:
6294a1767b4Smrg CHECK_UI (sp);
6304a1767b4Smrg (*p->mpX_set_si)
6314a1767b4Smrg (sp,
6324a1767b4Smrg (long) (* (mpexpr_fun_i_unary_ui_t) CP->op->fun)
6334a1767b4Smrg ((*p->mpX_get_ui) (sp)));
6344a1767b4Smrg break;
6354a1767b4Smrg default:
6364a1767b4Smrg ERROR ("unrecognised unary argument calling style",
6374a1767b4Smrg MPEXPR_RESULT_BAD_TABLE);
6384a1767b4Smrg }
6394a1767b4Smrg }
6404a1767b4Smrg break;
6414a1767b4Smrg
6424a1767b4Smrg case MPEXPR_TYPE_NARY(2):
6434a1767b4Smrg {
6444a1767b4Smrg mpX_ptr sp;
6454a1767b4Smrg
6464a1767b4Smrg /* pairwise functions are allowed to have just one argument */
6474a1767b4Smrg if ((CP->op->type & MPEXPR_TYPE_PAIRWISE)
6484a1767b4Smrg && CP->op->precedence == 0
6494a1767b4Smrg && CP->argcount == 1)
6504a1767b4Smrg goto apply_control_done;
6514a1767b4Smrg
6524a1767b4Smrg CHECK_ARGCOUNT ("binary", 2);
6534a1767b4Smrg DATA_POP (1);
6544a1767b4Smrg sp = SP;
6554a1767b4Smrg TRACE (MPX_TRACE ("lhs", sp);
6564a1767b4Smrg MPX_TRACE ("rhs", sp+1));
6574a1767b4Smrg
6584a1767b4Smrg if (CP->op->type & MPEXPR_TYPE_MASK_CMP)
6594a1767b4Smrg {
6604a1767b4Smrg int type = CP->op->type;
6614a1767b4Smrg int cmp = (* (mpexpr_fun_i_binary_t) CP->op->fun)
6624a1767b4Smrg (sp, sp+1);
6634a1767b4Smrg (*p->mpX_set_si)
6644a1767b4Smrg (sp,
6654a1767b4Smrg (long)
6664a1767b4Smrg (( (cmp < 0) & ((type & MPEXPR_TYPE_MASK_CMP_LT) != 0))
6674a1767b4Smrg | ((cmp == 0) & ((type & MPEXPR_TYPE_MASK_CMP_EQ) != 0))
6684a1767b4Smrg | ((cmp > 0) & ((type & MPEXPR_TYPE_MASK_CMP_GT) != 0))));
6694a1767b4Smrg goto apply_control_done;
6704a1767b4Smrg }
6714a1767b4Smrg
6724a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
6734a1767b4Smrg case 0:
6744a1767b4Smrg /* not a special */
6754a1767b4Smrg break;
6764a1767b4Smrg
6774a1767b4Smrg case MPEXPR_TYPE_QUESTION & MPEXPR_TYPE_MASK_SPECIAL:
6784a1767b4Smrg ERROR ("'?' without ':'", MPEXPR_RESULT_PARSE_ERROR);
6794a1767b4Smrg
6804a1767b4Smrg case MPEXPR_TYPE_COLON & MPEXPR_TYPE_MASK_SPECIAL:
6814a1767b4Smrg TRACE (printf ("special colon\n"));
6824a1767b4Smrg CONTROL_POP ();
6834a1767b4Smrg if (CP->op->type != MPEXPR_TYPE_QUESTION)
6844a1767b4Smrg ERROR ("':' without '?'", MPEXPR_RESULT_PARSE_ERROR);
6854a1767b4Smrg
6864a1767b4Smrg CP->argcount--;
6874a1767b4Smrg DATA_POP (1);
6884a1767b4Smrg sp--;
6894a1767b4Smrg TRACE (MPX_TRACE ("query", sp);
6904a1767b4Smrg MPX_TRACE ("true", sp+1);
6914a1767b4Smrg MPX_TRACE ("false", sp+2));
6924a1767b4Smrg (*p->mpX_set)
6934a1767b4Smrg (sp, (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
6944a1767b4Smrg ? sp+1 : sp+2);
6954a1767b4Smrg goto apply_control_done;
6964a1767b4Smrg
6974a1767b4Smrg case MPEXPR_TYPE_LOGICAL_AND & MPEXPR_TYPE_MASK_SPECIAL:
6984a1767b4Smrg TRACE (printf ("special logical and\n"));
6994a1767b4Smrg (*p->mpX_set_si)
7004a1767b4Smrg (sp,
7014a1767b4Smrg (long)
7024a1767b4Smrg ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
7034a1767b4Smrg && (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
7044a1767b4Smrg goto apply_control_done;
7054a1767b4Smrg
7064a1767b4Smrg case MPEXPR_TYPE_LOGICAL_OR & MPEXPR_TYPE_MASK_SPECIAL:
7074a1767b4Smrg TRACE (printf ("special logical and\n"));
7084a1767b4Smrg (*p->mpX_set_si)
7094a1767b4Smrg (sp,
7104a1767b4Smrg (long)
7114a1767b4Smrg ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
7124a1767b4Smrg || (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
7134a1767b4Smrg goto apply_control_done;
7144a1767b4Smrg
7154a1767b4Smrg case MPEXPR_TYPE_MAX & MPEXPR_TYPE_MASK_SPECIAL:
7164a1767b4Smrg TRACE (printf ("special max\n"));
7174a1767b4Smrg if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) < 0)
7184a1767b4Smrg (*p->mpX_swap) (sp, sp+1);
7194a1767b4Smrg goto apply_control_done;
7204a1767b4Smrg case MPEXPR_TYPE_MIN & MPEXPR_TYPE_MASK_SPECIAL:
7214a1767b4Smrg TRACE (printf ("special min\n"));
7224a1767b4Smrg if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) > 0)
7234a1767b4Smrg (*p->mpX_swap) (sp, sp+1);
7244a1767b4Smrg goto apply_control_done;
7254a1767b4Smrg
7264a1767b4Smrg default:
7274a1767b4Smrg ERROR ("unrecognised special binary operator",
7284a1767b4Smrg MPEXPR_RESULT_BAD_TABLE);
7294a1767b4Smrg }
7304a1767b4Smrg
7314a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
7324a1767b4Smrg case 0:
7334a1767b4Smrg (* (mpexpr_fun_binary_t) CP->op->fun) (sp, sp, sp+1);
7344a1767b4Smrg break;
7354a1767b4Smrg case MPEXPR_TYPE_LAST_UI:
7364a1767b4Smrg CHECK_UI (sp+1);
7374a1767b4Smrg (* (mpexpr_fun_binary_ui_t) CP->op->fun)
7384a1767b4Smrg (sp, sp, (*p->mpX_get_ui) (sp+1));
7394a1767b4Smrg break;
7404a1767b4Smrg case MPEXPR_TYPE_RESULT_INT:
7414a1767b4Smrg (*p->mpX_set_si)
7424a1767b4Smrg (sp,
7434a1767b4Smrg (long) (* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1));
7444a1767b4Smrg break;
7454a1767b4Smrg case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
7464a1767b4Smrg CHECK_UI (sp+1);
7474a1767b4Smrg (*p->mpX_set_si)
7484a1767b4Smrg (sp,
7494a1767b4Smrg (long) (* (mpexpr_fun_i_binary_ui_t) CP->op->fun)
7504a1767b4Smrg (sp, (*p->mpX_get_ui) (sp+1)));
7514a1767b4Smrg break;
7524a1767b4Smrg default:
7534a1767b4Smrg ERROR ("unrecognised binary argument calling style",
7544a1767b4Smrg MPEXPR_RESULT_BAD_TABLE);
7554a1767b4Smrg }
7564a1767b4Smrg }
7574a1767b4Smrg break;
7584a1767b4Smrg
7594a1767b4Smrg case MPEXPR_TYPE_NARY(3):
7604a1767b4Smrg {
7614a1767b4Smrg mpX_ptr sp;
7624a1767b4Smrg
7634a1767b4Smrg CHECK_ARGCOUNT ("ternary", 3);
7644a1767b4Smrg DATA_POP (2);
7654a1767b4Smrg sp = SP;
7664a1767b4Smrg TRACE (MPX_TRACE ("arg1", sp);
7674a1767b4Smrg MPX_TRACE ("arg2", sp+1);
7684a1767b4Smrg MPX_TRACE ("arg3", sp+1));
7694a1767b4Smrg
7704a1767b4Smrg switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
7714a1767b4Smrg case 0:
7724a1767b4Smrg (* (mpexpr_fun_ternary_t) CP->op->fun) (sp, sp, sp+1, sp+2);
7734a1767b4Smrg break;
7744a1767b4Smrg case MPEXPR_TYPE_LAST_UI:
7754a1767b4Smrg CHECK_UI (sp+2);
7764a1767b4Smrg (* (mpexpr_fun_ternary_ui_t) CP->op->fun)
7774a1767b4Smrg (sp, sp, sp+1, (*p->mpX_get_ui) (sp+2));
7784a1767b4Smrg break;
7794a1767b4Smrg case MPEXPR_TYPE_RESULT_INT:
7804a1767b4Smrg (*p->mpX_set_si)
7814a1767b4Smrg (sp,
7824a1767b4Smrg (long) (* (mpexpr_fun_i_ternary_t) CP->op->fun)
7834a1767b4Smrg (sp, sp+1, sp+2));
7844a1767b4Smrg break;
7854a1767b4Smrg case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
7864a1767b4Smrg CHECK_UI (sp+2);
7874a1767b4Smrg (*p->mpX_set_si)
7884a1767b4Smrg (sp,
7894a1767b4Smrg (long) (* (mpexpr_fun_i_ternary_ui_t) CP->op->fun)
7904a1767b4Smrg (sp, sp+1, (*p->mpX_get_ui) (sp+2)));
7914a1767b4Smrg break;
7924a1767b4Smrg default:
7934a1767b4Smrg ERROR ("unrecognised binary argument calling style",
7944a1767b4Smrg MPEXPR_RESULT_BAD_TABLE);
7954a1767b4Smrg }
7964a1767b4Smrg }
7974a1767b4Smrg break;
7984a1767b4Smrg
7994a1767b4Smrg default:
8004a1767b4Smrg TRACE (printf ("unrecognised operator type: 0x%X\n", CP->op->type));
8014a1767b4Smrg ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
8024a1767b4Smrg }
8034a1767b4Smrg
8044a1767b4Smrg apply_control_done:
8054a1767b4Smrg TRACE (MPX_TRACE ("result", SP));
8064a1767b4Smrg CONTROL_POP ();
8074a1767b4Smrg goto another_operator;
8084a1767b4Smrg
8094a1767b4Smrg done:
8104a1767b4Smrg if (p->error_code == MPEXPR_RESULT_OK)
8114a1767b4Smrg {
8124a1767b4Smrg if (p->data_top != 0)
8134a1767b4Smrg {
8144a1767b4Smrg TRACE (printf ("data stack want top at 0, got %d\n", p->data_top));
8154a1767b4Smrg p->error_code = MPEXPR_RESULT_PARSE_ERROR;
8164a1767b4Smrg }
8174a1767b4Smrg else
8184a1767b4Smrg (*p->mpX_set_or_swap) (p->res, SP);
8194a1767b4Smrg }
8204a1767b4Smrg
8214a1767b4Smrg {
8224a1767b4Smrg int i;
8234a1767b4Smrg for (i = 0; i < p->data_inited; i++)
8244a1767b4Smrg {
8254a1767b4Smrg TRACE (printf ("clear %d\n", i));
8264a1767b4Smrg (*p->mpX_clear) (p->data_stack+i);
8274a1767b4Smrg }
8284a1767b4Smrg }
8294a1767b4Smrg
8304a1767b4Smrg FREE_FUNC_TYPE (p->data_stack, p->data_alloc, union mpX_t);
8314a1767b4Smrg FREE_FUNC_TYPE (p->control_stack, p->control_alloc, struct mpexpr_control_t);
8324a1767b4Smrg
8334a1767b4Smrg return p->error_code;
8344a1767b4Smrg }
835