Example #1
0
void init_memory()
{
    extend_input_line();
    extend_token_table();
    replot_line = gp_alloc(1, "string");
    *replot_line = NUL;
}
Example #2
0
static void
init_memory()
{
    extend_input_line();
    extend_token_table();
    replot_line = gp_strdup("");
}
Example #3
0
/*
 * scanner() breaks expression[] into lexical units, storing them in token[].
 *   The total number of tokens found is returned as the function
 *   value.  Scanning will stop when '\0' is found in expression[], or
 *   when token[] is full.  extend_input_line() is called to extend
 *   expression array if needed.
 *
 *       Scanning is performed by following rules:
 *
 *      Current char    token should contain
 *     -------------    -----------------------
 *      1.  alpha,_     all following alpha-numerics
 *      2.  digit       0 or more following digits, 0 or 1 decimal point,
 *                              0 or more digits, 0 or 1 'e' or 'E',
 *                              0 or more digits.
 *      3.  ^,+,-,/     only current char
 *          %,~,(,)
 *          [,],;,:,
 *          ?,comma
 *          $           for using patch (div)
 *      4.  &,|,=,*     current char; also next if next is same
 *      5.  !,<,>       current char; also next if next is =
 *      6.  ", '        all chars up until matching quote
 *      7.  #           this token cuts off scanning of the line (DFK).
 *      8.  `           (command substitution: all characters through the
 *                      matching backtic are replaced by the output of
 *                      the contained command, then scanning is restarted.)
 * EAM Jan 2010:	Bugfix. No rule covered an initial period. This caused
 *			string concatenation to fail for variables whose first
 *			character is 'E' or 'e'.  Now we add a 9th rule:
 *	9.  .		A period may be a token by itself (string concatenation)
 *			or the start of a decimal number continuing with a digit
 *
 *                      white space between tokens is ignored
 */
int
scanner(char **expressionp, size_t *expressionlenp)
{
    int current;	/* index of current char in expression[] */
    char *expression = *expressionp;
    int quote;
    char brace;

    for (current = t_num = 0; expression[current] != NUL; current++) {
	if (t_num + 1 >= token_table_size) {
	    /* leave space for dummy end token */
	    extend_token_table();
	}
	if (isspace((unsigned char) expression[current]))
	    continue;		/* skip the whitespace */
	token[t_num].start_index = current;
	token[t_num].length = 1;
	token[t_num].is_token = TRUE;	/* to start with... */

	if (expression[current] == '`') {
	    substitute(expressionp, expressionlenp, current);
	    expression = *expressionp;	/* expression might have moved */
	    current--;
	    continue;
	}
	/* allow _ to be the first character of an identifier */
	if (isalpha((unsigned char) expression[current])
	    || expression[current] == '_') {
	    SCAN_IDENTIFIER;
	} else if (isdigit((unsigned char) expression[current])) {
	    token[t_num].is_token = FALSE;
	    token[t_num].length = get_num(&expression[current]);
	    current += (token[t_num].length - 1);

	} else if (expression[current] == '.') {
	    /* Rule 9 */
	    if (isdigit(expression[current+1])) {
		token[t_num].is_token = FALSE;
		token[t_num].length = get_num(&expression[current]);
		current += (token[t_num].length - 1);
	    } /* do nothing if the . is a token by itself */

	} else if (expression[current] == LBRACE) {
	    token[t_num].is_token = FALSE;
	    token[t_num].l_val.type = CMPLX;
#ifdef __PUREC__
	    {
		char l[80];
		if ((sscanf(&expression[++current], "%lf,%lf%[ }]s",
			    &token[t_num].l_val.v.cmplx_val.real,
			    &token[t_num].l_val.v.cmplx_val.imag,
			    &l) != 3) || (!strchr(l, RBRACE)))
		    int_error(t_num, "invalid complex constant");
	    }
#else
	    if ((sscanf(&expression[++current], "%lf , %lf %c",
			&token[t_num].l_val.v.cmplx_val.real,
			&token[t_num].l_val.v.cmplx_val.imag,
			&brace) != 3) || (brace != RBRACE))
		int_error(t_num, "invalid complex constant");
#endif
	    token[t_num].length += 2;
	    while (expression[++current] != RBRACE) {
		token[t_num].length++;
		if (expression[current] == NUL)		/* { for vi % */
		    int_error(t_num, "no matching '}'");
	    }
	} else if (expression[current] == '\'' ||
		   expression[current] == '\"') {
	    token[t_num].length++;
	    quote = expression[current];
	    while (expression[++current] != quote) {
		if (!expression[current]) {
		    expression[current] = quote;
		    expression[current + 1] = NUL;
		    break;
		} else if (quote == '\"'
                           && expression[current] == '\\'
			   && expression[current + 1]) {
		    current++;
		    token[t_num].length += 2;
		} else if (quote == '\"' && expression[current] == '`') {
		    substitute(expressionp, expressionlenp, current);
		    expression = *expressionp;	/* it might have moved */
		    current--;
                } else if (quote == '\'' 
                           && expression[current+1] == '\''
                           && expression[current+2] == '\'') {
                    /* look ahead: two subsequent single quotes 
                     * -> take them in
                     */
                    current += 2;
                    token[t_num].length += 3;
		} else
		    token[t_num].length++;
	    }
	} else
	    switch (expression[current]) {
	    case '#':		/* DFK: add comments to gnuplot */
		goto endline;	/* ignore the rest of the line */
	    case '^':
	    case '+':
	    case '-':
	    case '/':
	    case '%':
	    case '~':
	    case '(':
	    case ')':
	    case '[':
	    case ']':
	    case ';':
	    case ':':
	    case '?':
	    case ',':
	    case '$':		/* div */
		break;
	    case '&':
	    case '|':
	    case '=':
	    case '*':
		if (expression[current] == expression[current + 1])
		    APPEND_TOKEN;
		break;
	    case '!':
	    case '<':
	    case '>':
		if (expression[current + 1] == '=')
		    APPEND_TOKEN;
		break;
	    default:
		int_error(t_num, "invalid character %c",expression[current]);
	    }
	++t_num;		/* next token if not white space */
    }

  endline:			/* comments jump here to ignore line */

/* Now kludge an extra token which points to '\0' at end of expression[].
   This is useful so printerror() looks nice even if we've fallen off the
   line. */

    token[t_num].start_index = current;
    token[t_num].length = 0;
    /* print 3+4  then print 3+  is accepted without
     * this, since string is ignored if it is not
     * a token
     */
    token[t_num].is_token = TRUE;
    return (t_num);
}
Example #4
0
/*
 * scanner() breaks expression[] into lexical units, storing them in token[].
 *   The total number of tokens found is returned as the function
 *   value.  Scanning will stop when '\0' is found in expression[], or
 *   when token[] is full.  extend_input_line() is called to extend
 *   expression array if needed.
 *
 *       Scanning is performed by following rules:
 *
 *      Current char    token should contain
 *     -------------    -----------------------
 *      1.  alpha,_     all following alpha-numerics
 *      2.  digit       0 or more following digits, 0 or 1 decimal point,
 *                              0 or more digits, 0 or 1 'e' or 'E',
 *                              0 or more digits.
 *      3.  ^,+,-,/     only current char
 *          %,~,(,)
 *          [,],;,:,
 *          ?,comma
 *          $           
 *      4.  &,|,=,*     current char; also next if next is same
 *      5.  !,<,>       current char; also next if next is =
 *      6.  ", '        all chars up until matching quote
 *      7.  #           this token cuts off scanning of the line (DFK).
 *      8.  `           (command substitution: all characters through the
 *                      matching backtic are replaced by the output of
 *                      the contained command, then scanning is restarted.)
 * EAM Jan 2010:	Bugfix. No rule covered an initial period. This caused
 *			string concatenation to fail for variables whose first
 *			character is 'E' or 'e'.  Now we add a 9th rule:
 *	9.  .		A period may be a token by itself (string concatenation)
 *			or the start of a decimal number continuing with a digit
 *
 *                      white space between tokens is ignored
 */
int
scanner(char **expressionp, size_t *expressionlenp)
{
    int current;	/* index of current char in expression[] */
    char *expression = *expressionp;
    int quote;
    char brace;

    curly_brace_count = 0;

    for (current = t_num = 0; expression[current] != NUL; current++) {
	if (t_num + 1 >= token_table_size) {
	    /* leave space for dummy end token */
	    extend_token_table();
	}
	if (isspace((unsigned char) expression[current]))
	    continue;		/* skip the whitespace */
	token[t_num].start_index = current;
	token[t_num].length = 1;
	token[t_num].is_token = TRUE;	/* to start with... */

	if (expression[current] == '`') {
	    substitute(expressionp, expressionlenp, current);
	    expression = *expressionp;	/* expression might have moved */
	    current--;
	    continue;
	}
	/* allow _ to be the first character of an identifier */
	/* allow 8bit characters in identifiers */
	if (isalpha((unsigned char)expression[current])
	    || (expression[current] == '_')
	    || ALLOWED_8BITVAR(expression[current])) {
		while (isident(expression[current + 1]))
		    APPEND_TOKEN;

	} else if (isdigit((unsigned char) expression[current])) {
	    token[t_num].is_token = FALSE;
	    token[t_num].length = get_num(&expression[current]);
	    current += (token[t_num].length - 1);

	} else if (expression[current] == '.') {
	    /* Rule 9 */
	    if (isdigit((unsigned char)expression[current+1])) {
		token[t_num].is_token = FALSE;
		token[t_num].length = get_num(&expression[current]);
		current += (token[t_num].length - 1);
	    } /* do nothing if the . is a token by itself */

	} else if (expression[current] == LBRACE) {
	    int partial;
	    token[t_num].is_token = FALSE;
	    token[t_num].l_val.type = CMPLX;
	    partial = sscanf(&expression[++current], "%lf , %lf %c",
			&token[t_num].l_val.v.cmplx_val.real,
			&token[t_num].l_val.v.cmplx_val.imag,
			&brace);

	    if (partial <= 0) {
		curly_brace_count++;
		token[t_num++].is_token = TRUE;
		current--;
		continue;
	    }

	    if (partial != 3 || brace != RBRACE)
		int_error(t_num, "invalid complex constant");

	    token[t_num].length += 2;
	    while (expression[++current] != RBRACE) {
		token[t_num].length++;
		if (expression[current] == NUL)		/* { for vi % */
		    int_error(t_num, "no matching '}'");
	    }
	} else if (expression[current] == '\'' ||
		   expression[current] == '\"') {
	    token[t_num].length++;
	    quote = expression[current];
	    while (expression[++current] != quote) {
		if (!expression[current]) {
		    expression[current] = quote;
		    expression[current + 1] = NUL;
		    break;
		} else if (quote == '\"'
                           && expression[current] == '\\'
			   && expression[current + 1]) {
		    current++;
		    token[t_num].length += 2;
		} else if (quote == '\"' && expression[current] == '`') {
		    substitute(expressionp, expressionlenp, current);
		    expression = *expressionp;	/* it might have moved */
		    current--;
                } else if (quote == '\'' 
                           && expression[current+1] == '\''
                           && expression[current+2] == '\'') {
                    /* look ahead: two subsequent single quotes 
                     * -> take them in
                     */
                    current += 2;
                    token[t_num].length += 3;
		} else
		    token[t_num].length++;
	    }
	} else
	    switch (expression[current]) {
	    case '#':
#ifdef OLD_STYLE_CALL_ARGS
		/* FIXME: This ugly exception handles the old-style syntatic  */
		/* entity $# (number of arguments in "call" statement), which */
		/* otherwise would be treated as introducing a comment.       */
		if ((t_num == 0) ||
		    (gp_input_line[token[t_num-1].start_index] != '$'))
#endif
			goto endline;	/* ignore the rest of the line */
	    case '^':
	    case '+':
	    case '-':
	    case '/':
	    case '%':
	    case '~':
	    case '(':
	    case ')':
	    case '[':
	    case ']':
	    case ';':
	    case ':':
	    case '?':
	    case ',':
	    case '$':
		break;
	    case '}':		/* complex constants will not end up here */
		curly_brace_count--;
		break;
	    case '&':
	    case '|':
	    case '=':
	    case '*':
		if (expression[current] == expression[current + 1])
		    APPEND_TOKEN;
		break;
	    case '!':
	    case '>':
		if (expression[current + 1] == '=')
		    APPEND_TOKEN;
		if (expression[current + 1] == '>')
		    APPEND_TOKEN;
		break;
	    case '<':
		if (expression[current + 1] == '=')
		    APPEND_TOKEN;
		if (expression[current + 1] == '<')
		    APPEND_TOKEN;
		break;
	    default:
		int_error(t_num, "invalid character %c",expression[current]);
	    }
	++t_num;		/* next token if not white space */
    }

  endline:			/* comments jump here to ignore line */

/* Now kludge an extra token which points to '\0' at end of expression[].
   This is useful so printerror() looks nice even if we've fallen off the
   line. */

    token[t_num].start_index = current;
    token[t_num].length = 0;
    /* print 3+4  then print 3+  is accepted without
     * this, since string is ignored if it is not
     * a token
     */
    token[t_num].is_token = TRUE;
    return (t_num);
}