return result;
}
-#define MAX(a,b) ((a) < (b) ? (b) : (a))
-
/* Record STR if input recording is enabled. */
void
grub_script_lexer_record (struct grub_parser_param *parser, char *str)
if (lexer->recordpos + len + 1 > lexer->recordlen)
{
old = lexer->recording;
- lexer->recordlen = MAX (len, lexer->recordlen) * 2;
+ lexer->recordlen = grub_max (len, lexer->recordlen) * 2;
lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
if (!lexer->recording)
{
lexer->recordpos += len;
}
-/* Append '\n' to SRC, before '\0' */
-static char *
-append_newline (const char *src)
-{
- char *line;
- grub_size_t len;
-
- len = grub_strlen (src);
- line = grub_malloc (len + 2);
- if (!line)
- return 0;
-
- grub_strcpy (line, src);
-
- line[len] = '\n';
- line[len + 1] = '\0';
- return line;
-}
-
/* Read next line of input if necessary, and set yyscanner buffers. */
int
-grub_script_lexer_yywrap (struct grub_parser_param *parserstate)
+grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
+ const char *input)
{
int len;
- char *line;
- char *line2;
+ char *p = 0;
+ char *line = 0;
YY_BUFFER_STATE buffer;
struct grub_lexer_param *lexerstate = parserstate->lexerstate;
- if (!lexerstate->refs)
- return 0;
+ if (! lexerstate->refs && ! lexerstate->prefix && ! input)
+ return 1;
- if (!lexerstate->getline)
+ if (! lexerstate->getline && ! input)
{
grub_script_yyerror (parserstate, "unexpected end of file");
- return 0;
+ return 1;
}
line = 0;
- buffer = 0;
- lexerstate->getline (&line, 1);
- if (!line)
+ if (! input)
+ lexerstate->getline (&line, 1);
+ else
+ line = grub_strdup (input);
+ if (! line)
{
- grub_script_yyerror (parserstate, 0); /* XXX this could be for ^C case? */
- return 0;
+ grub_script_yyerror (parserstate, 0);
+ return 1;
}
len = grub_strlen (line);
- if (line[len - 1] == '\n')
+ if (lexerstate->prefix)
{
- buffer = yy_scan_string (line, lexerstate->yyscanner);
+ int plen = grub_strlen (lexerstate->prefix);
+
+ p = grub_malloc (len + plen + 2);
+ if (! p)
+ {
+ grub_free (line);
+ return 1;
+ }
+ grub_strcpy (p, lexerstate->prefix);
+ lexerstate->prefix = 0;
+
+ if (! line[0])
+ {
+ line = "\n";
+ len = 1;
+ }
+ grub_strcpy (p + plen, line);
+
+ line = p;
+ len = len + plen;
}
- else
+
+ if (line[len - 1] != '\n')
{
- line2 = append_newline (line);
- if (line2)
+ char *p;
+ p = grub_realloc (line, len + 2);
+ if (! p)
{
- buffer = yy_scan_string (line2, lexerstate->yyscanner);
- grub_free (line2);
+ grub_free (line);
+ return 1;
}
+ line = p;
+ line[len++] = '\n';
+ line[len] = '\0';
}
+ buffer = yy_scan_string (line, lexerstate->yyscanner);
grub_free (line);
- if (!buffer)
+
+ if (! buffer)
{
grub_script_yyerror (parserstate, 0);
- return 0;
+ return 1;
}
-
- return 1;
+ return 0;
}
struct grub_lexer_param *
grub_free (lexerstate);
return 0;
}
+ yyset_extra (parser, lexerstate->yyscanner);
+ parser->lexerstate = lexerstate;
- buffer = 0;
- script = script ? : "\n";
- len = grub_strlen (script);
-
- if (script[len - 1] == '\n')
- {
- buffer = yy_scan_string (script, lexerstate->yyscanner);
- }
- else
- {
- script2 = append_newline (script);
- if (script2)
- {
- buffer = yy_scan_string (script2, lexerstate->yyscanner);
- grub_free (script2);
- }
- }
-
- if (!buffer)
+ if (grub_script_lexer_yywrap (parser, script ?: "\n"))
{
+ parser->lexerstate = 0;
yylex_destroy (lexerstate->yyscanner);
grub_free (lexerstate->yyscanner);
-
grub_free (lexerstate->text);
grub_free (lexerstate);
return 0;
}
- yyset_extra (parser, lexerstate->yyscanner);
return lexerstate;
}
#define YY_INPUT(buf,res,max) do { res = 0; } while (0)
/* forward declarations */
-static int resplit (const char *input, yyscan_t yyscanner);
+static int grub_lexer_unput (const char *input, yyscan_t yyscanner);
+static int grub_lexer_resplit (const char *input, yyscan_t yyscanner);
+
static void grub_lexer_yyfree (void *, yyscan_t yyscanner);
static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner);
static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner);
%option never-interactive
%option noyyfree noyyalloc noyyrealloc
-%option nounistd nostdinit nodefault noyylineno noyywrap
+%option nounistd nostdinit nodefault noyylineno
/* Reduce lexer size, by not defining these. */
-%option noyy_top_state
%option noinput nounput
%option noyyget_in noyyset_in
%option noyyget_out noyyset_out
NAME [[:alpha:]_][[:alnum:][:digit:]_]*
ESC \\.
+SQCHR [^\']
+DQCHR {ESC}|[^\"]
+DQSTR \"{DQCHR}*\"
+SQSTR \'{SQCHR}*\'
VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\}
-DQSTR \"([^\"]|{ESC})*\"
-SQSTR \'([^\'])*\'
WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
-DQSTR2 {WORD}?\"({ESC}|[^\"])*\n
-SQSTR2 {WORD}?\'({ESC}|[^\'])*\n
+MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*))
%x SPLIT
%x DQUOTE
%x SQUOTE
%x VAR
-%x DQMULTILINE
-%x SQMULTILINE
%%
{NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; }
{WORD} {
RECORD;
+ yyextra->lexerstate->resplit = 1;
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
- if (resplit (yytext, yyscanner))
- {
- yypop_buffer_state (yyscanner);
- return GRUB_PARSER_TOKEN_WORD;
- }
- }
-{DQSTR2} {
- yy_push_state (DQMULTILINE, yyscanner);
- grub_script_lexer_ref (yyextra->lexerstate);
- yymore ();
- }
-<DQMULTILINE>{
- \"{WORD}? {
- RECORD;
- grub_script_lexer_deref (yyextra->lexerstate);
- yy_pop_state (yyscanner);
- yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
- if (resplit (yytext, yyscanner))
+ if (grub_lexer_resplit (yytext, yyscanner))
{
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
}
- {ESC} { yymore(); }
- [^\"] { yymore(); }
-}
-
-{SQSTR2} {
- yy_push_state (SQMULTILINE, yyscanner);
- grub_script_lexer_ref (yyextra->lexerstate);
- yymore ();
- }
-
-<SQMULTILINE>{
- \'{WORD}? {
- RECORD;
- grub_script_lexer_deref (yyextra->lexerstate);
- yy_pop_state (yyscanner);
- yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
- if (resplit (yytext, yyscanner))
- {
- yypop_buffer_state (yyscanner);
- return GRUB_PARSER_TOKEN_WORD;
- }
+{MULTILINE} {
+ if (grub_lexer_unput (yytext, yyscanner))
+ return GRUB_PARSER_TOKEN_BAD;
+ }
+. {
+ grub_script_yyerror (yyextra, yytext);
+ return GRUB_PARSER_TOKEN_BAD;
}
- {ESC} { yymore(); }
- [^\'] { yymore(); }
-}
/* Split word into multiple args */
<<EOF>> {
yy_pop_state (yyscanner);
yypop_buffer_state (yyscanner);
+ yyextra->lexerstate->resplit = 0;
yyextra->lexerstate->merge_end = 1;
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
}
(.|\n) { COPY (yytext, yyleng); }
}
-. { /* ignore */ }
<<EOF>> {
yypop_buffer_state (yyscanner);
- if (! grub_script_lexer_yywrap (yyextra))
- {
- yyextra->lexerstate->eof = 1;
- return GRUB_PARSER_TOKEN_EOF;
- }
+ yyextra->lexerstate->eof = 1;
+ return GRUB_PARSER_TOKEN_EOF;
}
%%
-#if 0
int
yywrap (yyscan_t yyscanner)
{
- char *line = 0;
- struct grub_lexer_param *lexerstate = yyget_extra(yyscanner)->lexerstate;
+ if (yyget_extra (yyscanner)->lexerstate->resplit)
+ return 1;
- grub_printf ("yywrap\n");
- if (lexerstate->getline)
- {
- lexerstate->getline (&line, 1);
- if (! line)
- return 1;
-
- yy_scan_string (line, yyscanner);
- return 0;
- }
- return 1;
+ return grub_script_lexer_yywrap (yyget_extra (yyscanner), 0);
}
-#endif
static void
grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused)))
}
static int
-resplit (const char *text, yyscan_t yyscanner)
+grub_lexer_resplit (const char *text, yyscan_t yyscanner)
{
/* resplit text */
if (yy_scan_string (text, yyscanner))
grub_script_yyerror (yyget_extra (yyscanner), 0);
return 1;
}
+
+static int
+grub_lexer_unput (const char *text, yyscan_t yyscanner)
+{
+ struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate;
+
+ if (lexerstate->prefix)
+ {
+ grub_free (lexerstate->prefix);
+ lexerstate->prefix = 0;
+ }
+
+ lexerstate->prefix = grub_strdup (text);
+ if (! lexerstate->prefix)
+ {
+ grub_script_yyerror (yyget_extra (yyscanner), "out of memory");
+ return 1;
+ }
+ return 0;
+}