Home | History | Annotate | Line # | Download | only in expr
expr.c revision 1.1.1.2
      1      1.1  mrg /* mpexpr_evaluate -- shared code for simple expression evaluation
      2      1.1  mrg 
      3      1.1  mrg Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU MP Library.
      6      1.1  mrg 
      7      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
      8      1.1  mrg it under the terms of the GNU Lesser General Public License as published by
      9      1.1  mrg the Free Software Foundation; either version 3 of the License, or (at your
     10      1.1  mrg option) any later version.
     11      1.1  mrg 
     12      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     13      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14      1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     15      1.1  mrg License for more details.
     16      1.1  mrg 
     17      1.1  mrg You should have received a copy of the GNU Lesser General Public License
     18      1.1  mrg along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     19      1.1  mrg 
     20      1.1  mrg #include <ctype.h>
     21      1.1  mrg #include <stdio.h>
     22      1.1  mrg #include <string.h>
     23      1.1  mrg 
     24      1.1  mrg #include "gmp.h"
     25      1.1  mrg #include "expr-impl.h"
     26      1.1  mrg 
     27      1.1  mrg 
     28      1.1  mrg /* Change this to "#define TRACE(x) x" to get some traces.  The trace
     29      1.1  mrg    printfs junk up the code a bit, but it's very hard to tell what's going
     30      1.1  mrg    on without them.  Set MPX_TRACE to a suitable output function for the
     31      1.1  mrg    mpz/mpq/mpf being run (if you have the wrong trace function it'll
     32      1.1  mrg    probably segv).  */
     33      1.1  mrg 
     34      1.1  mrg #define TRACE(x)
     35      1.1  mrg #define MPX_TRACE  mpz_trace
     36      1.1  mrg 
     37      1.1  mrg 
     38      1.1  mrg /* A few helper macros copied from gmp-impl.h */
     39      1.1  mrg #define ALLOCATE_FUNC_TYPE(n,type) \
     40      1.1  mrg   ((type *) (*allocate_func) ((n) * sizeof (type)))
     41      1.1  mrg #define ALLOCATE_FUNC_LIMBS(n)   ALLOCATE_FUNC_TYPE (n, mp_limb_t)
     42      1.1  mrg #define REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \
     43      1.1  mrg   ((type *) (*reallocate_func)                            \
     44      1.1  mrg    (p, (old_size) * sizeof (type), (new_size) * sizeof (type)))
     45      1.1  mrg #define REALLOCATE_FUNC_LIMBS(p, old_size, new_size) \
     46      1.1  mrg   REALLOCATE_FUNC_TYPE(p, old_size, new_size, mp_limb_t)
     47      1.1  mrg #define FREE_FUNC_TYPE(p,n,type) (*free_func) (p, (n) * sizeof (type))
     48      1.1  mrg #define FREE_FUNC_LIMBS(p,n)     FREE_FUNC_TYPE (p, n, mp_limb_t)
     49      1.1  mrg #define ASSERT(x)
     50      1.1  mrg 
     51      1.1  mrg 
     52      1.1  mrg 
     53      1.1  mrg /* All the error strings are just for diagnostic traces.  Only the error
     54      1.1  mrg    code is actually returned.  */
     55      1.1  mrg #define ERROR(str,code)                 \
     56      1.1  mrg   {                                     \
     57      1.1  mrg     TRACE (printf ("%s\n", str));       \
     58      1.1  mrg     p->error_code = (code);             \
     59      1.1  mrg     goto done;                          \
     60      1.1  mrg   }
     61      1.1  mrg 
     62      1.1  mrg 
     63      1.1  mrg #define REALLOC(ptr, alloc, incr, type)                         \
     64      1.1  mrg   do {                                                          \
     65      1.1  mrg     int  new_alloc = (alloc) + (incr);                          \
     66      1.1  mrg     ptr = REALLOCATE_FUNC_TYPE (ptr, alloc, new_alloc, type);   \
     67      1.1  mrg     (alloc) = new_alloc;                                        \
     68      1.1  mrg   } while (0)
     69      1.1  mrg 
     70      1.1  mrg 
     71      1.1  mrg /* data stack top element */
     72      1.1  mrg #define SP   (p->data_stack + p->data_top)
     73      1.1  mrg 
     74      1.1  mrg /* Make sure there's room for another data element above current top.
     75      1.1  mrg    reallocate_func is fetched for when this macro is used in lookahead(). */
     76      1.1  mrg #define DATA_SPACE()                                                    \
     77      1.1  mrg   do {                                                                  \
     78      1.1  mrg     if (p->data_top + 1 >= p->data_alloc)                               \
     79      1.1  mrg       {                                                                 \
     80      1.1  mrg 	void *(*reallocate_func) (void *, size_t, size_t);              \
     81      1.1  mrg 	mp_get_memory_functions (NULL, &reallocate_func, NULL);         \
     82      1.1  mrg 	TRACE (printf ("grow stack from %d\n", p->data_alloc));         \
     83      1.1  mrg 	REALLOC (p->data_stack, p->data_alloc, 20, union mpX_t);        \
     84      1.1  mrg       }                                                                 \
     85      1.1  mrg     ASSERT (p->data_top + 1 <= p->data_inited);                         \
     86      1.1  mrg     if (p->data_top + 1 == p->data_inited)                              \
     87      1.1  mrg       {                                                                 \
     88      1.1  mrg 	TRACE (printf ("initialize %d\n", p->data_top + 1));            \
     89      1.1  mrg 	(*p->mpX_init) (&p->data_stack[p->data_top + 1], p->prec);      \
     90      1.1  mrg 	p->data_inited++;                                               \
     91      1.1  mrg       }                                                                 \
     92      1.1  mrg   } while (0)
     93      1.1  mrg 
     94      1.1  mrg #define DATA_PUSH()                             \
     95      1.1  mrg   do {                                          \
     96      1.1  mrg     p->data_top++;                              \
     97      1.1  mrg     ASSERT (p->data_top < p->data_alloc);       \
     98      1.1  mrg     ASSERT (p->data_top < p->data_inited);      \
     99      1.1  mrg   } while (0)
    100      1.1  mrg 
    101      1.1  mrg /* the last stack entry is never popped, so top>=0 will be true */
    102      1.1  mrg #define DATA_POP(n)             \
    103      1.1  mrg   do {                          \
    104      1.1  mrg     p->data_top -= (n);         \
    105      1.1  mrg     ASSERT (p->data_top >= 0);  \
    106      1.1  mrg   } while (0)
    107      1.1  mrg 
    108      1.1  mrg 
    109      1.1  mrg /* lookahead() parses the next token.  Return 1 if successful, with some
    110      1.1  mrg    extra data.  Return 0 if fail, with reason in p->error_code.
    111      1.1  mrg 
    112      1.1  mrg    "prefix" is MPEXPR_TYPE_PREFIX if an operator with that attribute is
    113      1.1  mrg    preferred, or 0 if an operator without is preferred. */
    114      1.1  mrg 
    115      1.1  mrg #define TOKEN_EOF         -1   /* no extra data */
    116      1.1  mrg #define TOKEN_VALUE       -2   /* pushed onto data stack */
    117      1.1  mrg #define TOKEN_OPERATOR    -3   /* stored in p->token_op */
    118      1.1  mrg #define TOKEN_FUNCTION    -4   /* stored in p->token_op */
    119      1.1  mrg 
    120      1.1  mrg #define TOKEN_NAME(n)                           \
    121      1.1  mrg   ((n) == TOKEN_EOF ? "TOKEN_EOF"               \
    122      1.1  mrg    : (n) == TOKEN_VALUE ? "TOKEN_VALUE"         \
    123      1.1  mrg    : (n) == TOKEN_OPERATOR ? "TOKEN_OPERATOR"   \
    124      1.1  mrg    : (n) == TOKEN_VALUE ? "TOKEN_FUNCTION"      \
    125      1.1  mrg    : "UNKNOWN TOKEN")
    126      1.1  mrg 
    127      1.1  mrg /* Functions default to being parsed as whole words, operators to match just
    128      1.1  mrg    at the start of the string.  The type flags override this. */
    129      1.1  mrg #define WHOLEWORD(op)                           \
    130      1.1  mrg   (op->precedence == 0                          \
    131      1.1  mrg    ? (! (op->type & MPEXPR_TYPE_OPERATOR))      \
    132      1.1  mrg    :   (op->type & MPEXPR_TYPE_WHOLEWORD))
    133      1.1  mrg 
    134      1.1  mrg #define isasciispace(c)   (isascii (c) && isspace (c))
    135      1.1  mrg 
    136      1.1  mrg static int
    137      1.1  mrg lookahead (struct mpexpr_parse_t *p, int prefix)
    138      1.1  mrg {
    139  1.1.1.2  mrg   const struct mpexpr_operator_t  *op, *op_found;
    140      1.1  mrg   size_t  oplen, oplen_found, wlen;
    141      1.1  mrg   int     i;
    142      1.1  mrg 
    143      1.1  mrg   /* skip white space */
    144      1.1  mrg   while (p->elen > 0 && isasciispace (*p->e))
    145      1.1  mrg     p->e++, p->elen--;
    146      1.1  mrg 
    147      1.1  mrg   if (p->elen == 0)
    148      1.1  mrg     {
    149      1.1  mrg       TRACE (printf ("lookahead EOF\n"));
    150      1.1  mrg       p->token = TOKEN_EOF;
    151      1.1  mrg       return 1;
    152      1.1  mrg     }
    153      1.1  mrg 
    154      1.1  mrg   DATA_SPACE ();
    155      1.1  mrg 
    156      1.1  mrg   /* Get extent of whole word. */
    157      1.1  mrg   for (wlen = 0; wlen < p->elen; wlen++)
    158      1.1  mrg     if (! isasciicsym (p->e[wlen]))
    159      1.1  mrg       break;
    160      1.1  mrg 
    161      1.1  mrg   TRACE (printf ("lookahead at: \"%.*s\" length %u, word %u\n",
    162      1.1  mrg 		 (int) p->elen, p->e, p->elen, wlen));
    163      1.1  mrg 
    164      1.1  mrg   op_found = NULL;
    165      1.1  mrg   oplen_found = 0;
    166      1.1  mrg   for (op = p->table; op->name != NULL; op++)
    167      1.1  mrg     {
    168      1.1  mrg       if (op->type == MPEXPR_TYPE_NEW_TABLE)
    169      1.1  mrg 	{
    170      1.1  mrg 	  printf ("new\n");
    171      1.1  mrg 	  op = (struct mpexpr_operator_t *) op->name - 1;
    172      1.1  mrg 	  continue;
    173      1.1  mrg 	}
    174      1.1  mrg 
    175      1.1  mrg       oplen = strlen (op->name);
    176      1.1  mrg       if (! ((WHOLEWORD (op) ? wlen == oplen : p->elen >= oplen)
    177      1.1  mrg 	     && memcmp (p->e, op->name, oplen) == 0))
    178      1.1  mrg 	continue;
    179      1.1  mrg 
    180      1.1  mrg       /* Shorter matches don't replace longer previous ones. */
    181      1.1  mrg       if (op_found && oplen < oplen_found)
    182      1.1  mrg 	continue;
    183      1.1  mrg 
    184      1.1  mrg       /* On a match of equal length to a previous one, the old match isn't
    185      1.1  mrg 	 replaced if it has the preferred prefix, and if it doesn't then
    186      1.1  mrg 	 it's not replaced if the new one also doesn't.  */
    187      1.1  mrg       if (op_found && oplen == oplen_found
    188      1.1  mrg 	  && ((op_found->type & MPEXPR_TYPE_PREFIX) == prefix
    189      1.1  mrg 	      || (op->type & MPEXPR_TYPE_PREFIX) != prefix))
    190      1.1  mrg 	continue;
    191      1.1  mrg 
    192      1.1  mrg       /* This is now either the first match seen, or a longer than previous
    193      1.1  mrg 	 match, or an equal to previous one but with a preferred prefix. */
    194      1.1  mrg       op_found = op;
    195      1.1  mrg       oplen_found = oplen;
    196      1.1  mrg     }
    197      1.1  mrg 
    198      1.1  mrg   if (op_found)
    199      1.1  mrg     {
    200      1.1  mrg       p->e += oplen_found, p->elen -= oplen_found;
    201      1.1  mrg 
    202      1.1  mrg       if (op_found->type == MPEXPR_TYPE_VARIABLE)
    203      1.1  mrg 	{
    204      1.1  mrg 	  if (p->elen == 0)
    205      1.1  mrg 	    ERROR ("end of string expecting a variable",
    206      1.1  mrg 		   MPEXPR_RESULT_PARSE_ERROR);
    207      1.1  mrg 	  i = p->e[0] - 'a';
    208      1.1  mrg 	  if (i < 0 || i >= MPEXPR_VARIABLES)
    209      1.1  mrg 	    ERROR ("bad variable name", MPEXPR_RESULT_BAD_VARIABLE);
    210      1.1  mrg 	  goto variable;
    211      1.1  mrg 	}
    212      1.1  mrg 
    213      1.1  mrg       if (op_found->precedence == 0)
    214      1.1  mrg 	{
    215      1.1  mrg 	  TRACE (printf ("lookahead function: %s\n", op_found->name));
    216      1.1  mrg 	  p->token = TOKEN_FUNCTION;
    217      1.1  mrg 	  p->token_op = op_found;
    218      1.1  mrg 	  return 1;
    219      1.1  mrg 	}
    220      1.1  mrg       else
    221      1.1  mrg 	{
    222      1.1  mrg 	  TRACE (printf ("lookahead operator: %s\n", op_found->name));
    223      1.1  mrg 	  p->token = TOKEN_OPERATOR;
    224      1.1  mrg 	  p->token_op = op_found;
    225      1.1  mrg 	  return 1;
    226      1.1  mrg 	}
    227      1.1  mrg     }
    228      1.1  mrg 
    229      1.1  mrg   oplen = (*p->mpX_number) (SP+1, p->e, p->elen, p->base);
    230      1.1  mrg   if (oplen != 0)
    231      1.1  mrg     {
    232      1.1  mrg       p->e += oplen, p->elen -= oplen;
    233      1.1  mrg       p->token = TOKEN_VALUE;
    234      1.1  mrg       DATA_PUSH ();
    235      1.1  mrg       TRACE (MPX_TRACE ("lookahead number", SP));
    236      1.1  mrg       return 1;
    237      1.1  mrg     }
    238      1.1  mrg 
    239      1.1  mrg   /* Maybe an unprefixed one character variable */
    240      1.1  mrg   i = p->e[0] - 'a';
    241      1.1  mrg   if (wlen == 1 && i >= 0 && i < MPEXPR_VARIABLES)
    242      1.1  mrg     {
    243      1.1  mrg     variable:
    244      1.1  mrg       p->e++, p->elen--;
    245      1.1  mrg       if (p->var[i] == NULL)
    246      1.1  mrg 	ERROR ("NULL variable", MPEXPR_RESULT_BAD_VARIABLE);
    247      1.1  mrg       TRACE (printf ("lookahead variable: var[%d] = ", i);
    248      1.1  mrg 	     MPX_TRACE ("", p->var[i]));
    249      1.1  mrg       p->token = TOKEN_VALUE;
    250      1.1  mrg       DATA_PUSH ();
    251      1.1  mrg       (*p->mpX_set) (SP, p->var[i]);
    252      1.1  mrg       return 1;
    253      1.1  mrg     }
    254      1.1  mrg 
    255      1.1  mrg   ERROR ("no token matched", MPEXPR_RESULT_PARSE_ERROR);
    256      1.1  mrg 
    257      1.1  mrg  done:
    258      1.1  mrg   return 0;
    259      1.1  mrg }
    260      1.1  mrg 
    261      1.1  mrg 
    262      1.1  mrg /* control stack current top element */
    263      1.1  mrg #define CP   (p->control_stack + p->control_top)
    264      1.1  mrg 
    265      1.1  mrg /* make sure there's room for another control element above current top */
    266      1.1  mrg #define CONTROL_SPACE()                                                    \
    267      1.1  mrg   do {                                                                     \
    268      1.1  mrg     if (p->control_top + 1 >= p->control_alloc)                            \
    269      1.1  mrg       {                                                                    \
    270      1.1  mrg 	TRACE (printf ("grow control stack from %d\n", p->control_alloc)); \
    271      1.1  mrg 	REALLOC (p->control_stack, p->control_alloc, 20,                   \
    272      1.1  mrg 		 struct mpexpr_control_t);                                 \
    273      1.1  mrg       }                                                                    \
    274      1.1  mrg   } while (0)
    275      1.1  mrg 
    276      1.1  mrg /* Push an operator on the control stack, claiming currently to have the
    277      1.1  mrg    given number of args ready.  Local variable "op" is used in case opptr is
    278      1.1  mrg    a reference through CP.  */
    279      1.1  mrg #define CONTROL_PUSH(opptr,args)                        \
    280      1.1  mrg   do {                                                  \
    281  1.1.1.2  mrg     const struct mpexpr_operator_t *op = opptr;		\
    282      1.1  mrg     struct mpexpr_control_t *cp;                        \
    283      1.1  mrg     CONTROL_SPACE ();                                   \
    284      1.1  mrg     p->control_top++;                                   \
    285      1.1  mrg     ASSERT (p->control_top < p->control_alloc);         \
    286      1.1  mrg     cp = CP;                                            \
    287      1.1  mrg     cp->op = op;                                        \
    288      1.1  mrg     cp->argcount = (args);                              \
    289      1.1  mrg     TRACE_CONTROL("control stack push:");               \
    290      1.1  mrg   } while (0)
    291      1.1  mrg 
    292      1.1  mrg /* The special operator_done is never popped, so top>=0 will hold. */
    293      1.1  mrg #define CONTROL_POP()                           \
    294      1.1  mrg   do {                                          \
    295      1.1  mrg     p->control_top--;                           \
    296      1.1  mrg     ASSERT (p->control_top >= 0);               \
    297      1.1  mrg     TRACE_CONTROL ("control stack pop:");       \
    298      1.1  mrg   } while (0)
    299      1.1  mrg 
    300      1.1  mrg #define TRACE_CONTROL(str)                              \
    301      1.1  mrg   TRACE ({                                              \
    302      1.1  mrg     int  i;                                             \
    303      1.1  mrg     printf ("%s depth %d:", str, p->control_top);       \
    304      1.1  mrg     for (i = 0; i <= p->control_top; i++)               \
    305      1.1  mrg       printf (" \"%s\"(%d)",                            \
    306      1.1  mrg 	      p->control_stack[i].op->name,             \
    307      1.1  mrg 	      p->control_stack[i].argcount);            \
    308      1.1  mrg     printf ("\n");                                      \
    309      1.1  mrg   });
    310      1.1  mrg 
    311      1.1  mrg 
    312      1.1  mrg #define LOOKAHEAD(prefix)               \
    313      1.1  mrg   do {                                  \
    314      1.1  mrg     if (! lookahead (p, prefix))        \
    315      1.1  mrg       goto done;                        \
    316      1.1  mrg   } while (0)
    317      1.1  mrg 
    318      1.1  mrg #define CHECK_UI(n)                                                     \
    319      1.1  mrg   do {                                                                  \
    320      1.1  mrg     if (! (*p->mpX_ulong_p) (n))                                        \
    321      1.1  mrg       ERROR ("operand doesn't fit ulong", MPEXPR_RESULT_NOT_UI);        \
    322      1.1  mrg   } while (0)
    323      1.1  mrg 
    324      1.1  mrg #define CHECK_ARGCOUNT(str,n)                                              \
    325      1.1  mrg   do {                                                                     \
    326      1.1  mrg     if (CP->argcount != (n))                                               \
    327      1.1  mrg       {                                                                    \
    328      1.1  mrg 	TRACE (printf ("wrong number of arguments for %s, got %d want %d", \
    329      1.1  mrg 		       str, CP->argcount, n));                             \
    330      1.1  mrg 	ERROR ("", MPEXPR_RESULT_PARSE_ERROR);                             \
    331      1.1  mrg       }                                                                    \
    332      1.1  mrg   } while (0)
    333      1.1  mrg 
    334      1.1  mrg 
    335      1.1  mrg /* There's two basic states here.  In both p->token is the next token.
    336      1.1  mrg 
    337      1.1  mrg    "another_expr" is when a whole expression should be parsed.  This means a
    338      1.1  mrg    literal or variable value possibly followed by an operator, or a function
    339      1.1  mrg    or prefix operator followed by a further whole expression.
    340      1.1  mrg 
    341      1.1  mrg    "another_operator" is when an expression has been parsed and its value is
    342      1.1  mrg    on the top of the data stack (SP) and an optional further postfix or
    343      1.1  mrg    infix operator should be parsed.
    344      1.1  mrg 
    345      1.1  mrg    In "another_operator" precedences determine whether to push the operator
    346      1.1  mrg    onto the control stack, or instead go to "apply_control" to reduce the
    347      1.1  mrg    operator currently on top of the control stack.
    348      1.1  mrg 
    349      1.1  mrg    When an operator has both a prefix and postfix/infix form, a LOOKAHEAD()
    350      1.1  mrg    for "another_expr" will seek the prefix form, a LOOKAHEAD() for
    351      1.1  mrg    "another_operator" will seek the postfix/infix form.  The grammar is
    352      1.1  mrg    simple enough that the next state is known before reading the next token.
    353      1.1  mrg 
    354      1.1  mrg    Argument count checking guards against functions consuming the wrong
    355      1.1  mrg    number of operands from the data stack.  The same checks are applied to
    356      1.1  mrg    operators, but will always pass since a UNARY or BINARY will only ever
    357      1.1  mrg    parse with the correct operands.  */
    358      1.1  mrg 
    359      1.1  mrg int
    360      1.1  mrg mpexpr_evaluate (struct mpexpr_parse_t *p)
    361      1.1  mrg {
    362      1.1  mrg   void *(*allocate_func) (size_t);
    363      1.1  mrg   void *(*reallocate_func) (void *, size_t, size_t);
    364      1.1  mrg   void (*free_func) (void *, size_t);
    365      1.1  mrg 
    366      1.1  mrg   mp_get_memory_functions (&allocate_func, &reallocate_func, &free_func);
    367      1.1  mrg 
    368      1.1  mrg   TRACE (printf ("mpexpr_evaluate() base %d \"%.*s\"\n",
    369      1.1  mrg 		 p->base, (int) p->elen, p->e));
    370      1.1  mrg 
    371      1.1  mrg   /* "done" is a special sentinel at the bottom of the control stack,
    372      1.1  mrg      precedence -1 is lower than any normal operator.  */
    373      1.1  mrg   {
    374  1.1.1.2  mrg     static const struct mpexpr_operator_t  operator_done
    375      1.1  mrg       = { "DONE", NULL, MPEXPR_TYPE_DONE, -1 };
    376      1.1  mrg 
    377      1.1  mrg     p->control_alloc = 20;
    378      1.1  mrg     p->control_stack = ALLOCATE_FUNC_TYPE (p->control_alloc,
    379      1.1  mrg 					   struct mpexpr_control_t);
    380      1.1  mrg     p->control_top = 0;
    381      1.1  mrg     CP->op = &operator_done;
    382      1.1  mrg     CP->argcount = 1;
    383      1.1  mrg   }
    384      1.1  mrg 
    385      1.1  mrg   p->data_inited = 0;
    386      1.1  mrg   p->data_alloc = 20;
    387      1.1  mrg   p->data_stack = ALLOCATE_FUNC_TYPE (p->data_alloc, union mpX_t);
    388      1.1  mrg   p->data_top = -1;
    389      1.1  mrg 
    390      1.1  mrg   p->error_code = MPEXPR_RESULT_OK;
    391      1.1  mrg 
    392      1.1  mrg 
    393      1.1  mrg  another_expr_lookahead:
    394      1.1  mrg   LOOKAHEAD (MPEXPR_TYPE_PREFIX);
    395      1.1  mrg   TRACE (printf ("another expr\n"));
    396      1.1  mrg 
    397      1.1  mrg   /*another_expr:*/
    398      1.1  mrg   switch (p->token) {
    399      1.1  mrg   case TOKEN_VALUE:
    400      1.1  mrg     goto another_operator_lookahead;
    401      1.1  mrg 
    402      1.1  mrg   case TOKEN_OPERATOR:
    403      1.1  mrg     TRACE (printf ("operator %s\n", p->token_op->name));
    404      1.1  mrg     if (! (p->token_op->type & MPEXPR_TYPE_PREFIX))
    405      1.1  mrg       ERROR ("expected a prefix operator", MPEXPR_RESULT_PARSE_ERROR);
    406      1.1  mrg 
    407      1.1  mrg     CONTROL_PUSH (p->token_op, 1);
    408      1.1  mrg     goto another_expr_lookahead;
    409      1.1  mrg 
    410      1.1  mrg   case TOKEN_FUNCTION:
    411      1.1  mrg     CONTROL_PUSH (p->token_op, 1);
    412      1.1  mrg 
    413      1.1  mrg     if (p->token_op->type & MPEXPR_TYPE_CONSTANT)
    414      1.1  mrg       goto apply_control_lookahead;
    415      1.1  mrg 
    416      1.1  mrg     LOOKAHEAD (MPEXPR_TYPE_PREFIX);
    417      1.1  mrg     if (! (p->token == TOKEN_OPERATOR
    418      1.1  mrg 	   && p->token_op->type == MPEXPR_TYPE_OPENPAREN))
    419      1.1  mrg       ERROR ("expected open paren for function", MPEXPR_RESULT_PARSE_ERROR);
    420      1.1  mrg 
    421      1.1  mrg     TRACE (printf ("open paren for function \"%s\"\n", CP->op->name));
    422      1.1  mrg 
    423      1.1  mrg     if ((CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) == MPEXPR_TYPE_NARY(0))
    424      1.1  mrg       {
    425      1.1  mrg 	LOOKAHEAD (0);
    426      1.1  mrg 	if (! (p->token == TOKEN_OPERATOR
    427      1.1  mrg 	       && p->token_op->type == MPEXPR_TYPE_CLOSEPAREN))
    428      1.1  mrg 	  ERROR ("expected close paren for 0ary function",
    429      1.1  mrg 		 MPEXPR_RESULT_PARSE_ERROR);
    430      1.1  mrg 	goto apply_control_lookahead;
    431      1.1  mrg       }
    432      1.1  mrg 
    433      1.1  mrg     goto another_expr_lookahead;
    434      1.1  mrg   }
    435      1.1  mrg   ERROR ("unrecognised start of expression", MPEXPR_RESULT_PARSE_ERROR);
    436      1.1  mrg 
    437      1.1  mrg 
    438      1.1  mrg  another_operator_lookahead:
    439      1.1  mrg   LOOKAHEAD (0);
    440      1.1  mrg  another_operator:
    441      1.1  mrg   TRACE (printf ("another operator maybe: %s\n", TOKEN_NAME(p->token)));
    442      1.1  mrg 
    443      1.1  mrg   switch (p->token) {
    444      1.1  mrg   case TOKEN_EOF:
    445      1.1  mrg     goto apply_control;
    446      1.1  mrg 
    447      1.1  mrg   case TOKEN_OPERATOR:
    448      1.1  mrg     /* The next operator is compared to the one on top of the control stack.
    449      1.1  mrg        If the next is lower precedence, or the same precedence and not
    450      1.1  mrg        right-associative, then reduce using the control stack and look at
    451      1.1  mrg        the next operator again later.  */
    452      1.1  mrg 
    453      1.1  mrg #define PRECEDENCE_TEST_REDUCE(tprec,cprec,ttype,ctype)                 \
    454      1.1  mrg     ((tprec) < (cprec)                                                  \
    455      1.1  mrg      || ((tprec) == (cprec) && ! ((ttype) & MPEXPR_TYPE_RIGHTASSOC)))
    456      1.1  mrg 
    457      1.1  mrg     if (PRECEDENCE_TEST_REDUCE (p->token_op->precedence, CP->op->precedence,
    458      1.1  mrg 				p->token_op->type,       CP->op->type))
    459      1.1  mrg       {
    460      1.1  mrg 	TRACE (printf ("defer operator: %s (prec %d vs %d, type 0x%X)\n",
    461      1.1  mrg 		       p->token_op->name,
    462      1.1  mrg 		       p->token_op->precedence, CP->op->precedence,
    463      1.1  mrg 		       p->token_op->type));
    464      1.1  mrg 	goto apply_control;
    465      1.1  mrg       }
    466      1.1  mrg 
    467      1.1  mrg     /* An argsep is a binary operator, but is never pushed on the control
    468      1.1  mrg        stack, it just accumulates an extra argument for a function. */
    469      1.1  mrg     if (p->token_op->type == MPEXPR_TYPE_ARGSEP)
    470      1.1  mrg       {
    471      1.1  mrg 	if (CP->op->precedence != 0)
    472      1.1  mrg 	  ERROR ("ARGSEP not in a function call", MPEXPR_RESULT_PARSE_ERROR);
    473      1.1  mrg 
    474      1.1  mrg 	TRACE (printf ("argsep for function \"%s\"(%d)\n",
    475      1.1  mrg 		       CP->op->name, CP->argcount));
    476      1.1  mrg 
    477      1.1  mrg #define IS_PAIRWISE(type)                                               \
    478      1.1  mrg 	(((type) & (MPEXPR_TYPE_MASK_ARGCOUNT | MPEXPR_TYPE_PAIRWISE))  \
    479      1.1  mrg 	 == (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_PAIRWISE))
    480      1.1  mrg 
    481      1.1  mrg 	if (IS_PAIRWISE (CP->op->type) && CP->argcount >= 2)
    482      1.1  mrg 	  {
    483      1.1  mrg 	    TRACE (printf ("    will reduce pairwise now\n"));
    484      1.1  mrg 	    CP->argcount--;
    485      1.1  mrg 	    CONTROL_PUSH (CP->op, 2);
    486      1.1  mrg 	    goto apply_control;
    487      1.1  mrg 	  }
    488      1.1  mrg 
    489      1.1  mrg 	CP->argcount++;
    490      1.1  mrg 	goto another_expr_lookahead;
    491      1.1  mrg       }
    492      1.1  mrg 
    493      1.1  mrg     switch (p->token_op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
    494      1.1  mrg     case MPEXPR_TYPE_NARY(1):
    495      1.1  mrg       /* Postfix unary operators can always be applied immediately.  The
    496      1.1  mrg 	 easiest way to do this is just push it on the control stack and go
    497      1.1  mrg 	 to the normal control stack reduction code. */
    498      1.1  mrg 
    499      1.1  mrg       TRACE (printf ("postfix unary operator: %s\n", p->token_op->name));
    500      1.1  mrg       if (p->token_op->type & MPEXPR_TYPE_PREFIX)
    501      1.1  mrg 	ERROR ("prefix unary operator used postfix",
    502      1.1  mrg 	       MPEXPR_RESULT_PARSE_ERROR);
    503      1.1  mrg       CONTROL_PUSH (p->token_op, 1);
    504      1.1  mrg       goto apply_control_lookahead;
    505      1.1  mrg 
    506      1.1  mrg     case MPEXPR_TYPE_NARY(2):
    507      1.1  mrg       CONTROL_PUSH (p->token_op, 2);
    508      1.1  mrg       goto another_expr_lookahead;
    509      1.1  mrg 
    510      1.1  mrg     case MPEXPR_TYPE_NARY(3):
    511      1.1  mrg       CONTROL_PUSH (p->token_op, 1);
    512      1.1  mrg       goto another_expr_lookahead;
    513      1.1  mrg     }
    514      1.1  mrg 
    515      1.1  mrg     TRACE (printf ("unrecognised operator \"%s\" type: 0x%X",
    516      1.1  mrg 		   CP->op->name, CP->op->type));
    517      1.1  mrg     ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
    518      1.1  mrg     break;
    519      1.1  mrg 
    520      1.1  mrg   default:
    521      1.1  mrg     TRACE (printf ("expecting an operator, got token %d", p->token));
    522      1.1  mrg     ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
    523      1.1  mrg   }
    524      1.1  mrg 
    525      1.1  mrg 
    526      1.1  mrg  apply_control_lookahead:
    527      1.1  mrg   LOOKAHEAD (0);
    528      1.1  mrg  apply_control:
    529      1.1  mrg   /* Apply the top element CP of the control stack.  Data values are SP,
    530      1.1  mrg      SP-1, etc.  Result is left as stack top SP after popping consumed
    531      1.1  mrg      values.
    532      1.1  mrg 
    533      1.1  mrg      The use of sp as a duplicate of SP will help compilers that can't
    534      1.1  mrg      otherwise recognise the various uses of SP as common subexpressions.  */
    535      1.1  mrg 
    536      1.1  mrg   TRACE (printf ("apply control: nested %d, \"%s\" 0x%X, %d args\n",
    537      1.1  mrg 		 p->control_top, CP->op->name, CP->op->type, CP->argcount));
    538      1.1  mrg 
    539      1.1  mrg   TRACE (printf ("apply 0x%X-ary\n",
    540      1.1  mrg 		 CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT));
    541      1.1  mrg   switch (CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
    542      1.1  mrg   case MPEXPR_TYPE_NARY(0):
    543      1.1  mrg     {
    544      1.1  mrg       mpX_ptr  sp;
    545      1.1  mrg       DATA_SPACE ();
    546      1.1  mrg       DATA_PUSH ();
    547      1.1  mrg       sp = SP;
    548      1.1  mrg       switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
    549      1.1  mrg       case 0:
    550      1.1  mrg 	(* (mpexpr_fun_0ary_t) CP->op->fun) (sp);
    551      1.1  mrg 	break;
    552      1.1  mrg       case MPEXPR_TYPE_RESULT_INT:
    553      1.1  mrg 	(*p->mpX_set_si) (sp, (long) (* (mpexpr_fun_i_0ary_t) CP->op->fun) ());
    554      1.1  mrg 	break;
    555      1.1  mrg       default:
    556      1.1  mrg 	ERROR ("unrecognised 0ary argument calling style",
    557      1.1  mrg 	       MPEXPR_RESULT_BAD_TABLE);
    558      1.1  mrg       }
    559      1.1  mrg     }
    560      1.1  mrg     break;
    561      1.1  mrg 
    562      1.1  mrg   case MPEXPR_TYPE_NARY(1):
    563      1.1  mrg     {
    564      1.1  mrg       mpX_ptr  sp = SP;
    565      1.1  mrg       CHECK_ARGCOUNT ("unary", 1);
    566      1.1  mrg       TRACE (MPX_TRACE ("before", sp));
    567      1.1  mrg 
    568      1.1  mrg       switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
    569      1.1  mrg       case 0:
    570      1.1  mrg 	/* not a special */
    571      1.1  mrg 	break;
    572      1.1  mrg 
    573      1.1  mrg       case MPEXPR_TYPE_DONE & MPEXPR_TYPE_MASK_SPECIAL:
    574      1.1  mrg 	TRACE (printf ("special done\n"));
    575      1.1  mrg 	goto done;
    576      1.1  mrg 
    577      1.1  mrg       case MPEXPR_TYPE_LOGICAL_NOT & MPEXPR_TYPE_MASK_SPECIAL:
    578      1.1  mrg 	TRACE (printf ("special logical not\n"));
    579      1.1  mrg 	(*p->mpX_set_si)
    580      1.1  mrg 	  (sp, (long) ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp) == 0));
    581      1.1  mrg 	goto apply_control_done;
    582      1.1  mrg 
    583      1.1  mrg       case MPEXPR_TYPE_CLOSEPAREN & MPEXPR_TYPE_MASK_SPECIAL:
    584      1.1  mrg 	CONTROL_POP ();
    585      1.1  mrg 	if (CP->op->type == MPEXPR_TYPE_OPENPAREN)
    586      1.1  mrg 	  {
    587      1.1  mrg 	    TRACE (printf ("close paren matching open paren\n"));
    588      1.1  mrg 	    CONTROL_POP ();
    589      1.1  mrg 	    goto another_operator;
    590      1.1  mrg 	  }
    591      1.1  mrg 	if (CP->op->precedence == 0)
    592      1.1  mrg 	  {
    593      1.1  mrg 	    TRACE (printf ("close paren for function\n"));
    594      1.1  mrg 	    goto apply_control;
    595      1.1  mrg 	  }
    596      1.1  mrg 	ERROR ("unexpected close paren", MPEXPR_RESULT_PARSE_ERROR);
    597      1.1  mrg 
    598      1.1  mrg       default:
    599      1.1  mrg 	TRACE (printf ("unrecognised special unary operator 0x%X",
    600      1.1  mrg 		       CP->op->type & MPEXPR_TYPE_MASK_SPECIAL));
    601      1.1  mrg 	ERROR ("", MPEXPR_RESULT_BAD_TABLE);
    602      1.1  mrg       }
    603      1.1  mrg 
    604      1.1  mrg       switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
    605      1.1  mrg       case 0:
    606      1.1  mrg 	(* (mpexpr_fun_unary_t) CP->op->fun) (sp, sp);
    607      1.1  mrg 	break;
    608      1.1  mrg       case MPEXPR_TYPE_LAST_UI:
    609      1.1  mrg 	CHECK_UI (sp);
    610      1.1  mrg 	(* (mpexpr_fun_unary_ui_t) CP->op->fun)
    611      1.1  mrg 	  (sp, (*p->mpX_get_ui) (sp));
    612      1.1  mrg 	break;
    613      1.1  mrg       case MPEXPR_TYPE_RESULT_INT:
    614      1.1  mrg 	(*p->mpX_set_si)
    615      1.1  mrg 	  (sp, (long) (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp));
    616      1.1  mrg 	break;
    617      1.1  mrg       case MPEXPR_TYPE_RESULT_INT | MPEXPR_TYPE_LAST_UI:
    618      1.1  mrg 	CHECK_UI (sp);
    619      1.1  mrg 	(*p->mpX_set_si)
    620      1.1  mrg 	  (sp,
    621      1.1  mrg 	   (long) (* (mpexpr_fun_i_unary_ui_t) CP->op->fun)
    622      1.1  mrg 	   ((*p->mpX_get_ui) (sp)));
    623      1.1  mrg 	break;
    624      1.1  mrg       default:
    625      1.1  mrg 	ERROR ("unrecognised unary argument calling style",
    626      1.1  mrg 	       MPEXPR_RESULT_BAD_TABLE);
    627      1.1  mrg       }
    628      1.1  mrg     }
    629      1.1  mrg     break;
    630      1.1  mrg 
    631      1.1  mrg   case MPEXPR_TYPE_NARY(2):
    632      1.1  mrg     {
    633      1.1  mrg       mpX_ptr  sp;
    634      1.1  mrg 
    635      1.1  mrg       /* pairwise functions are allowed to have just one argument */
    636      1.1  mrg       if ((CP->op->type & MPEXPR_TYPE_PAIRWISE)
    637      1.1  mrg 	  && CP->op->precedence == 0
    638      1.1  mrg 	  && CP->argcount == 1)
    639      1.1  mrg 	goto apply_control_done;
    640      1.1  mrg 
    641      1.1  mrg       CHECK_ARGCOUNT ("binary", 2);
    642      1.1  mrg       DATA_POP (1);
    643      1.1  mrg       sp = SP;
    644      1.1  mrg       TRACE (MPX_TRACE ("lhs", sp);
    645      1.1  mrg 	     MPX_TRACE ("rhs", sp+1));
    646      1.1  mrg 
    647      1.1  mrg       if (CP->op->type & MPEXPR_TYPE_MASK_CMP)
    648      1.1  mrg 	{
    649      1.1  mrg 	  int  type = CP->op->type;
    650      1.1  mrg 	  int  cmp = (* (mpexpr_fun_i_binary_t) CP->op->fun)
    651      1.1  mrg 	    (sp, sp+1);
    652      1.1  mrg 	  (*p->mpX_set_si)
    653      1.1  mrg 	    (sp,
    654      1.1  mrg 	     (long)
    655      1.1  mrg 	     ((  (cmp  < 0) & ((type & MPEXPR_TYPE_MASK_CMP_LT) != 0))
    656      1.1  mrg 	      | ((cmp == 0) & ((type & MPEXPR_TYPE_MASK_CMP_EQ) != 0))
    657      1.1  mrg 	      | ((cmp  > 0) & ((type & MPEXPR_TYPE_MASK_CMP_GT) != 0))));
    658      1.1  mrg 	  goto apply_control_done;
    659      1.1  mrg 	}
    660      1.1  mrg 
    661      1.1  mrg       switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
    662      1.1  mrg       case 0:
    663      1.1  mrg 	/* not a special */
    664      1.1  mrg 	break;
    665      1.1  mrg 
    666      1.1  mrg       case MPEXPR_TYPE_QUESTION & MPEXPR_TYPE_MASK_SPECIAL:
    667      1.1  mrg 	ERROR ("'?' without ':'", MPEXPR_RESULT_PARSE_ERROR);
    668      1.1  mrg 
    669      1.1  mrg       case MPEXPR_TYPE_COLON & MPEXPR_TYPE_MASK_SPECIAL:
    670      1.1  mrg 	TRACE (printf ("special colon\n"));
    671      1.1  mrg 	CONTROL_POP ();
    672      1.1  mrg 	if (CP->op->type != MPEXPR_TYPE_QUESTION)
    673      1.1  mrg 	  ERROR ("':' without '?'", MPEXPR_RESULT_PARSE_ERROR);
    674      1.1  mrg 
    675      1.1  mrg 	CP->argcount--;
    676      1.1  mrg 	DATA_POP (1);
    677      1.1  mrg 	sp--;
    678      1.1  mrg 	TRACE (MPX_TRACE ("query", sp);
    679      1.1  mrg 	       MPX_TRACE ("true",  sp+1);
    680      1.1  mrg 	       MPX_TRACE ("false", sp+2));
    681      1.1  mrg 	(*p->mpX_set)
    682      1.1  mrg 	  (sp, (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
    683      1.1  mrg 	   ? sp+1 : sp+2);
    684      1.1  mrg 	goto apply_control_done;
    685      1.1  mrg 
    686      1.1  mrg       case MPEXPR_TYPE_LOGICAL_AND & MPEXPR_TYPE_MASK_SPECIAL:
    687      1.1  mrg 	TRACE (printf ("special logical and\n"));
    688      1.1  mrg 	(*p->mpX_set_si)
    689      1.1  mrg 	  (sp,
    690      1.1  mrg 	   (long)
    691      1.1  mrg 	   ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
    692      1.1  mrg 	    && (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
    693      1.1  mrg 	goto apply_control_done;
    694      1.1  mrg 
    695      1.1  mrg       case MPEXPR_TYPE_LOGICAL_OR & MPEXPR_TYPE_MASK_SPECIAL:
    696      1.1  mrg 	TRACE (printf ("special logical and\n"));
    697      1.1  mrg 	(*p->mpX_set_si)
    698      1.1  mrg 	  (sp,
    699      1.1  mrg 	   (long)
    700      1.1  mrg 	   ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
    701      1.1  mrg 	    || (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
    702      1.1  mrg 	goto apply_control_done;
    703      1.1  mrg 
    704      1.1  mrg       case MPEXPR_TYPE_MAX & MPEXPR_TYPE_MASK_SPECIAL:
    705      1.1  mrg 	TRACE (printf ("special max\n"));
    706      1.1  mrg 	if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) < 0)
    707      1.1  mrg 	  (*p->mpX_swap) (sp, sp+1);
    708      1.1  mrg 	goto apply_control_done;
    709      1.1  mrg       case MPEXPR_TYPE_MIN & MPEXPR_TYPE_MASK_SPECIAL:
    710      1.1  mrg 	TRACE (printf ("special min\n"));
    711      1.1  mrg 	if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) > 0)
    712      1.1  mrg 	  (*p->mpX_swap) (sp, sp+1);
    713      1.1  mrg 	goto apply_control_done;
    714      1.1  mrg 
    715      1.1  mrg       default:
    716      1.1  mrg 	ERROR ("unrecognised special binary operator",
    717      1.1  mrg 	       MPEXPR_RESULT_BAD_TABLE);
    718      1.1  mrg       }
    719      1.1  mrg 
    720      1.1  mrg       switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
    721      1.1  mrg       case 0:
    722      1.1  mrg 	(* (mpexpr_fun_binary_t) CP->op->fun) (sp, sp, sp+1);
    723      1.1  mrg 	break;
    724      1.1  mrg       case MPEXPR_TYPE_LAST_UI:
    725      1.1  mrg 	CHECK_UI (sp+1);
    726      1.1  mrg 	(* (mpexpr_fun_binary_ui_t) CP->op->fun)
    727      1.1  mrg 	  (sp, sp, (*p->mpX_get_ui) (sp+1));
    728      1.1  mrg 	break;
    729      1.1  mrg       case MPEXPR_TYPE_RESULT_INT:
    730      1.1  mrg 	(*p->mpX_set_si)
    731      1.1  mrg 	  (sp,
    732      1.1  mrg 	   (long) (* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1));
    733      1.1  mrg 	break;
    734      1.1  mrg       case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
    735      1.1  mrg 	CHECK_UI (sp+1);
    736      1.1  mrg 	(*p->mpX_set_si)
    737      1.1  mrg 	  (sp,
    738      1.1  mrg 	   (long) (* (mpexpr_fun_i_binary_ui_t) CP->op->fun)
    739      1.1  mrg 	   (sp, (*p->mpX_get_ui) (sp+1)));
    740      1.1  mrg 	break;
    741      1.1  mrg       default:
    742      1.1  mrg 	ERROR ("unrecognised binary argument calling style",
    743      1.1  mrg 	       MPEXPR_RESULT_BAD_TABLE);
    744      1.1  mrg       }
    745      1.1  mrg     }
    746      1.1  mrg     break;
    747      1.1  mrg 
    748      1.1  mrg   case MPEXPR_TYPE_NARY(3):
    749      1.1  mrg     {
    750      1.1  mrg       mpX_ptr  sp;
    751      1.1  mrg 
    752      1.1  mrg       CHECK_ARGCOUNT ("ternary", 3);
    753      1.1  mrg       DATA_POP (2);
    754      1.1  mrg       sp = SP;
    755      1.1  mrg       TRACE (MPX_TRACE ("arg1", sp);
    756      1.1  mrg 	     MPX_TRACE ("arg2", sp+1);
    757      1.1  mrg 	     MPX_TRACE ("arg3", sp+1));
    758      1.1  mrg 
    759      1.1  mrg       switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
    760      1.1  mrg       case 0:
    761      1.1  mrg 	(* (mpexpr_fun_ternary_t) CP->op->fun) (sp, sp, sp+1, sp+2);
    762      1.1  mrg 	break;
    763      1.1  mrg       case MPEXPR_TYPE_LAST_UI:
    764      1.1  mrg 	CHECK_UI (sp+2);
    765      1.1  mrg 	(* (mpexpr_fun_ternary_ui_t) CP->op->fun)
    766      1.1  mrg 	  (sp, sp, sp+1, (*p->mpX_get_ui) (sp+2));
    767      1.1  mrg 	break;
    768      1.1  mrg       case MPEXPR_TYPE_RESULT_INT:
    769      1.1  mrg 	(*p->mpX_set_si)
    770      1.1  mrg 	  (sp,
    771      1.1  mrg 	   (long) (* (mpexpr_fun_i_ternary_t) CP->op->fun)
    772      1.1  mrg 	   (sp, sp+1, sp+2));
    773      1.1  mrg 	break;
    774      1.1  mrg       case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
    775      1.1  mrg 	CHECK_UI (sp+2);
    776      1.1  mrg 	(*p->mpX_set_si)
    777      1.1  mrg 	  (sp,
    778      1.1  mrg 	   (long) (* (mpexpr_fun_i_ternary_ui_t) CP->op->fun)
    779      1.1  mrg 	   (sp, sp+1, (*p->mpX_get_ui) (sp+2)));
    780      1.1  mrg 	break;
    781      1.1  mrg       default:
    782      1.1  mrg 	ERROR ("unrecognised binary argument calling style",
    783      1.1  mrg 	       MPEXPR_RESULT_BAD_TABLE);
    784      1.1  mrg       }
    785      1.1  mrg     }
    786      1.1  mrg     break;
    787      1.1  mrg 
    788      1.1  mrg   default:
    789      1.1  mrg     TRACE (printf ("unrecognised operator type: 0x%X\n", CP->op->type));
    790      1.1  mrg     ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
    791      1.1  mrg   }
    792      1.1  mrg 
    793      1.1  mrg  apply_control_done:
    794      1.1  mrg   TRACE (MPX_TRACE ("result", SP));
    795      1.1  mrg   CONTROL_POP ();
    796      1.1  mrg   goto another_operator;
    797      1.1  mrg 
    798      1.1  mrg  done:
    799      1.1  mrg   if (p->error_code == MPEXPR_RESULT_OK)
    800      1.1  mrg     {
    801      1.1  mrg       if (p->data_top != 0)
    802      1.1  mrg 	{
    803      1.1  mrg 	  TRACE (printf ("data stack want top at 0, got %d\n", p->data_top));
    804      1.1  mrg 	  p->error_code = MPEXPR_RESULT_PARSE_ERROR;
    805      1.1  mrg 	}
    806      1.1  mrg       else
    807      1.1  mrg 	(*p->mpX_set_or_swap) (p->res, SP);
    808      1.1  mrg     }
    809      1.1  mrg 
    810      1.1  mrg   {
    811      1.1  mrg     int  i;
    812      1.1  mrg     for (i = 0; i < p->data_inited; i++)
    813      1.1  mrg       {
    814      1.1  mrg 	TRACE (printf ("clear %d\n", i));
    815      1.1  mrg 	(*p->mpX_clear) (p->data_stack+i);
    816      1.1  mrg       }
    817      1.1  mrg   }
    818      1.1  mrg 
    819      1.1  mrg   FREE_FUNC_TYPE (p->data_stack, p->data_alloc, union mpX_t);
    820      1.1  mrg   FREE_FUNC_TYPE (p->control_stack, p->control_alloc, struct mpexpr_control_t);
    821      1.1  mrg 
    822      1.1  mrg   return p->error_code;
    823      1.1  mrg }
    824