static void prepare_call(void) { call_argc = 0; /* Gnuplot "call" command can have up to 10 arguments "$0" to "$9" */ while (!END_OF_COMMAND && call_argc <= 9) { if (isstring(c_token)) m_quote_capture(&call_args[call_argc++], c_token, c_token); else m_capture(&call_args[call_argc++], c_token, c_token); c_token++; } if (!END_OF_COMMAND) int_error(++c_token, "too many arguments for 'call <file>'"); }
/* add action table entries for primary expressions, i.e. either a * parenthesized expression, a variable name, a numeric constant, a * function evaluation, a power operator or postfix '!' (factorial) * expression */ static void parse_primary_expression() { if (equals(c_token, "(")) { c_token++; parse_expression(); /* Expressions may be separated by a comma */ while (equals(c_token,",")) { c_token++; (void) add_action(POP); parse_expression(); } if (!equals(c_token, ")")) int_error(c_token, "')' expected"); c_token++; } else if (equals(c_token, "$")) { struct value a; c_token++; if (equals(c_token,"N")) { /* $N == pseudocolumn -3 means "last column" */ c_token++; Ginteger(&a, -3); at_highest_column_used = -3; } else if (!isanumber(c_token)) { int_error(c_token, "Column number expected"); } else { convert(&a, c_token++); if (a.type != INTGR || a.v.int_val < 0) int_error(c_token, "Positive integer expected"); if (at_highest_column_used < a.v.int_val) at_highest_column_used = a.v.int_val; } add_action(DOLLARS)->v_arg = a; } else if (isanumber(c_token)) { /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */ /* HBB 20010724: use this code for all platforms, then */ union argument *foo = add_action(PUSHC); convert(&(foo->v_arg), c_token); c_token++; } else if (isletter(c_token)) { /* Found an identifier --- check whether its a function or a * variable by looking for the parentheses of a function * argument list */ if (equals(c_token + 1, "(")) { enum operators whichfunc = is_builtin_function(c_token); struct value num_params; num_params.type = INTGR; #if (1) /* DEPRECATED */ if (whichfunc && (strcmp(ft[whichfunc].f_name,"defined")==0)) { /* Deprecated syntax: if (defined(foo)) ... */ /* New syntax: if (exists("foo")) ... */ struct udvt_entry *udv = add_udv(c_token+2); union argument *foo = add_action(PUSHC); foo->v_arg.type = INTGR; foo->v_arg.v.int_val = udv->udv_undef ? 0 : 1; c_token += 4; /* skip past "defined ( <foo> ) " */ return; } #endif if (whichfunc) { c_token += 2; /* skip fnc name and '(' */ parse_expression(); /* parse fnc argument */ num_params.v.int_val = 1; while (equals(c_token, ",")) { c_token++; num_params.v.int_val++; parse_expression(); } if (!equals(c_token, ")")) int_error(c_token, "')' expected"); c_token++; /* So far sprintf is the only built-in function */ /* with a variable number of arguments. */ if (!strcmp(ft[whichfunc].f_name,"sprintf")) add_action(PUSHC)->v_arg = num_params; /* The column() function has side effects requiring special handling */ if (!strcmp(ft[whichfunc].f_name,"column")) { set_up_columnheader_parsing( &(at->actions[at->a_count-1]) ); } (void) add_action(whichfunc); } else { /* it's a call to a user-defined function */ enum operators call_type = (int) CALL; int tok = c_token; c_token += 2; /* skip func name and '(' */ parse_expression(); if (equals(c_token, ",")) { /* more than 1 argument? */ num_params.v.int_val = 1; while (equals(c_token, ",")) { num_params.v.int_val += 1; c_token += 1; parse_expression(); } add_action(PUSHC)->v_arg = num_params; call_type = (int) CALLN; } if (!equals(c_token, ")")) int_error(c_token, "')' expected"); c_token++; add_action(call_type)->udf_arg = add_udf(tok); } } else if (equals(c_token, "sum") && equals(c_token+1, "[")) { parse_sum_expression(); /* dummy_func==NULL is a flag to say no dummy variables active */ } else if (dummy_func) { if (equals(c_token, c_dummy_var[0])) { c_token++; add_action(PUSHD1)->udf_arg = dummy_func; fit_dummy_var[0]++; } else if (equals(c_token, c_dummy_var[1])) { c_token++; add_action(PUSHD2)->udf_arg = dummy_func; fit_dummy_var[1]++; } else { int i, param = 0; for (i = 2; i < MAX_NUM_VAR; i++) { if (equals(c_token, c_dummy_var[i])) { struct value num_params; num_params.type = INTGR; num_params.v.int_val = i; param = 1; c_token++; add_action(PUSHC)->v_arg = num_params; add_action(PUSHD)->udf_arg = dummy_func; fit_dummy_var[i]++; break; } } if (!param) { /* defined variable */ add_action(PUSH)->udv_arg = add_udv(c_token); c_token++; } } /* its a variable, with no dummies active - div */ } else { add_action(PUSH)->udv_arg = add_udv(c_token); c_token++; } } /* end if letter */ /* Maybe it's a string constant */ else if (isstring(c_token)) { union argument *foo = add_action(PUSHC); foo->v_arg.type = STRING; foo->v_arg.v.string_val = NULL; /* this dynamically allocated string will be freed by free_at() */ m_quote_capture(&(foo->v_arg.v.string_val), c_token, c_token); c_token++; } else int_error(c_token, "invalid expression "); /* add action code for ! (factorial) operator */ while (equals(c_token, "!")) { c_token++; (void) add_action(FACTORIAL); } /* add action code for ** operator */ if (equals(c_token, "**")) { c_token++; parse_unary_expression(); (void) add_action(POWER); } /* Parse and add actions for range specifier applying to previous entity. * Currently only used to generate substrings, but could also be used to * extract vector slices. */ if (equals(c_token, "[") && !isanumber(c_token-1)) { /* handle '*' or empty start of range */ if (equals(++c_token,"*") || equals(c_token,":")) { union argument *empty = add_action(PUSHC); empty->v_arg.type = INTGR; empty->v_arg.v.int_val = 1; if (equals(c_token,"*")) c_token++; } else parse_expression(); if (!equals(c_token, ":")) int_error(c_token, "':' expected"); /* handle '*' or empty end of range */ if (equals(++c_token,"*") || equals(c_token,"]")) { union argument *empty = add_action(PUSHC); empty->v_arg.type = INTGR; empty->v_arg.v.int_val = 65535; /* should be INT_MAX */ if (equals(c_token,"*")) c_token++; } else parse_expression(); if (!equals(c_token, "]")) int_error(c_token, "']' expected"); c_token++; (void) add_action(RANGE); } }
void load_file(FILE *fp, char *name, TBOOLEAN can_do_args) { int len; int start, left; int more; int stop = FALSE; lf_push(fp); /* save state for errors and recursion */ do_load_arg_substitution = can_do_args; if (fp == (FILE *) NULL) { os_error(c_token, "Cannot open %s file '%s'", can_do_args ? "call" : "load", name); } else if (fp == stdin) { /* DBT 10-6-98 go interactive if "-" named as load file */ interactive = TRUE; while (!com_line()); } else { /* go into non-interactive mode during load */ /* will be undone below, or in load_file_error */ int argc = 0; /* number arguments passed by "call" */ interactive = FALSE; inline_num = 0; lf_head->name = name; if (can_do_args) { /* Gnuplot "call" command can have up to 10 arguments "$0" to "$9" */ while (!END_OF_COMMAND && argc <= 9) { if (isstring(c_token)) m_quote_capture(&call_args[argc++], c_token, c_token); else m_capture(&call_args[argc++], c_token, c_token); c_token++; } if (!END_OF_COMMAND) int_error(++c_token, "too many arguments for 'call <file>'"); } /* These were initialized to NULL in lf_push(); will be freed in lf_pop() */ lf_head->c_token = c_token; lf_head->num_tokens = num_tokens; lf_head->tokens = gp_alloc(num_tokens * sizeof(struct lexical_unit), "lf tokens"); memcpy(lf_head->tokens, token, num_tokens * sizeof(struct lexical_unit)); lf_head->input_line = gp_strdup(gp_input_line); while (!stop) { /* read all commands in file */ /* read one command */ left = gp_input_line_len; start = 0; more = TRUE; while (more) { if (fgets(&(gp_input_line[start]), left, fp) == (char *) NULL) { stop = TRUE; /* EOF in file */ gp_input_line[start] = '\0'; more = FALSE; } else { inline_num++; len = strlen(gp_input_line) - 1; if (gp_input_line[len] == '\n') { /* remove any newline */ gp_input_line[len] = '\0'; /* Look, len was 1-1 = 0 before, take care here! */ if (len > 0) --len; if (gp_input_line[len] == '\r') { /* remove any carriage return */ gp_input_line[len] = NUL; if (len > 0) --len; } } else if (len + 2 >= left) { extend_input_line(); left = gp_input_line_len - len - 1; start = len + 1; continue; /* don't check for '\' */ } if (gp_input_line[len] == '\\') { /* line continuation */ start = len; left = gp_input_line_len - start; } else more = FALSE; } } if (strlen(gp_input_line) > 0) { if (can_do_args) { int il = 0; char *rl; char *raw_line = gp_strdup(gp_input_line); rl = raw_line; *gp_input_line = '\0'; while (*rl) { int aix; if (*rl == '$' && ((aix = *(++rl)) != 0) /* HBB 980308: quiet BCC warning */ && ((aix >= '0' && aix <= '9') || aix == '#')) { if (aix == '#') { /* replace $# by number of passed arguments */ len = argc < 10 ? 1 : 2; /* argc can be 0 .. 10 */ while (gp_input_line_len - il < len + 1) { extend_input_line(); } sprintf(gp_input_line + il, "%i", argc); il += len; } else if (call_args[aix -= '0']) { /* replace $n for n=0..9 by the passed argument */ len = strlen(call_args[aix]); while (gp_input_line_len - il < len + 1) { extend_input_line(); } strcpy(gp_input_line + il, call_args[aix]); il += len; } } else { /* substitute for $<n> here */ if (il + 1 > gp_input_line_len) { extend_input_line(); } gp_input_line[il++] = *rl; } rl++; } if (il + 1 > gp_input_line_len) { extend_input_line(); } gp_input_line[il] = '\0'; free(raw_line); } screen_ok = FALSE; /* make sure command line is echoed on error */ if (do_line()) stop = TRUE; } } } /* pop state */ (void) lf_pop(); /* also closes file fp */ }