/* Implementation specifics for 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/.  */


/* Same tests as gmp.h. */
#if  defined (__STDC__)                                 \
  || defined (__cplusplus)                              \
  || defined (_AIX)                                     \
  || defined (__DECC)                                   \
  || (defined (__mips) && defined (_SYSTYPE_SVR4))      \
  || defined (_MSC_VER)                                 \
  || defined (_WIN32)
#define HAVE_STDARG 1
#include <stdarg.h>
#else
#define HAVE_STDARG 0
#include <varargs.h>
#endif

#include "expr.h"


#define isasciidigit(c)   (isascii (c) && isdigit (c))
#define isasciicsym(c)    (isascii (c) && (isalnum(c) || (c) == '_'))

#define isasciidigit_in_base(c,base)                    \
  (isascii (c)                                          \
   && ((isdigit (c) && (c)-'0' < (base))                \
       || (isupper (c) && (c)-'A'+10 < (base))          \
       || (islower (c) && (c)-'a'+10 < (base))))


union mpX_t {
  mpz_t   z;
  mpq_t   q;
  mpf_t   f;
};

typedef union mpX_t *mpX_ptr;
typedef __gmp_const union mpX_t *mpX_srcptr;

typedef void (*mpexpr_fun_one_t) __GMP_PROTO ((mpX_ptr));
typedef unsigned long (*mpexpr_fun_ui_one_t) __GMP_PROTO ((mpX_ptr));

typedef void (*mpexpr_fun_0ary_t) __GMP_PROTO ((mpX_ptr));
typedef int  (*mpexpr_fun_i_0ary_t) __GMP_PROTO ((void));

typedef void (*mpexpr_fun_unary_t) __GMP_PROTO ((mpX_ptr, mpX_srcptr));
typedef void (*mpexpr_fun_unary_ui_t) __GMP_PROTO ((mpX_ptr, unsigned long));
typedef int  (*mpexpr_fun_i_unary_t) __GMP_PROTO ((mpX_srcptr));
typedef int  (*mpexpr_fun_i_unary_ui_t) __GMP_PROTO ((unsigned long));

typedef void (*mpexpr_fun_binary_t) __GMP_PROTO ((mpX_ptr, mpX_srcptr, mpX_srcptr));
typedef void (*mpexpr_fun_binary_ui_t) __GMP_PROTO ((mpX_ptr, mpX_srcptr, unsigned long));
typedef int  (*mpexpr_fun_i_binary_t) __GMP_PROTO ((mpX_srcptr, mpX_srcptr));
typedef int  (*mpexpr_fun_i_binary_ui_t) __GMP_PROTO ((mpX_srcptr, unsigned long));

typedef void (*mpexpr_fun_ternary_t)
     __GMP_PROTO ((mpX_ptr, mpX_srcptr, mpX_srcptr, mpX_srcptr));
typedef void (*mpexpr_fun_ternary_ui_t)
     __GMP_PROTO ((mpX_ptr, mpX_srcptr, mpX_srcptr, unsigned long));
typedef int (*mpexpr_fun_i_ternary_t)
     __GMP_PROTO ((mpX_srcptr, mpX_srcptr, mpX_srcptr));
typedef int (*mpexpr_fun_i_ternary_ui_t)
     __GMP_PROTO ((mpX_srcptr, mpX_srcptr, unsigned long));

typedef size_t (*mpexpr_fun_number_t)
     __GMP_PROTO ((mpX_ptr, __gmp_const char *str, size_t len, int base));
typedef void (*mpexpr_fun_swap_t) __GMP_PROTO ((mpX_ptr, mpX_ptr));
typedef unsigned long (*mpexpr_fun_get_ui_t) __GMP_PROTO ((mpX_srcptr));
typedef void (*mpexpr_fun_set_si_t) __GMP_PROTO ((mpX_srcptr, long));

struct mpexpr_control_t {
  __gmp_const struct mpexpr_operator_t  *op;
  int                                   argcount;
};

#define MPEXPR_VARIABLES  26

struct mpexpr_parse_t {
  __gmp_const struct mpexpr_operator_t  *table;

  mpX_ptr                               res;
  int                                   base;
  unsigned long                         prec;
  __gmp_const char                      *e;
  size_t                                elen;
  mpX_srcptr                            *var;
  int                                   error_code;

  int                                   token;
  __gmp_const struct mpexpr_operator_t  *token_op;

  union mpX_t                           *data_stack;
  int                                   data_top;
  int                                   data_alloc;
  int                                   data_inited;

  struct mpexpr_control_t               *control_stack;
  int                                   control_top;
  int                                   control_alloc;


  mpexpr_fun_0ary_t                     mpX_clear;
  mpexpr_fun_i_unary_t                  mpX_ulong_p;
  mpexpr_fun_get_ui_t                   mpX_get_ui;
  mpexpr_fun_unary_ui_t                 mpX_init;
  mpexpr_fun_number_t                   mpX_number;
  mpexpr_fun_unary_t                    mpX_set;
  mpexpr_fun_unary_t                    mpX_set_or_swap;
  mpexpr_fun_set_si_t                   mpX_set_si;
  mpexpr_fun_swap_t                     mpX_swap;
};


int mpexpr_evaluate __GMP_PROTO ((struct mpexpr_parse_t *p));
int mpexpr_va_to_var __GMP_PROTO ((void *var[], va_list ap));
size_t mpexpr_mpz_number __GMP_PROTO ((mpz_ptr res,
                                  __gmp_const char *e, size_t elen, int base));
