void init_memory() { extend_input_line(); extend_token_table(); replot_line = gp_alloc(1, "string"); *replot_line = NUL; }
static void init_memory() { extend_input_line(); extend_token_table(); replot_line = gp_strdup(""); }
/* * 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); }
/* * 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); }