2 static char *RCSid() { return RCSid("$Id: parse.c,v 1.47.2.1 2008/04/08 19:00:44 sfeam Exp $"); }
5 /* GNUPLOT - parse.c */
8 * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
10 * Permission to use, copy, and distribute this software and its
11 * documentation for any purpose with or without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and
13 * that both that copyright notice and this permission notice appear
14 * in supporting documentation.
16 * Permission to modify the software is granted, but not the right to
17 * distribute the complete modified source code. Modifications are to
18 * be distributed as patches to the released version. Permission to
19 * distribute binaries produced by compiling modified sources is granted,
21 * 1. distribute the corresponding source modifications from the
22 * released version in the form of a patch file along with the binaries,
23 * 2. add special version identification to distinguish your version
24 * in addition to the base release version number,
25 * 3. provide your name and address as the primary contact for the
26 * support of your modified version, and
27 * 4. retain our contact information in regard to use of the base
29 * Permission to distribute the released version of the source code along
30 * with corresponding source modifications in the form of a patch file is
31 * granted with same provisions 2 through 4 for binary distributions.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
45 /* protection mechanism for parsing string followed by + or - sign */
46 static int parse_recursion_level;
47 static TBOOLEAN string_result_only = FALSE;
49 /* Exported globals: the current 'dummy' variable names */
50 char c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1];
51 char set_dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1] = { "x", "y" };
53 /* This is used by plot_option_using() */
54 int at_highest_column_used = -1;
56 /* Internal prototypes: */
58 static void convert __PROTO((struct value *, int));
59 static void extend_at __PROTO((void));
60 static union argument *add_action __PROTO((enum operators sf_index));
61 static void parse_expression __PROTO((void));
62 static void accept_logical_OR_expression __PROTO((void));
63 static void accept_logical_AND_expression __PROTO((void));
64 static void accept_inclusive_OR_expression __PROTO((void));
65 static void accept_exclusive_OR_expression __PROTO((void));
66 static void accept_AND_expression __PROTO((void));
67 static void accept_equality_expression __PROTO((void));
68 static void accept_relational_expression __PROTO((void));
69 static void accept_additive_expression __PROTO((void));
70 static void accept_multiplicative_expression __PROTO((void));
71 static void parse_primary_expression __PROTO((void));
72 static void parse_conditional_expression __PROTO((void));
73 static void parse_logical_OR_expression __PROTO((void));
74 static void parse_logical_AND_expression __PROTO((void));
75 static void parse_inclusive_OR_expression __PROTO((void));
76 static void parse_exclusive_OR_expression __PROTO((void));
77 static void parse_AND_expression __PROTO((void));
78 static void parse_equality_expression __PROTO((void));
79 static void parse_relational_expression __PROTO((void));
80 static void parse_additive_expression __PROTO((void));
81 static void parse_multiplicative_expression __PROTO((void));
82 static void parse_unary_expression __PROTO((void));
83 static int is_builtin_function __PROTO((int t_num));
85 /* Internal variables: */
87 static struct at_type *at = NULL;
88 static int at_size = 0;
91 convert(struct value *val_ptr, int t_num)
93 *val_ptr = token[t_num].l_val;
98 * Wrapper around const_express() called by try_to_get_string().
99 * Disallows top level + and - operators.
100 * This enables things like set xtics ('-\pi' -pi, '-\pi/2' -pi/2.)
103 const_string_express(struct value *valptr)
105 string_result_only = TRUE;
106 const_express(valptr);
107 string_result_only = FALSE;
112 const_express(struct value *valptr)
117 int_error(c_token, "constant expression required");
119 /* div - no dummy variables in a constant expression */
122 evaluate_at(temp_at(), valptr); /* run it and send answer back */
125 int_error(tkn, "undefined value");
130 /* Used by plot2d/plot3d/fit:
131 * Parse an expression that may return a string or may return a constant or may
132 * be a dummy function using dummy variables x, y, ...
133 * If any dummy variables are present, set (*atptr) to point to an action table
134 * corresponding to the parsed expression, and return NULL.
135 * Otherwise evaluate the expression and return a string if there is one.
136 * The return value "str" and "*atptr" both point to locally-managed memory,
137 * which must not be freed by the caller!
140 string_or_express(struct at_type **atptr)
143 TBOOLEAN has_dummies;
145 static char* str = NULL;
150 int_error(c_token, "expression expected");
152 #ifndef GP_STRING_VARS
153 if (isstring(c_token)) {
156 str = try_to_get_string();
161 /* parse expression */
164 /* check if any dummy variables are used */
166 for (i = 0; i < at->a_count; i++) {
167 enum operators op_index = at->actions[i].index;
168 if ( op_index == PUSHD1 || op_index == PUSHD2 || op_index == PUSHD ) {
175 /* no dummy variables: evaluate expression */
178 evaluate_at(at, &val);
179 #ifdef GP_STRING_VARS
180 if (!undefined && val.type == STRING)
181 str = val.v.string_val;
192 /* build an action table and return its pointer, but keep a pointer in at
193 * so that we can free it later if the caller hasn't taken over management
203 at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
205 memset(at, 0, sizeof(*at)); /* reset action table !!! */
206 at_size = MAX_AT_LEN;
208 parse_recursion_level = 0;
214 /* build an action table, put it in dynamic memory, and return its pointer */
219 struct at_type *at_ptr;
223 len = sizeof(struct at_type) +
224 (at->a_count - MAX_AT_LEN) * sizeof(struct at_entry);
225 at_ptr = (struct at_type *) gp_realloc(at, len, "perm_at");
226 at = NULL; /* invalidate at pointer */
233 size_t newsize = sizeof(struct at_type) + at_size * sizeof(struct at_entry);
235 at = gp_realloc(at, newsize, "extend_at");
236 at_size += MAX_AT_LEN;
237 FPRINTF((stderr, "Extending at size to %d\n", at_size));
240 /* Add function number <sf_index> to the current action table */
241 static union argument *
242 add_action(enum operators sf_index)
244 if (at->a_count >= at_size) {
247 at->actions[at->a_count].index = sf_index;
248 return (&(at->actions[at->a_count++].arg));
252 /* For external calls to parse_expressions()
253 * parse_recursion_level is expected to be 0 */
256 { /* full expressions */
257 parse_recursion_level++;
258 accept_logical_OR_expression();
259 parse_conditional_expression();
260 parse_recursion_level--;
264 accept_logical_OR_expression()
265 { /* ? : expressions */
266 accept_logical_AND_expression();
267 parse_logical_OR_expression();
272 accept_logical_AND_expression()
274 accept_inclusive_OR_expression();
275 parse_logical_AND_expression();
280 accept_inclusive_OR_expression()
282 accept_exclusive_OR_expression();
283 parse_inclusive_OR_expression();
288 accept_exclusive_OR_expression()
290 accept_AND_expression();
291 parse_exclusive_OR_expression();
296 accept_AND_expression()
298 accept_equality_expression();
299 parse_AND_expression();
304 accept_equality_expression()
306 accept_relational_expression();
307 parse_equality_expression();
312 accept_relational_expression()
314 accept_additive_expression();
315 parse_relational_expression();
320 accept_additive_expression()
322 accept_multiplicative_expression();
323 parse_additive_expression();
328 accept_multiplicative_expression()
330 parse_unary_expression(); /* - things */
331 parse_multiplicative_expression(); /* * / % */
335 /* add action table entries for primary expressions, i.e. either a
336 * parenthesized expression, a variable names, a numeric constant, a
337 * function evaluation, a power operator or postfix '!' (factorial)
340 parse_primary_expression()
342 if (equals(c_token, "(")) {
345 if (!equals(c_token, ")"))
346 int_error(c_token, "')' expected");
348 } else if (equals(c_token, "$")) {
351 if (!isanumber(++c_token))
352 int_error(c_token, "Column number expected");
353 convert(&a, c_token++);
354 if (a.type != INTGR || a.v.int_val < 0)
355 int_error(c_token, "Positive integer expected");
356 if (at_highest_column_used < a.v.int_val)
357 at_highest_column_used = a.v.int_val;
358 add_action(DOLLARS)->v_arg = a;
359 } else if (isanumber(c_token)) {
360 /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */
361 /* HBB 20010724: use this code for all platforms, then */
362 union argument *foo = add_action(PUSHC);
364 convert(&(foo->v_arg), c_token);
366 } else if (isletter(c_token)) {
367 /* Found an identifier --- check whether its a function or a
368 * variable by looking for the parentheses of a function
370 if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
371 enum operators whichfunc = is_builtin_function(c_token);
372 struct value num_params;
373 num_params.type = INTGR;
376 #ifdef BACKWARDS_COMPATIBLE
377 /* Deprecated syntax: if (defined(foo)) ... */
378 /* New syntax: if (exists("foo")) ... */
379 if (strcmp(ft[whichfunc].f_name,"defined")==0) {
380 struct udvt_entry *udv = add_udv(c_token+2);
381 union argument *foo = add_action(PUSHC);
382 foo->v_arg.type = INTGR;
383 foo->v_arg.v.int_val = udv->udv_undef ? 0 : 1;
384 c_token += 4; /* skip past "defined ( <foo> ) " */
388 c_token += 2; /* skip fnc name and '(' */
389 parse_expression(); /* parse fnc argument */
390 num_params.v.int_val = 1;
391 while (equals(c_token, ",")) {
393 num_params.v.int_val++;
397 if (!equals(c_token, ")"))
398 int_error(c_token, "')' expected");
401 #ifdef GP_STRING_VARS
402 /* So far sprintf is the only built-in function */
403 /* with a variable number of arguments. */
404 if (!strcmp(ft[whichfunc].f_name,"sprintf"))
405 add_action(PUSHC)->v_arg = num_params;
406 /* And "words(s)" is implemented as "word(s,-1)" */
407 if (!strcmp(ft[whichfunc].f_name,"words")) {
408 num_params.v.int_val = -1;
409 add_action(PUSHC)->v_arg = num_params;
412 (void) add_action(whichfunc);
415 /* it's a call to a user-defined function */
416 enum operators call_type = (int) CALL;
419 c_token += 2; /* skip func name and '(' */
421 if (equals(c_token, ",")) { /* more than 1 argument? */
422 num_params.v.int_val = 1;
423 while (equals(c_token, ",")) {
424 num_params.v.int_val += 1;
428 add_action(PUSHC)->v_arg = num_params;
429 call_type = (int) CALLN;
431 if (!equals(c_token, ")"))
432 int_error(c_token, "')' expected");
434 add_action(call_type)->udf_arg = add_udf(tok);
436 /* dummy_func==NULL is a flag to say no dummy variables active */
437 } else if (dummy_func) {
438 if (equals(c_token, c_dummy_var[0])) {
440 add_action(PUSHD1)->udf_arg = dummy_func;
441 } else if (equals(c_token, c_dummy_var[1])) {
443 add_action(PUSHD2)->udf_arg = dummy_func;
447 for (i = 2; i < MAX_NUM_VAR; i++) {
448 if (equals(c_token, c_dummy_var[i])) {
449 struct value num_params;
450 num_params.type = INTGR;
451 num_params.v.int_val = i;
454 add_action(PUSHC)->v_arg = num_params;
455 add_action(PUSHD)->udf_arg = dummy_func;
459 if (!param) { /* defined variable */
460 add_action(PUSH)->udv_arg = add_udv(c_token);
464 /* its a variable, with no dummies active - div */
466 add_action(PUSH)->udv_arg = add_udv(c_token);
472 #ifdef GP_STRING_VARS
473 /* Maybe it's a string constant */
474 else if (isstring(c_token)) {
475 union argument *foo = add_action(PUSHC);
476 foo->v_arg.type = STRING;
477 foo->v_arg.v.string_val = NULL;
478 /* this dynamically allocated string will be freed by free_at() */
479 m_quote_capture(&(foo->v_arg.v.string_val), c_token, c_token);
485 int_error(c_token, "invalid expression ");
487 /* add action code for ! (factorial) operator */
488 while (equals(c_token, "!")) {
490 (void) add_action(FACTORIAL);
492 /* add action code for ** operator */
493 if (equals(c_token, "**")) {
495 parse_unary_expression();
496 (void) add_action(POWER);
498 #ifdef GP_STRING_VARS
499 /* Parse and add actions for range specifier applying to previous entity.
500 * Currently only used to generate substrings, but could also be used to
501 * extract vector slices.
503 if (equals(c_token, "[")) {
504 /* handle '*' or empty start of range */
505 if (equals(++c_token,"*") || equals(c_token,":")) {
506 union argument *empty = add_action(PUSHC);
507 empty->v_arg.type = INTGR;
508 empty->v_arg.v.int_val = 1;
509 if (equals(c_token,"*"))
513 if (!equals(c_token, ":"))
514 int_error(c_token, "':' expected");
515 /* handle '*' or empty end of range */
516 if (equals(++c_token,"*") || equals(c_token,"]")) {
517 union argument *empty = add_action(PUSHC);
518 empty->v_arg.type = INTGR;
519 empty->v_arg.v.int_val = 65535; /* should be MAXINT */
520 if (equals(c_token,"*"))
524 if (!equals(c_token, "]"))
525 int_error(c_token, "']' expected");
527 (void) add_action(RANGE);
533 /* HBB 20010309: Here and below: can't store pointers into the middle
534 * of at->actions[]. That array may be realloc()ed by add_action() or
535 * express() calls!. Access via index savepc1/savepc2, instead. */
538 parse_conditional_expression()
540 /* create action code for ? : expressions */
542 if (equals(c_token, "?")) {
543 int savepc1, savepc2;
545 /* Fake same recursion level for alternatives
546 * set xlabel a>b ? 'foo' : 'bar' -1, 1
547 * FIXME: This won't work:
548 * set xlabel a-b>c ? 'foo' : 'bar' offset -1, 1
550 parse_recursion_level--;
553 savepc1 = at->a_count;
556 if (!equals(c_token, ":"))
557 int_error(c_token, "expecting ':'");
560 savepc2 = at->a_count;
562 at->actions[savepc1].arg.j_arg = at->a_count - savepc1;
564 at->actions[savepc2].arg.j_arg = at->a_count - savepc2;
565 parse_recursion_level++;
571 parse_logical_OR_expression()
573 /* create action codes for || operator */
575 while (equals(c_token, "||")) {
579 savepc = at->a_count;
580 add_action(JUMPNZ); /* short-circuit if already TRUE */
581 accept_logical_AND_expression();
582 /* offset for jump */
583 at->actions[savepc].arg.j_arg = at->a_count - savepc;
584 (void) add_action(BOOLE);
590 parse_logical_AND_expression()
592 /* create action code for && operator */
594 while (equals(c_token, "&&")) {
598 savepc = at->a_count;
599 add_action(JUMPZ); /* short-circuit if already FALSE */
600 accept_inclusive_OR_expression();
601 at->actions[savepc].arg.j_arg = at->a_count - savepc; /* offset for jump */
602 (void) add_action(BOOLE);
608 parse_inclusive_OR_expression()
610 /* create action code for | operator */
612 while (equals(c_token, "|")) {
614 accept_exclusive_OR_expression();
615 (void) add_action(BOR);
621 parse_exclusive_OR_expression()
623 /* create action code for ^ operator */
625 while (equals(c_token, "^")) {
627 accept_AND_expression();
628 (void) add_action(XOR);
634 parse_AND_expression()
636 /* create action code for & operator */
638 while (equals(c_token, "&")) {
640 accept_equality_expression();
641 (void) add_action(BAND);
647 parse_equality_expression()
649 /* create action codes for == and != numeric operators
650 * eq and ne string operators */
653 if (equals(c_token, "==")) {
655 accept_relational_expression();
656 (void) add_action(EQ);
657 } else if (equals(c_token, "!=")) {
659 accept_relational_expression();
660 (void) add_action(NE);
661 #ifdef GP_STRING_VARS
662 } else if (equals(c_token, "eq")) {
664 accept_relational_expression();
665 (void) add_action(EQS);
666 } else if (equals(c_token, "ne")) {
668 accept_relational_expression();
669 (void) add_action(NES);
678 parse_relational_expression()
680 /* create action code for < > >= or <=
684 /* I hate "else if" statements */
685 if (equals(c_token, ">")) {
687 accept_additive_expression();
688 (void) add_action(GT);
689 } else if (equals(c_token, "<")) {
691 accept_additive_expression();
692 (void) add_action(LT);
693 } else if (equals(c_token, ">=")) {
695 accept_additive_expression();
696 (void) add_action(GE);
697 } else if (equals(c_token, "<=")) {
699 accept_additive_expression();
700 (void) add_action(LE);
710 parse_additive_expression()
712 /* create action codes for +, - and . operators */
714 #ifdef GP_STRING_VARS
715 if (equals(c_token, ".")) {
717 accept_multiplicative_expression();
718 (void) add_action(CONCATENATE);
719 /* If only string results are wanted
720 * do not accept '-' or '+' at the top level. */
721 } else if (string_result_only && parse_recursion_level == 1)
725 if (equals(c_token, "+")) {
727 accept_multiplicative_expression();
728 (void) add_action(PLUS);
729 } else if (equals(c_token, "-")) {
731 accept_multiplicative_expression();
732 (void) add_action(MINUS);
740 parse_multiplicative_expression()
742 /* add action code for * / and % operators */
745 if (equals(c_token, "*")) {
747 parse_unary_expression();
748 (void) add_action(MULT);
749 } else if (equals(c_token, "/")) {
751 parse_unary_expression();
752 (void) add_action(DIV);
753 } else if (equals(c_token, "%")) {
755 parse_unary_expression();
756 (void) add_action(MOD);
764 parse_unary_expression()
766 /* add code for unary operators */
768 if (equals(c_token, "!")) {
770 parse_unary_expression();
771 (void) add_action(LNOT);
772 } else if (equals(c_token, "~")) {
774 parse_unary_expression();
775 (void) add_action(BNOT);
776 } else if (equals(c_token, "-")) {
778 parse_unary_expression();
779 (void) add_action(UMINUS);
780 } else if (equals(c_token, "+")) { /* unary + is no-op */
782 parse_unary_expression();
784 parse_primary_expression();
787 /* find or add value and return pointer */
791 char varname[MAX_ID_LEN+1];
792 copy_str(varname, t_num, MAX_ID_LEN);
793 return add_udv_by_name(varname);
797 /* find or add function at index <t_num>, and return pointer */
801 struct udft_entry **udf_ptr = &first_udf;
805 if (equals(t_num, (*udf_ptr)->udf_name))
807 udf_ptr = &((*udf_ptr)->next_udf);
810 /* get here => not found. udf_ptr points at first_udf or
811 * next_udf field of last udf
814 if (is_builtin_function(t_num))
815 int_warn(t_num, "Warning : udf shadowed by built-in function of the same name");
817 /* create and return a new udf slot */
819 *udf_ptr = (struct udft_entry *)
820 gp_alloc(sizeof(struct udft_entry), "function");
821 (*udf_ptr)->next_udf = (struct udft_entry *) NULL;
822 (*udf_ptr)->definition = NULL;
823 (*udf_ptr)->at = NULL;
824 (*udf_ptr)->udf_name = gp_alloc (token_len(t_num)+1, "user func");
825 copy_str((*udf_ptr)->udf_name, t_num, token_len(t_num)+1);
826 for (i = 0; i < MAX_NUM_VAR; i++)
827 (void) Ginteger(&((*udf_ptr)->dummy_values[i]), 0);
831 /* return standard function index or 0 */
833 is_builtin_function(int t_num)
837 for (i = (int) SF_START; ft[i].f_name != NULL; i++) {
838 if (equals(t_num, ft[i].f_name))
847 struct udvt_entry *udv_ptr = first_udv;
848 struct udvt_entry *udv_dead;
850 while (udv_ptr->next_udv) {
851 if (udv_ptr->next_udv->udv_undef) {
852 udv_dead = udv_ptr->next_udv;
853 udv_ptr->next_udv = udv_dead->next_udv;
854 FPRINTF((stderr,"cleanup_udvlist: deleting %s\n",udv_dead->udv_name));
855 free(udv_dead->udv_name);
858 udv_ptr = udv_ptr->next_udv;