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