Ejemplo n.º 1
0
/*
 * f_range() handles both explicit calls to substr(string, beg, end)
 * and the short form string[beg:end].  The calls to gp_strlen() and
 * gp_strchrn() allow it to handle utf8 strings.
 */
void
f_range(union argument *arg)
{
    struct value beg, end, full;
    struct value substr;

    (void) arg;			/* avoid -Wunused warning */
    (void) pop(&end);
    (void) pop(&beg);
    (void) pop(&full);

    if (end.type != INTGR || beg.type != INTGR)
	int_error(NO_CARET, "internal error: substring range specifiers must have integer values");

    if (full.type != STRING)
	int_error(NO_CARET, "internal error: substring range operator applied to non-STRING type");

    FPRINTF((stderr,"f_range( \"%s\", %d, %d)\n", full.v.string_val, beg.v.int_val, end.v.int_val));

    if (end.v.int_val > gp_strlen(full.v.string_val))
	end.v.int_val = gp_strlen(full.v.string_val);
    if (beg.v.int_val < 1)
	beg.v.int_val = 1;

    if (beg.v.int_val > end.v.int_val) {
	push(Gstring(&substr, ""));
    } else {
	char *begp = gp_strchrn(full.v.string_val,beg.v.int_val-1);
	char *endp = gp_strchrn(full.v.string_val,end.v.int_val);
	*endp = '\0';
	push(Gstring(&substr, begp));
    }
    gpfree_string(&full);
}
Ejemplo n.º 2
0
void
f_concatenate(union argument *arg)
{
    struct value a, b, result;

    (void) arg;			/* avoid -Wunused warning */
    (void) pop(&b);
    (void) pop(&a);

    if (b.type == INTGR) {
	int i = b.v.int_val;
	b.type = STRING;
	b.v.string_val = (char *)gp_alloc(32,"str_const");
#ifdef HAVE_SNPRINTF
	snprintf(b.v.string_val,32,"%d",i);
#else
	sprintf(b.v.string_val,"%d",i);
#endif
    }

    if (a.type != STRING || b.type != STRING)
	int_error(NO_CARET, "internal error : STRING operator applied to non-STRING type");

    (void) Gstring(&result, gp_stradd(a.v.string_val, b.v.string_val));
    gpfree_string(&a);
    gpfree_string(&b);
    push(&result);
    gpfree_string(&result); /* free string allocated within gp_stradd() */
}
Ejemplo n.º 3
0
/* execute a system call and return stream from STDOUT */
void
f_system(union argument *arg)
{
    struct value val, result;
    struct udvt_entry *errno_var;
    char *output;
    int output_len, ierr;

    /* Retrieve parameters from top of stack */
    pop(&val);

    /* Make sure parameters are of the correct type */
    if (val.type != STRING)
	int_error(NO_CARET, "non-string argument to system()");

    FPRINTF((stderr," f_system input = \"%s\"\n", val.v.string_val));

    ierr = do_system_func(val.v.string_val, &output);
    if ((errno_var = add_udv_by_name("ERRNO"))) {
	errno_var->udv_undef = FALSE;
	Ginteger(&errno_var->udv_value, ierr);
    }
    output_len = strlen(output);

    /* chomp result */
    if ( output_len > 0 && output[output_len-1] == '\n' )
	output[output_len-1] = NUL;

    FPRINTF((stderr," f_system result = \"%s\"\n", output));

    push(Gstring(&result, output));

    gpfree_string(&result); /* free output */
    gpfree_string(&val);    /* free command string */
}
Ejemplo n.º 4
0
/* Look for an iterate-over-plot construct, of the form
 *    {s}plot  for [<var> = <start> : <end> { : <increment>}] ...
 */
void
check_for_iteration()
{
    char *errormsg = "Expecting iterator \tfor [<var> = <start> : <end>]\n\t\t\tor\tfor [<var> in \"string of words\"]";

    iteration_udv = NULL;
    free(iteration_string);
    iteration_string = NULL;
    iteration_increment = 1;
    iteration = 0;

    if (!equals(c_token, "for"))
	return;

    c_token++;
    if (!equals(c_token++, "[") || !isletter(c_token))
	int_error(c_token-1, errormsg);
    iteration_udv = add_udv(c_token++);

    if (equals(c_token, "=")) {
	c_token++;
	iteration_start = int_expression();
	if (!equals(c_token++, ":"))
	    int_error(c_token-1, errormsg);
	iteration_end = int_expression();
	if (equals(c_token,":")) {
	    c_token++;
	    iteration_increment = int_expression();
	}
	if (!equals(c_token++, "]"))
	    int_error(c_token-1, errormsg);
	if (iteration_udv->udv_undef == FALSE)
	    gpfree_string(&iteration_udv->udv_value);
	Ginteger(&(iteration_udv->udv_value), iteration_start);
	iteration_udv->udv_undef = FALSE;
    }

    else if (equals(c_token++, "in")) {
	iteration_string = try_to_get_string();
	if (!iteration_string)
	    int_error(c_token-1, errormsg);
	if (!equals(c_token++, "]"))
	    int_error(c_token-1, errormsg);
	iteration_start = 1;
	iteration_end = gp_words(iteration_string);
	if (iteration_udv->udv_undef == FALSE)
	    gpfree_string(&iteration_udv->udv_value);
	Gstring(&(iteration_udv->udv_value), gp_word(iteration_string, 1));
	iteration_udv->udv_undef = FALSE;
    }

    else /* Neither [i=B:E] or [s in "foo"] */
 	int_error(c_token-1, errormsg);

    iteration_current = iteration_start;

}
Ejemplo n.º 5
0
void
f_words(union argument *arg)
{
    struct value a, b, result;
    int nwords = 0;
    int ntarget;
    char *s;

    (void) arg;
    if (pop(&b)->type != INTGR)
	int_error(NO_CARET, "internal error : non-INTGR argument");
    ntarget = b.v.int_val;

    if (pop(&a)->type != STRING)
	int_error(NO_CARET, "internal error : non-STRING argument");
    s = a.v.string_val;

    Gstring(&result, "");
    while (*s) {
	while (isspace(*s)) s++;
	if (!*s)
	    break;
	nwords++;
	if (nwords == ntarget) { /* Found the one we wanted */
	    Gstring(&result,s);
	    s = result.v.string_val;
	}
	while (*s && !isspace(*s)) s++;
	if (nwords == ntarget) { /* Terminate this word cleanly */
	    *s = '\0';
	    break;
	}
    }

    if (ntarget < 0)
	/* words(s) = word(s,-1) = # of words in string */
	Ginteger(&result, nwords);

    push(&result);
    gpfree_string(&a);
}
Ejemplo n.º 6
0
/* Output time given in seconds from year 2000 into string */
void
f_strftime(union argument *arg)
{
    struct value fmt, val;
    char *fmtstr, *buffer;
    int fmtlen, buflen, length;

    (void) arg; /* Avoid compiler warnings */

    /* Retrieve parameters from top of stack */
    pop(&val);
    pop(&fmt);
    if ( fmt.type != STRING )
	int_error(NO_CARET,
		  "First parameter to strftime must be a format string");

    /* Prepare format string.
     * Make sure the resulting string not empty by adding a space.
     * Otherwise, the return value of gstrftime doesn't give enough
     * information.
     */
    fmtlen = strlen(fmt.v.string_val) + 1;
    fmtstr = gp_alloc(fmtlen + 1, "f_strftime: fmt");
    strncpy(fmtstr, fmt.v.string_val, fmtlen);
    strncat(fmtstr, " ", fmtlen);
    buflen = 80 + 2*fmtlen;
    buffer = gp_alloc(buflen, "f_strftime: buffer");

    /* Get time_str */
    length = gstrftime(buffer, buflen, fmtstr, real(&val));
    if (length == 0 || length >= buflen)
	int_error(NO_CARET, "Resulting string is too long");

    /* Remove trailing space */
    assert(buffer[length-1] == ' ');
    buffer[length-1] = NUL;
    buffer = gp_realloc(buffer, strlen(buffer)+1, "f_strftime");
    FPRINTF((stderr," strftime result = \"%s\"\n",buffer));

    gpfree_string(&val);
    gpfree_string(&fmt);
    free(fmtstr);

    push(Gstring(&val, buffer));
}
Ejemplo n.º 7
0
/* EAM July 2004 - Gnuplot's own string formatting conventions.
 * Currently this routine assumes base 10 representation, because
 * it is not clear where it could be specified to be anything else.
 */
void
f_gprintf(union argument *arg)
{
    struct value fmt, val, result;
    char *buffer;
    int length;
    double base;
 
    /* Retrieve parameters from top of stack */
    pop(&val);
    pop(&fmt);

#ifdef DEBUG
    fprintf(stderr,"----------\nGot gprintf parameters\nfmt: ");
	disp_value(stderr, &fmt, TRUE);
    fprintf(stderr,"\nval: ");
	disp_value(stderr, &val, TRUE);
    fprintf(stderr,"\n----------\n");
#endif

    /* Make sure parameters are of the correct type */
    if (fmt.type != STRING)
	int_error(NO_CARET,"First parameter to gprintf must be a format string");

    /* EAM FIXME - I have no idea where we would learn another base is wanted */
    base = 10.;

    /* Make sure we have at least as much space in the output as the format itself */
    length = 80 + strlen(fmt.v.string_val);
    buffer = gp_alloc(length, "f_gprintf");

    /* Call the old internal routine */
    gprintf(buffer, length, fmt.v.string_val, base, real(&val));

    FPRINTF((stderr," gprintf result = \"%s\"\n",buffer));
    push(Gstring(&result, buffer));

    gpfree_string(&fmt);
    free(buffer);
}
Ejemplo n.º 8
0
/* EAM July 2004  (revised to dynamic buffer July 2005)
 * There are probably an infinite number of things that can
 * go wrong if the user mis-matches arguments and format strings
 * in the call to sprintf, but I hope none will do worse than
 * result in a garbage output string.
 */
void
f_sprintf(union argument *arg)
{
    struct value a[10], *args;
    struct value num_params;
    struct value result;
    char *buffer;
    int bufsize;
    char *next_start, *outpos, tempchar;
    int next_length;
    char *prev_start;
    int prev_pos;
    int i, remaining;
    int nargs = 0;
    enum DATA_TYPES spec_type;

    /* Retrieve number of parameters from top of stack */
    pop(&num_params);
    nargs = num_params.v.int_val;
    if (nargs > 10) {	/* Fall back to slow but sure allocation */
	args = gp_alloc(sizeof(struct value)*nargs, "sprintf args");
    } else
	args = a;

    for (i=0; i<nargs; i++)
	pop(&args[i]);  /* pop next argument */

    /* Make sure we got a format string of some sort */
    if (args[nargs-1].type != STRING)
	int_error(NO_CARET,"First parameter to sprintf must be a format string");

    /* Allocate space for the output string. If this isn't */
    /* long enough we can reallocate a larger space later. */
    bufsize = 80 + strlen(args[nargs-1].v.string_val);
    buffer = gp_alloc(bufsize, "f_sprintf");

    /* Copy leading fragment of format into output buffer */
    outpos = buffer;
    next_start  = args[nargs-1].v.string_val;
    next_length = strcspn(next_start,"%");
    strncpy(outpos, next_start, next_length);

    next_start += next_length;
    outpos += next_length;

    /* Format the remaining sprintf() parameters one by one */
    prev_start = next_start;
    prev_pos = next_length;
    remaining = nargs - 1;

    /* If the user has set an explicit LC_NUMERIC locale, apply it */
    /* to sprintf calls during expression evaluation.              */
    set_numeric_locale();

    /* Each time we start this loop we are pointing to a % character */
    while (remaining-->0 && next_start[0] && next_start[1]) {
	struct value *next_param = &args[remaining];

	/* Check for %%; print as literal and don't consume a parameter */
	if (!strncmp(next_start,"%%",2)) {
	    next_start++;
	    do {
		*outpos++ = *next_start++;
	    } while(*next_start && *next_start != '%');
	    remaining++;
	    continue;
	}

	next_length = strcspn(next_start+1,"%") + 1;
	tempchar = next_start[next_length];
	next_start[next_length] = '\0';

	spec_type = sprintf_specifier(next_start);

	/* string value <-> numerical value check */
	if ( spec_type == STRING && next_param->type != STRING )
	    int_error(NO_CARET,"f_sprintf: attempt to print numeric value with string format");
	if ( spec_type != STRING && next_param->type == STRING )
	    int_error(NO_CARET,"f_sprintf: attempt to print string value with numeric format");

#ifdef HAVE_SNPRINTF
	/* Use the format to print next arg */
	switch(spec_type) {
	case INTGR:
	    snprintf(outpos,bufsize-(outpos-buffer),
		     next_start, (int)real(next_param));
	    break;
	case CMPLX:
	    snprintf(outpos,bufsize-(outpos-buffer),
		     next_start, real(next_param));
	    break;
	case STRING:
	    snprintf(outpos,bufsize-(outpos-buffer),
		next_start, next_param->v.string_val);
	    break;
	default:
	    int_error(NO_CARET,"internal error: invalid spec_type");
	}
#else
	/* FIXME - this is bad; we should dummy up an snprintf equivalent */
	switch(spec_type) {
	case INTGR:
	    sprintf(outpos, next_start, (int)real(next_param));
	    break;
	case CMPLX:
	    sprintf(outpos, next_start, real(next_param));
	    break;
	case STRING:
	    sprintf(outpos, next_start, next_param->v.string_val);
	    break;
	default:
	    int_error(NO_CARET,"internal error: invalid spec_type");
	}
#endif

	next_start[next_length] = tempchar;
	next_start += next_length;
	outpos = &buffer[strlen(buffer)];

	/* Check whether previous parameter output hit the end of the buffer */
	/* If so, reallocate a larger buffer, go back and try it again.      */
	if (strlen(buffer) >= bufsize-2) {
	    bufsize *= 2;
	    buffer = gp_realloc(buffer, bufsize, "f_sprintf");
	    next_start = prev_start;
	    outpos = buffer + prev_pos;
	    remaining++;
	    continue;
	} else {
	    prev_start = next_start;
	    prev_pos = outpos - buffer;
	}

    }

    /* Copy the trailing portion of the format, if any */
    /* We could just call snprintf(), but it doesn't check for */
    /* whether there really are more variables to handle.      */
    i = bufsize - (outpos-buffer);
    while (*next_start && --i > 0) {
	if (*next_start == '%' && *(next_start+1) == '%')
	    next_start++;
	*outpos++ = *next_start++;
    }
    *outpos = '\0';

    FPRINTF((stderr," snprintf result = \"%s\"\n",buffer));
    push(Gstring(&result, buffer));
    free(buffer);

    /* Free any strings from parameters we have now used */
    for (i=0; i<nargs; i++)
	gpfree_string(&args[i]);

    if (args != a)
	free(args);

    /* Return to C locale for internal use */
    reset_numeric_locale();

}
Ejemplo n.º 9
0
Archivo: parse.c Proyecto: Reen/gnuplot
/* create action code for 'sum' expressions */
static void
parse_sum_expression()
{
    /* sum [<var>=<range>] <expr>
     * - Pass a udf to f_sum (with action code (for <expr>) that is not added
     *   to the global action table).
     * - f_sum uses a newly created udv (<var>) to pass the current value of
     *   <var> to <expr> (resp. its ac).
     * - The original idea was to treat <expr> as function f(<var>), but there
     *   was the following problem: Consider 'g(x) = sum [k=1:4] f(k)'. There
     *   are two dummy variables 'x' and 'k' from different functions 'g' and
     *   'f' which would require changing the parsing of dummy variables.
     */

    char *errormsg = "Expecting 'sum [<var> = <start>:<end>] <expression>'\n";
    char *varname = NULL;
    union argument *arg;
    struct udft_entry *udf;

    struct at_type * save_at;
    int save_at_size;
    int i;
    
    /* Caller already checked for string "sum [" so skip both tokens */
    c_token += 2;

    /* <var> */
    if (!isletter(c_token))
        int_error(c_token, errormsg);
    /* create a user defined variable and pass it to f_sum via PUSHC, since the
     * argument of f_sum is already used by the udf */
    m_capture(&varname, c_token, c_token);
    add_udv(c_token);
    arg = add_action(PUSHC);
    Gstring(&(arg->v_arg), varname);
    c_token++;

    if (!equals(c_token, "="))
        int_error(c_token, errormsg);
    c_token++;

    /* <start> */
    parse_expression();

    if (!equals(c_token, ":"))
        int_error(c_token, errormsg);
    c_token++;

    /* <end> */
    parse_expression();

    if (!equals(c_token, "]"))
        int_error(c_token, errormsg);
    c_token++;

    /* parse <expr> and convert it to a new action table. */
    /* modeled on code from temp_at(). */
    /* 1. save environment to restart parsing */
    save_at = at;
    save_at_size = at_size;
    at = NULL;

    /* 2. save action table in a user defined function */
    udf = (struct udft_entry *) gp_alloc(sizeof(struct udft_entry), "sum");
    udf->next_udf = (struct udft_entry *) NULL;
    udf->udf_name = NULL; /* TODO maybe add a name and definition */ 
    udf->at = perm_at();
    udf->definition = NULL;
    udf->dummy_num = 0;
    for (i = 0; i < MAX_NUM_VAR; i++)
        (void) Ginteger(&(udf->dummy_values[i]), 0);

    /* 3. restore environment */
    at = save_at;
    at_size = save_at_size;

    /* pass the udf to f_sum using the argument */
    add_action(SUM)->udf_arg = udf;
}
Ejemplo n.º 10
0
Archivo: parse.c Proyecto: Reen/gnuplot
/* Set up next iteration.
 * Return TRUE if there is one, FALSE if we're done
 */
TBOOLEAN
next_iteration(t_iterator *iter)
{
    t_iterator *this_iter;
    TBOOLEAN condition = FALSE;
    
    if (!iter || iter->empty_iteration)
	return FALSE;

    /* Support for nested iteration:
     * we start with the innermost loop. */
    this_iter = iter->prev; /* linked to the last element of the list */
    
    if (!this_iter)
	return FALSE;
    
    while (!iter->really_done && this_iter != iter && this_iter->done) {
	this_iter->iteration_current = this_iter->iteration_start;
	this_iter->done = FALSE;
	if (this_iter->iteration_string) {
	    gpfree_string(&(this_iter->iteration_udv->udv_value));
	    Gstring(&(this_iter->iteration_udv->udv_value), 
		    gp_word(this_iter->iteration_string, this_iter->iteration_current));
    } else
	    this_iter->iteration_udv->udv_value.v.int_val = this_iter->iteration_current;	
	
	this_iter = this_iter->prev;
    }
   
    if (!this_iter->iteration_udv) {
	this_iter->iteration = 0;
	return FALSE;
    }
    iter->iteration++;
    /* don't increment if we're at the last iteration */
    if (!iter->really_done)
	this_iter->iteration_current += this_iter->iteration_increment;
    if (this_iter->iteration_string) {
	gpfree_string(&(this_iter->iteration_udv->udv_value));
	Gstring(&(this_iter->iteration_udv->udv_value), 
		gp_word(this_iter->iteration_string, this_iter->iteration_current));
    } else
	this_iter->iteration_udv->udv_value.v.int_val = this_iter->iteration_current;
    
    /* Mar 2014 revised to avoid integer overflow */
    if (this_iter->iteration_increment > 0
    &&  this_iter->iteration_end - this_iter->iteration_current < this_iter->iteration_increment)
	this_iter->done = TRUE;
    else if (this_iter->iteration_increment < 0
    &&  this_iter->iteration_end - this_iter->iteration_current > this_iter->iteration_increment)
	this_iter->done = TRUE;
    else
	this_iter->done = FALSE;
    
    /* We return false only if we're, um, really done */
    this_iter = iter;
    while (this_iter) {
	condition = condition || (!this_iter->done);
	this_iter = this_iter->next;
    }
    if (!condition) {
	if (!iter->really_done) {
	    iter->really_done = TRUE;
	    condition = TRUE;
	} else 
	    condition = FALSE;
    }
    return condition;
}
Ejemplo n.º 11
0
Archivo: parse.c Proyecto: Reen/gnuplot
/* Look for iterate-over-plot constructs, of the form
 *    for [<var> = <start> : <end> { : <increment>}] ...
 * If one (or more) is found, an iterator structure is allocated and filled
 * and a pointer to that structure is returned.
 * The pointer is NULL if no "for" statements are found.
 */
t_iterator *
check_for_iteration()
{
    char *errormsg = "Expecting iterator \tfor [<var> = <start> : <end> {: <incr>}]\n\t\t\tor\tfor [<var> in \"string of words\"]";
    int nesting_depth = 0;
    t_iterator *iter = NULL;
    t_iterator *this_iter = NULL;

    /* Now checking for iteration parameters */
    /* Nested "for" statements are supported, each one corresponds to a node of the linked list */
    while (equals(c_token, "for")) {
	struct udvt_entry *iteration_udv = NULL;
	char *iteration_string = NULL;
	int iteration_start;
	int iteration_end;
	int iteration_increment = 1;
	int iteration_current;
	int iteration = 0;
	TBOOLEAN empty_iteration;
	TBOOLEAN just_once = FALSE;

	c_token++;
	if (!equals(c_token++, "[") || !isletter(c_token))
	    int_error(c_token-1, errormsg);
	iteration_udv = add_udv(c_token++);

	if (equals(c_token, "=")) {
	    c_token++;
	    iteration_start = int_expression();
	    if (!equals(c_token++, ":"))
	    	int_error(c_token-1, errormsg);
	    iteration_end = int_expression();
	    if (equals(c_token,":")) {
	    	c_token++;
	    	iteration_increment = int_expression();
		if (iteration_increment == 0)
		    int_error(c_token-1, errormsg);
	    }
	    if (!equals(c_token++, "]"))
	    	int_error(c_token-1, errormsg);
	    if (iteration_udv->udv_undef == FALSE)
		gpfree_string(&(iteration_udv->udv_value));
	    Ginteger(&(iteration_udv->udv_value), iteration_start);
	    iteration_udv->udv_undef = FALSE;
	}
	else if (equals(c_token++, "in")) {
	    iteration_string = try_to_get_string();
	    if (!iteration_string)
	    	int_error(c_token-1, errormsg);
	    if (!equals(c_token++, "]"))
	    	int_error(c_token-1, errormsg);
	    iteration_start = 1;
	    iteration_end = gp_words(iteration_string);
	    if (iteration_udv->udv_undef == FALSE)
	    	gpfree_string(&(iteration_udv->udv_value));
	    Gstring(&(iteration_udv->udv_value), gp_word(iteration_string, 1));
	    iteration_udv->udv_undef = FALSE;
	}
	else /* Neither [i=B:E] or [s in "foo"] */
	    int_error(c_token-1, errormsg);

	iteration_current = iteration_start;

	empty_iteration = FALSE;	
	if ( (iteration_udv != NULL)
	&&   ((iteration_end > iteration_start && iteration_increment < 0)
	   || (iteration_end < iteration_start && iteration_increment > 0))) {
		empty_iteration = TRUE;
		FPRINTF((stderr,"Empty iteration\n"));
	}

	/* Allocating a node of the linked list nested iterations. */
	/* Iterating just once is the same as not iterating at all */
	/* so we skip building the node in that case.		   */
	if (iteration_start == iteration_end)
	    just_once = TRUE;
	if (iteration_start < iteration_end && iteration_end < iteration_start + iteration_increment)
	    just_once = TRUE;
	if (iteration_start > iteration_end && iteration_end > iteration_start + iteration_increment)
	    just_once = TRUE;

	if (!just_once) {
	    this_iter = gp_alloc(sizeof(t_iterator), "iteration linked list");
	    this_iter->iteration_udv = iteration_udv; 
	    this_iter->iteration_string = iteration_string;
	    this_iter->iteration_start = iteration_start;
	    this_iter->iteration_end = iteration_end;
	    this_iter->iteration_increment = iteration_increment;
	    this_iter->iteration_current = iteration_current;
	    this_iter->iteration = iteration;
	    this_iter->done = FALSE;
	    this_iter->really_done = FALSE;
	    this_iter->empty_iteration = empty_iteration;
	    this_iter->next = NULL;
	    this_iter->prev = NULL;
	    if (nesting_depth == 0) {
		/* first "for" statement: this will be the listhead */
		iter = this_iter;
	    }
	    else {
		/* not the first "for" statement: attach the newly created node to the end of the list */
		iter->prev->next = this_iter;  /* iter->prev points to the last node of the list */
		this_iter->prev = iter->prev;
	    }
	    iter->prev = this_iter; /* a shortcut: making the list circular */

	    /* if one iteration in the chain is empty, the subchain of nested iterations is too */
	    if (!iter->empty_iteration) 
		iter->empty_iteration = empty_iteration;

	    nesting_depth++;
	}
    }

    return iter;
}
Ejemplo n.º 12
0
/* pop from load_file state stack
   FALSE if stack was empty
   called by load_file and load_file_error */
TBOOLEAN
lf_pop()
{
    LFS *lf;
    int argindex;
    struct udvt_entry *udv;

    if (lf_head == NULL)
	return (FALSE);

    lf = lf_head;
    if (lf->fp == NULL || lf->fp == stdin)
	/* Do not close stdin in the case that "-" is named as a load file */
	;
#if defined(PIPES)
    else if (lf->name != NULL && lf->name[0] == '<')
	pclose(lf->fp);
#endif
    else
	fclose(lf->fp);

    /* call arguments are not relevant when invoked from do_string_and_free */
    if (lf->cmdline == NULL) {
	for (argindex = 0; argindex < 10; argindex++) {
	    if (call_args[argindex])
		free(call_args[argindex]);
	    call_args[argindex] = lf->call_args[argindex];
	}
	call_argc = lf->call_argc;

	/* Restore ARGC and ARG0 ... ARG9 */
	if ((udv = get_udv_by_name("ARGC"))) {
	    Ginteger(&(udv->udv_value), call_argc);
	}
	if ((udv = get_udv_by_name("ARG0"))) {
	    gpfree_string(&(udv->udv_value));
	    Gstring(&(udv->udv_value),
		(lf->prev && lf->prev->name) ? gp_strdup(lf->prev->name) : gp_strdup(""));
	}
	for (argindex = 1; argindex <= 9; argindex++) {
	    if ((udv = get_udv_by_name(argname[argindex]))) {
		gpfree_string(&(udv->udv_value));
		Gstring(&(udv->udv_value), gp_strdup(call_args[argindex-1]));
		if (!call_args[argindex-1])
		    udv->udv_undef = TRUE;
	    }
	}
    }

    interactive = lf->interactive;
    inline_num = lf->inline_num;
    add_udv_by_name("GPVAL_LINENO")->udv_value.v.int_val = inline_num;
    if_depth = lf->if_depth;
    if_condition = lf->if_condition;
    if_open_for_else = lf->if_open_for_else;

    /* Restore saved input state and free the copy */
    if (lf->tokens) {
	num_tokens = lf->num_tokens;
	c_token = lf->c_token;
	assert(token_table_size >= lf->num_tokens+1);
	memcpy(token, lf->tokens,
	       (lf->num_tokens+1) * sizeof(struct lexical_unit));
	free(lf->tokens);
    }
    if (lf->input_line) {
	strcpy(gp_input_line, lf->input_line);
	free(lf->input_line);
    }
    free(lf->name);
    free(lf->cmdline);
    
    lf_head = lf->prev;
    free(lf);
    return (TRUE);
}
Ejemplo n.º 13
0
static void
prepare_call(int calltype)
{
    struct udvt_entry *udv;
    int argindex;
    if (calltype == 2) {
	call_argc = 0;
	while (!END_OF_COMMAND && call_argc <= 9) {
	    call_args[call_argc] = try_to_get_string();
	    if (!call_args[call_argc]) {
		int save_token = c_token;

		/* This catches call "file" STRINGVAR (expression) */
		if (type_udv(c_token) == STRING) {
		    call_args[call_argc] = gp_strdup(add_udv(c_token)->udv_value.v.string_val);
		    c_token++;

		/* Evaluates a parenthesized expression and store the result in a string */
		} else if (equals(c_token, "(")) {
		    char val_as_string[32];
		    struct value a;
		    const_express(&a);
		    switch(a.type) {
			case CMPLX: /* FIXME: More precision? Some way to provide a format? */
				sprintf(val_as_string, "%g", a.v.cmplx_val.real);
				call_args[call_argc] = gp_strdup(val_as_string);
				break;
			default:
				int_error(save_token, "Unrecognized argument type");
				break;
			case INTGR:	
				sprintf(val_as_string, "%d", a.v.int_val);
				call_args[call_argc] = gp_strdup(val_as_string);
				break;
		    } 

		/* old (pre version 5) style wrapping of bare tokens as strings */
		/* is still useful for passing unquoted numbers */
		} else {
		    m_capture(&call_args[call_argc], c_token, c_token);
		    c_token++;
		}
	    }
	    call_argc++;
	}
	lf_head->c_token = c_token;
	if (!END_OF_COMMAND)
	    int_error(++c_token, "too many arguments for 'call <file>'");

    } else if (calltype == 5) {
	/* lf_push() moved our call arguments from call_args[] to lf->call_args[] */
	/* call_argc was determined at program entry */
	for (argindex = 0; argindex < 10; argindex++) {
	    call_args[argindex] = lf_head->call_args[argindex];
	    lf_head->call_args[argindex] = NULL;	/* just to be safe */
	}

    } else {
	/* "load" command has no arguments */
	call_argc = 0;
    }

    /* Old-style "call" arguments were referenced as $0 ... $9 and $# */
    /* New-style has ARG0 = script-name, ARG1 ... ARG9 and ARGC */
    /* FIXME:  If we defined these on entry, we could use get_udv* here */
    udv = add_udv_by_name("ARGC");
    Ginteger(&(udv->udv_value), call_argc);
    udv->udv_undef = FALSE;
    udv = add_udv_by_name("ARG0");
    gpfree_string(&(udv->udv_value));
    Gstring(&(udv->udv_value), gp_strdup(lf_head->name));
    udv->udv_undef = FALSE;
    for (argindex = 1; argindex <= 9; argindex++) {
	char *arg = gp_strdup(call_args[argindex-1]);
	udv = add_udv_by_name(argname[argindex]);
	gpfree_string(&(udv->udv_value));
	Gstring(&(udv->udv_value), arg ? arg : gp_strdup(""));
	udv->udv_undef = FALSE;
    }
}