]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2006-17-04 Marco Gerards <marco@gnu.org>
authormarco_g <marco_g@localhost>
Mon, 17 Apr 2006 13:01:20 +0000 (13:01 +0000)
committermarco_g <marco_g@localhost>
Mon, 17 Apr 2006 13:01:20 +0000 (13:01 +0000)
* include/grub/script.h: Include <grub/parser.h> and
"grub_script.tab.h".
(struct grub_lexer_param): New struct.
(struct grub_parser_param): Likewise.
(grub_script_create_arglist): Pass the state in an argument.
(grub_script_add_arglist): Likewise.
(grub_script_create_cmdline): Likewise.
(grub_script_create_cmdblock): Likewise.
(grub_script_create_cmdif): Likewise.
(grub_script_create_cmdmenu): Likewise.
(grub_script_add_cmd): Likewise.
(grub_script_arg_add): Likewise.
(grub_script_lexer_ref): Likewise.
(grub_script_lexer_deref): Likewise.
(grub_script_lexer_record_start): Likewise.
(grub_script_lexer_record_stop): Likewise.
(grub_script_mem_record): Likewise.
(grub_script_mem_record_stop): Likewise.
(grub_script_malloc): Likewise.
(grub_script_yylex): Likewise.
(grub_script_yyparse): Likewise.
(grub_script_yyerror): Likewise.
(grub_script_yylex): Likewise.
(grub_script_lexer_init): Return the state.

* normal/lexer.c (grub_script_lexer_state): Removed variable.
(grub_script_lexer_done): Likewise.
(grub_script_lexer_getline): Likewise.
(grub_script_lexer_refs): Likewise.
(script): Likewise.
(newscript): Likewise.
(record): Likewise.
(recording): Likewise.
(recordpos): Likewise.
(recordlen): Likewise.
(grub_script_lexer_init): Return the state instead of setting
global variables.
(grub_script_lexer_ref): Use the newly added argument for state
instead of globals.
(grub_script_lexer_deref): Likewise.
(grub_script_lexer_record_start): Likewise.
(grub_script_lexer_record_stop): Likewise.
(recordchar): Likewise.
(nextchar): Likewise.
(grub_script_yylex2): Likewise.
(grub_script_yylex): Likewise.
(grub_script_yyerror): Likewise.

* normal/parser.y (func_mem): Removed variable.
(menu_entry): Likewise.
(err): Likewise.
(%lex-param): New parser option.
(%parse-param): Likewise.
(script): Always return the AST.
(argument): Pass the state around.
(arguments): Likewise.
(grubcmd): Likewise.
(commands): Likewise.
(function): Likewise.
(menuentry): Likewise.
(if_statement): Likewise.
(if): Likewise.

* normal/script.c (grub_script_memused): Removed variable.
(grub_script_parsed): Likewise.
(grub_script_malloc): Added a state argument.  Use that instead of
global variables.
(grub_script_mem_record): Likewise.
(grub_script_mem_record_stop): Likewise.
(grub_script_arg_add): Likewise.
(grub_script_add_arglist): Likewise.
(grub_script_create_cmdline): Likewise.
(grub_script_create_cmdif): Likewise.
(grub_script_create_cmdmenu): Likewise.
(grub_script_add_cmd): Likewise.
(grub_script_parse): Setup the state before calling the parser.

ChangeLog
include/grub/script.h
normal/lexer.c
normal/parser.y
normal/script.c

index 77bf877398d7412a12196e15d9fac6da9f4c81d6..3968b8dc42ab1f3f76755f85eca4def905ac8a40 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,82 @@
+2006-17-04  Marco Gerards  <marco@gnu.org>
+
+       * include/grub/script.h: Include <grub/parser.h> and
+       "grub_script.tab.h".
+       (struct grub_lexer_param): New struct.
+       (struct grub_parser_param): Likewise.
+       (grub_script_create_arglist): Pass the state in an argument.
+       (grub_script_add_arglist): Likewise.
+       (grub_script_create_cmdline): Likewise.
+       (grub_script_create_cmdblock): Likewise.
+       (grub_script_create_cmdif): Likewise.
+       (grub_script_create_cmdmenu): Likewise.
+       (grub_script_add_cmd): Likewise.
+       (grub_script_arg_add): Likewise.
+       (grub_script_lexer_ref): Likewise.
+       (grub_script_lexer_deref): Likewise.
+       (grub_script_lexer_record_start): Likewise.
+       (grub_script_lexer_record_stop): Likewise.
+       (grub_script_mem_record): Likewise.
+       (grub_script_mem_record_stop): Likewise.
+       (grub_script_malloc): Likewise.
+       (grub_script_yylex): Likewise.
+       (grub_script_yyparse): Likewise.
+       (grub_script_yyerror): Likewise.
+       (grub_script_yylex): Likewise.
+       (grub_script_lexer_init): Return the state.
+
+       * normal/lexer.c (grub_script_lexer_state): Removed variable.
+       (grub_script_lexer_done): Likewise.
+       (grub_script_lexer_getline): Likewise.
+       (grub_script_lexer_refs): Likewise.
+       (script): Likewise.
+       (newscript): Likewise.
+       (record): Likewise.
+       (recording): Likewise.
+       (recordpos): Likewise.
+       (recordlen): Likewise.
+       (grub_script_lexer_init): Return the state instead of setting
+       global variables.
+       (grub_script_lexer_ref): Use the newly added argument for state
+       instead of globals.
+       (grub_script_lexer_deref): Likewise.
+       (grub_script_lexer_record_start): Likewise.
+       (grub_script_lexer_record_stop): Likewise.
+       (recordchar): Likewise.
+       (nextchar): Likewise.
+       (grub_script_yylex2): Likewise.
+       (grub_script_yylex): Likewise.
+       (grub_script_yyerror): Likewise.
+
+       * normal/parser.y (func_mem): Removed variable.
+       (menu_entry): Likewise.
+       (err): Likewise.
+       (%lex-param): New parser option.
+       (%parse-param): Likewise.
+       (script): Always return the AST.
+       (argument): Pass the state around.
+       (arguments): Likewise.
+       (grubcmd): Likewise.
+       (commands): Likewise.
+       (function): Likewise.
+       (menuentry): Likewise.
+       (if_statement): Likewise.
+       (if): Likewise.
+
+       * normal/script.c (grub_script_memused): Removed variable.
+       (grub_script_parsed): Likewise.
+       (grub_script_malloc): Added a state argument.  Use that instead of
+       global variables.
+       (grub_script_mem_record): Likewise.
+       (grub_script_mem_record_stop): Likewise.
+       (grub_script_arg_add): Likewise.
+       (grub_script_add_arglist): Likewise.
+       (grub_script_create_cmdline): Likewise.
+       (grub_script_create_cmdif): Likewise.
+       (grub_script_create_cmdmenu): Likewise.
+       (grub_script_add_cmd): Likewise.
+       (grub_script_parse): Setup the state before calling the parser.
+       
 2006-16-04  Marco Gerards  <marco@gnu.org>
 
        * normal/command.c (grub_command_init): Remove the title command.
index 5108eee92f3bb93dd57a37faebc2a1b6dab424b0..661d0ee33555e4d11e7b020c8a43bec4ef62899d 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <grub/types.h>
 #include <grub/err.h>
+#include <grub/parser.h>
+#include "grub_script.tab.h"
 
 struct grub_script_mem;
 
@@ -123,33 +125,98 @@ struct grub_script_cmd_menuentry
   int options;
 };
 
+/* State of the lexer as passed to the lexer.  */
+struct grub_lexer_param
+{
+  /* Set to 0 when the lexer is done.  */
+  int done;
+
+  /* State of the state machine.  */
+  grub_parser_state_t state;
+
+  /* Function used by the lexer to get a new line when more input is
+     expected, but not available.  */
+  grub_err_t (*getline) (char **);
+
+  /* A reference counter.  If this is >0 it means that the parser
+     expects more tokens and `getline' should be called to fetch more.
+     Otherwise the lexer can stop processing if the current buffer is
+     depleted.  */
+  int refs;
+
+  /* The character stream that has to be parsed.  */
+  char *script;
+  char *newscript; /* XXX */
+
+  /* While walking through the databuffer, `record' the characters to
+     this other buffer.  It can be used to edit the menu entry at a
+     later moment.  */
+
+  /* If true, recording is enabled.  */
+  int record;
+
+  /* Points to the recording.  */
+  char *recording;
+
+  /* index in the RECORDING.  */ 
+  int recordpos;
+
+  /* Size of RECORDING.  */
+  int recordlen;
+};
+
+/* State of the parser as passes to the parser.  */
+struct grub_parser_param
+{
+  /* Keep track of the memory allocated for this specific
+     function.  */
+  struct grub_script_mem *func_mem;
+
+  /* When set to 0, no errors have occured during parsing.  */
+  int err;
+
+  /* The memory that was used while parsing and scanning.  */
+  struct grub_script_mem *memused;
+
+  /* The result of the parser.  */
+  struct grub_script_cmd *parsed;
+
+  struct grub_lexer_param *lexerstate;
+};
+
 struct grub_script_arglist *
-grub_script_create_arglist (void);
+grub_script_create_arglist (struct grub_parser_param *state);
 
 struct grub_script_arglist *
-grub_script_add_arglist (struct grub_script_arglist *list,
+grub_script_add_arglist (struct grub_parser_param *state,
+                        struct grub_script_arglist *list,
                         struct grub_script_arg *arg);
 struct grub_script_cmd *
-grub_script_create_cmdline (char *cmdname,
+grub_script_create_cmdline (struct grub_parser_param *state,
+                           char *cmdname,
                            struct grub_script_arglist *arglist);
 struct grub_script_cmd *
-grub_script_create_cmdblock (void);
+grub_script_create_cmdblock (struct grub_parser_param *state);
 
 struct grub_script_cmd *
-grub_script_create_cmdif (struct grub_script_cmd *bool,
+grub_script_create_cmdif (struct grub_parser_param *state,
+                         struct grub_script_cmd *bool,
                          struct grub_script_cmd *true,
                          struct grub_script_cmd *false);
 
 struct grub_script_cmd *
-grub_script_create_cmdmenu (struct grub_script_arg *title,
+grub_script_create_cmdmenu (struct grub_parser_param *state,
+                           struct grub_script_arg *title,
                            char *sourcecode,
                            int options);
 
 struct grub_script_cmd *
-grub_script_add_cmd (struct grub_script_cmdblock *cmdblock,
+grub_script_add_cmd (struct grub_parser_param *state,
+                    struct grub_script_cmdblock *cmdblock,
                     struct grub_script_cmd *cmd);
 struct grub_script_arg *
-grub_script_arg_add (struct grub_script_arg *arg,
+grub_script_arg_add (struct grub_parser_param *state,
+                    struct grub_script_arg *arg,
                     grub_script_arg_type_t type, char *str);
 
 struct grub_script *grub_script_parse (char *script,
@@ -158,21 +225,23 @@ void grub_script_free (struct grub_script *script);
 struct grub_script *grub_script_create (struct grub_script_cmd *cmd,
                                        struct grub_script_mem *mem);
 
-void grub_script_lexer_init (char *s, grub_err_t (*getline) (char **));
-void grub_script_lexer_ref (void);
-void grub_script_lexer_deref (void);
-void grub_script_lexer_record_start (void);
-char *grub_script_lexer_record_stop (void);
+struct grub_lexer_param *grub_script_lexer_init (char *s,
+                                                grub_err_t (*getline) (char **));
+void grub_script_lexer_ref (struct grub_lexer_param *);
+void grub_script_lexer_deref (struct grub_lexer_param *);
+void grub_script_lexer_record_start (struct grub_lexer_param *);
+char *grub_script_lexer_record_stop (struct grub_lexer_param *);
 
 /* Functions to track allocated memory.  */
-void *grub_script_malloc (grub_size_t size);
-struct grub_script_mem *grub_script_mem_record (void);
-struct grub_script_mem *grub_script_mem_record_stop (struct grub_script_mem *restore);
+struct grub_script_mem *grub_script_mem_record (struct grub_parser_param *state);
+struct grub_script_mem *grub_script_mem_record_stop (struct grub_parser_param *state, 
+                                                    struct grub_script_mem *restore);
+void *grub_script_malloc (struct grub_parser_param *state, grub_size_t size);
 
 /* Functions used by bison.  */
-int grub_script_yylex (void);
-int grub_script_yyparse (void);
-void grub_script_yyerror (char const *err);
+int grub_script_yylex (YYSTYPE *, struct grub_parser_param *);
+int grub_script_yyparse (struct grub_parser_param *);
+void grub_script_yyerror (struct grub_parser_param *, char const *);
 
 /* Commands to execute, don't use these directly.  */
 grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
index f23e5a300c57d1112d2de80c5c43adfd2a326a30..bb1bbc460523701b24825f4785491aa3ae0dbfb1 100644 (file)
 
 #include "grub_script.tab.h"
 
-static grub_parser_state_t grub_script_lexer_state;
-static int grub_script_lexer_done = 0;
-static grub_err_t (*grub_script_lexer_getline) (char **);
-
 static int
 check_varstate (grub_parser_state_t state)
 {
@@ -48,109 +44,109 @@ check_textstate (grub_parser_state_t state)
          || state == GRUB_PARSER_STATE_DQUOTE);
 }
 
-/* The amount of references to the lexer by the parser.  If the parser
-   expects tokens the lexer is referenced.  */
-static int grub_script_lexer_refs = 0;
-static char *script;
-static char *newscript;
+struct grub_lexer_param *
+grub_script_lexer_init (char *script, grub_err_t (*getline) (char **))
+{
+  struct grub_lexer_param *param;
 
-static int record = 0;
-static char *recording = 0;
-static int recordpos = 0;
-static int recordlen = 0;
+  param = grub_malloc (sizeof (*param));
+  if (! param)
+    return 0;
 
-/* XXX: The lexer is not reentrant.  */
-void
-grub_script_lexer_init (char *s, grub_err_t (*getline) (char **))
-{
-  grub_script_lexer_state = GRUB_PARSER_STATE_TEXT;
-  grub_script_lexer_getline = getline;
-  grub_script_lexer_refs = 0;
-  grub_script_lexer_done = 0;
-  newscript = 0;
-  script = s;
+  param->state = GRUB_PARSER_STATE_TEXT;
+  param->getline = getline;
+  param->refs = 0;
+  param->done = 0;
+  param->newscript = 0;
+  param->script = script;
+  param->record = 0;
+  param->recording = 0;
+  param->recordpos = 0;
+  param->recordlen = 0;
+
+  return param;
 }
 
 void
-grub_script_lexer_ref (void)
+grub_script_lexer_ref (struct grub_lexer_param *state)
 {
-  grub_script_lexer_refs++;
+  state->refs++;
 }
 
 void
-grub_script_lexer_deref (void)
+grub_script_lexer_deref (struct grub_lexer_param *state)
 {
-  grub_script_lexer_refs--;
+  state->refs--;
 }
 
 /* Start recording all characters passing through the lexer.  */
 void
-grub_script_lexer_record_start (void)
+grub_script_lexer_record_start (struct grub_lexer_param *state)
 {
-  record = 1;
-  recordlen = 100;
-  recording = grub_malloc (recordlen);
-  recordpos = 0;
+  state->record = 1;
+  state->recordlen = 100;
+  state->recording = grub_malloc (state->recordlen);
+  state->recordpos = 0;
 }
 
 char *
-grub_script_lexer_record_stop (void)
+grub_script_lexer_record_stop (struct grub_lexer_param *state)
 {
-  record = 0;
+  state->record = 0;
 
   /* Delete the last character, it is a `}'.  */
-  if (recordpos > 0)
+  if (state->recordpos > 0)
     {
-      if (recording[--recordpos] != '}')
+      if (state->recording[--state->recordpos] != '}')
        {
          grub_printf ("Internal error while parsing menu entry");
          for (;;); /* XXX */
        }
-      recording[recordpos] = '\0';
+      state->recording[state->recordpos] = '\0';
     }
 
-  return recording;
+  return state->recording;
 }
 
 /* When recording is enabled, record the character C as the next item
    in the character stream.  */
 static void
-recordchar (char c)
+recordchar (struct grub_lexer_param *state, char c)
 {
-  if (recordpos == recordlen)
+  if (state->recordpos == state->recordlen)
     {
-      char *old = recording;
-      recordlen += 100;
-      recording = grub_realloc (recording, recordlen);
-      if (! recording)
+      char *old = state->recording;
+      state->recordlen += 100;
+      state->recording = grub_realloc (state->recording, state->recordlen);
+      if (! state->recording)
        {
          grub_free (old);
-         record = 0;
+         state->record = 0;
        }
     }
-  recording[recordpos++] = c;
+  state->recording[state->recordpos++] = c;
 }
 
 /* Fetch the next character for the lexer.  */
 static void
-nextchar (void)
+nextchar (struct grub_lexer_param *state)
 {
-  if (record)
-    recordchar (*script);
-  script++;
+  if (state->record)
+    recordchar (state, *state->script);
+  state->script++;
 }
 
 int
-grub_script_yylex2 (void);
+grub_script_yylex2 (YYSTYPE *yylval, struct grub_parser_param *parsestate);
 
 int
-grub_script_yylex (void)
+grub_script_yylex (YYSTYPE *yylval, struct grub_parser_param *parsestate)
 {
   int r = -1;
 
   while (r == -1)
     {
-      r = grub_script_yylex2 ();
+      r = grub_script_yylex2 (yylval, parsestate);
       if (r == ' ' || r == '\n')
        r = -1;
     }
@@ -158,48 +154,49 @@ grub_script_yylex (void)
 }
 
 int
-grub_script_yylex2 (void)
+grub_script_yylex2 (YYSTYPE *yylval, struct grub_parser_param *parsestate)
 {
   grub_parser_state_t newstate;
   char use;
   char *buffer;
   char *bp;
+  struct grub_lexer_param *state = parsestate->lexerstate;
 
-  if (grub_script_lexer_done)
+  if (state->done)
     return 0;
 
-  if (! *script)
+  if (! *state->script)
     {
       /* Check if more tokens are requested by the parser.  */
-      if ((grub_script_lexer_refs
-          || grub_script_lexer_state == GRUB_PARSER_STATE_ESC)
-         && grub_script_lexer_getline)
+      if ((state->refs
+          || state->state == GRUB_PARSER_STATE_ESC)
+         && state->getline)
        {
-         while (!script || ! grub_strlen (script))
+         while (!state->script || ! grub_strlen (state->script))
            {
-             grub_free (newscript);
-             newscript = 0;
-             grub_script_lexer_getline (&newscript);
-             script = newscript;
-             if (! script)
+             grub_free (state->newscript);
+             state->newscript = 0;
+             state->getline (&state->newscript);
+             state->script = state->newscript;
+             if (! state->script)
                return 0;
            }
          grub_dprintf ("scripting", "token=`\\n'\n");
-         recordchar ('\n');
-         if (grub_script_lexer_state != GRUB_PARSER_STATE_ESC)
+         recordchar (state, '\n');
+         if (state->state != GRUB_PARSER_STATE_ESC)
            return '\n';
        }
       else
        {
-         grub_free (newscript);
-         newscript = 0;
-         grub_script_lexer_done = 1;
+         grub_free (state->newscript);
+         state->newscript = 0;
+         state->done = 1;
          grub_dprintf ("scripting", "token=`\\n'\n");
          return '\n';
        }
     }
 
-  newstate = grub_parser_cmdline_state (grub_script_lexer_state, *script, &use);
+  newstate = grub_parser_cmdline_state (state->state, *state->script, &use);
 
   /* Check if it is a text.  */
   if (check_textstate (newstate))
@@ -208,21 +205,21 @@ grub_script_yylex2 (void)
         length symbol.  */
       if (newstate == GRUB_PARSER_STATE_TEXT)
        {
-         switch (*script)
+         switch (*state->script)
            {
            case ' ':
-             while (*script)
+             while (*state->script)
                {
-                 newstate = grub_parser_cmdline_state (grub_script_lexer_state,
-                                                       *script, &use);
-                 if (! (grub_script_lexer_state == GRUB_PARSER_STATE_TEXT
-                        && *script == ' '))
+                 newstate = grub_parser_cmdline_state (state->state,
+                                                       *state->script, &use);
+                 if (! (state->state == GRUB_PARSER_STATE_TEXT
+                        && *state->script == ' '))
                    {
                      grub_dprintf ("scripting", "token=` '\n");
                      return ' ';
                    }
-                 grub_script_lexer_state = newstate;
-                 nextchar ();
+                 state->state = newstate;
+                 nextchar (state);
                }
              grub_dprintf ("scripting", "token=` '\n");
              return ' ';
@@ -232,26 +229,26 @@ grub_script_yylex2 (void)
            case '\n':
              {
                char c;
-               grub_dprintf ("scripting", "token=`%c'\n", *script);
-               c = *script;;
-               nextchar ();
+               grub_dprintf ("scripting", "token=`%c'\n", *state->script);
+               c = *state->script;;
+               nextchar (state);
                return c;
              }
            }
        }
 
       /* XXX: Use a better size.  */
-      buffer = grub_script_malloc (2048);
+      buffer = grub_script_malloc (parsestate, 2048);
       if (! buffer)
        return 0;
 
       bp = buffer;
 
       /* Read one token, possible quoted.  */
-      while (*script)
+      while (*state->script)
        {
-         newstate = grub_parser_cmdline_state (grub_script_lexer_state,
-                                               *script, &use);
+         newstate = grub_parser_cmdline_state (state->state,
+                                               *state->script, &use);
 
          /* Check if a variable name starts.  */
          if (check_varstate (newstate))
@@ -261,7 +258,7 @@ grub_script_yylex2 (void)
             when a special token was found.  It will be recognised
             next time when this function is called.  */
          if (newstate == GRUB_PARSER_STATE_TEXT
-             && grub_script_lexer_state != GRUB_PARSER_STATE_ESC)
+             && state->state != GRUB_PARSER_STATE_ESC)
            {
              int breakout = 0;
 
@@ -281,14 +278,14 @@ grub_script_yylex2 (void)
          else if (use)
            *(bp++) = use;
 
-         grub_script_lexer_state = newstate;
-         nextchar ();
+         state->state = newstate;
+         nextchar (state);
        }
 
       /* A string of text was read in.  */
       *bp = '\0';
       grub_dprintf ("scripting", "token=`%s'\n", buffer);
-      grub_script_yylval.string = buffer;
+      yylval->string = buffer;
 
       /* Detect some special tokens.  */
       if (! grub_strcmp (buffer, "while"))
@@ -314,38 +311,38 @@ grub_script_yylex2 (void)
           || newstate == GRUB_PARSER_STATE_QVAR)
     {
       /* XXX: Use a better size.  */
-      buffer = grub_script_malloc (2096);
+      buffer = grub_script_malloc (parsestate, 2096);
       if (! buffer)
        return 0;
 
       bp = buffer;
 
       /* This is a variable, read the variable name.  */
-      while (*script)
+      while (*state->script)
        {
-         newstate = grub_parser_cmdline_state (grub_script_lexer_state,
-                                               *script, &use);
+         newstate = grub_parser_cmdline_state (state->state,
+                                               *state->script, &use);
 
          /* Check if this character is not part of the variable name
             anymore.  */
          if (! (check_varstate (newstate)))
            {
-             if (grub_script_lexer_state == GRUB_PARSER_STATE_VARNAME2
-                 || grub_script_lexer_state == GRUB_PARSER_STATE_QVARNAME2)
-               nextchar ();
-             grub_script_lexer_state = newstate;
+             if (state->state == GRUB_PARSER_STATE_VARNAME2
+                 || state->state == GRUB_PARSER_STATE_QVARNAME2)
+               nextchar (state);
+             state->state = newstate;
              break;
            }
 
          if (use)
            *(bp++) = use;
-         nextchar ();
-         grub_script_lexer_state = newstate;
+         nextchar (state);
+         state->state = newstate;
        }
 
       *bp = '\0';
-      grub_script_lexer_state = newstate;
-      grub_script_yylval.string = buffer;
+      state->state = newstate;
+      yylval->string = buffer;
       grub_dprintf ("scripting", "vartoken=`%s'\n", buffer);
 
       return GRUB_PARSER_TOKEN_VAR;
@@ -360,7 +357,7 @@ grub_script_yylex2 (void)
 }
 
 void
-grub_script_yyerror (char const *err)
+grub_script_yyerror (struct grub_parser_param *lex, char const *err)
 {
   grub_printf ("%s\n", err);
 }
index 08aae76055d39365a26a681de6f94c5a5507c605..2c1fb0aa80cd07b26ed2de6b7133db5b23f89ce8 100644 (file)
 #define YYFREE         grub_free
 #define YYMALLOC       grub_malloc
 
-/* Keep track of the memory allocated for this specific function.  */
-static struct grub_script_mem *func_mem;
-
-static char *menu_entry;
-
-static int err;
 
 %}
 
@@ -56,11 +50,15 @@ static int err;
 %type <string> "if" "while" "function" "else" "then" "fi"
 %type <string> text GRUB_PARSER_TOKEN_NAME GRUB_PARSER_TOKEN_VAR
 
+%pure-parser
+%lex-param { struct grub_parser_param *state };
+%parse-param { struct grub_parser_param *state };
+
 %%
 /* It should be possible to do this in a clean way...  */
-script:                { err = 0} commands
+script:                { state->err = 0} commands
                  {
-                   grub_script_parsed = err ? 0 : $2;
+                   state->parsed = $2;
                  }
 ;
 
@@ -84,11 +82,11 @@ text:               GRUB_PARSER_TOKEN_NAME
    for example: `foo${bar}baz'.  */
 argument:      GRUB_PARSER_TOKEN_VAR
                  {
-                   $$ = grub_script_arg_add (0, GRUB_SCRIPT_ARG_TYPE_VAR, $1);
+                   $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_VAR, $1);
                  }
                | text
                  {
-                   $$ = grub_script_arg_add (0, GRUB_SCRIPT_ARG_TYPE_STR, $1);
+                   $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_STR, $1);
                  }
 /* XXX: Currently disabled to simplify the parser.  This should be
    parsed by yet another parser for readibility.  */
@@ -104,21 +102,21 @@ argument: GRUB_PARSER_TOKEN_VAR
 
 arguments:     argument
                  {
-                   $$ = grub_script_add_arglist (0, $1);
+                   $$ = grub_script_add_arglist (state, 0, $1);
                  }
                | arguments argument
                  {
-                   $$ = grub_script_add_arglist ($1, $2);
+                   $$ = grub_script_add_arglist (state, $1, $2);
                  }
 ;
 
 grubcmd:       GRUB_PARSER_TOKEN_NAME arguments
                  {
-                   $$ = grub_script_create_cmdline ($1, $2);
+                   $$ = grub_script_create_cmdline (state, $1, $2);
                  }
                | GRUB_PARSER_TOKEN_NAME
                  {
-                   $$ = grub_script_create_cmdline ($1, 0);
+                   $$ = grub_script_create_cmdline (state, $1, 0);
                  }
 ;
 
@@ -132,18 +130,18 @@ command:  grubcmd         { $$ = $1; }
 /* A block of commands.  */
 commands:      command
                  { 
-                   $$ = grub_script_add_cmd (0, $1);
+                   $$ = grub_script_add_cmd (state, 0, $1);
                  }
                | command ';' commands
                  { 
                    struct grub_script_cmdblock *cmd;
                    cmd = (struct grub_script_cmdblock *) $1;
-                   $$ = grub_script_add_cmd (cmd, $3);
+                   $$ = grub_script_add_cmd (state, cmd, $3);
                  }
                | error
                  {
-                   yyerror ("Incorrect command");
-                   err = 1;
+                   yyerror (state, "Incorrect command");
+                   state->err = 1;
                    yyerrok;
                  }
 ;
@@ -151,59 +149,61 @@ commands: command
 /* A function.  Carefully save the memory that is allocated.  */
 function:      "function" GRUB_PARSER_TOKEN_NAME
                  { 
-                   grub_script_lexer_ref ();
+                   grub_script_lexer_ref (state->lexerstate);
                  } '{'
                  { 
                    /* The first part of the function was recognised.
                       Now start recording the memory usage to store
                       this function.  */
-                   func_mem = grub_script_mem_record ();
+                   state->func_mem = grub_script_mem_record (state);
                  } commands '}'
                  {
                    struct grub_script *script;
 
                    /* All the memory usage for parsing this function
                       was recorded.  */
-                   func_mem = grub_script_mem_record_stop (func_mem);
-                   script = grub_script_create ($6, func_mem);
+                   state->func_mem = grub_script_mem_record_stop (state,
+                                                                  state->func_mem);
+                   script = grub_script_create ($6, state->func_mem);
                    if (script)
                      grub_script_function_create ($2, script);
-                   grub_script_lexer_deref ();
+                   grub_script_lexer_deref (state->lexerstate);
                  }
 ;
 
 /* A menu entry.  Carefully save the memory that is allocated.  */
 menuentry:     "menuentry" argument
                  { 
-                   grub_script_lexer_ref ();
+                   grub_script_lexer_ref (state->lexerstate);
                  } '{'
                  { 
                    /* Record sourcecode of the menu entry.  It can be
                       parsed multiple times if it is part of a
                       loop.  */
-                   grub_script_lexer_record_start ();
+                   grub_script_lexer_record_start (state->lexerstate);
                  } commands '}'
                  {
-                   menu_entry = grub_script_lexer_record_stop ();
-                   $$ = grub_script_create_cmdmenu ($2, menu_entry, 0);
-                   grub_script_lexer_deref ();
+                   char *menu_entry;
+                   menu_entry = grub_script_lexer_record_stop (state->lexerstate);
+                   $$ = grub_script_create_cmdmenu (state, $2, menu_entry, 0);
+                   grub_script_lexer_deref (state->lexerstate);
                  }
 ;
 
 /* The first part of the if statement.  It's used to switch the lexer
    to a state in which it demands more tokens.  */
-if_statement:  "if" { grub_script_lexer_ref (); }
+if_statement:  "if" { grub_script_lexer_ref (state->lexerstate); }
 ;
 
 /* The if statement.  */
 if:             if_statement grubcmd ';' "then" commands "fi"
                  {
-                   $$ = grub_script_create_cmdif ($2, $5, 0);
-                   grub_script_lexer_deref ();
+                   $$ = grub_script_create_cmdif (state, $2, $5, 0);
+                   grub_script_lexer_deref (state->lexerstate);
                  }
                 | if_statement grubcmd ';' "then" commands "else" commands  "fi"
                  {
-                   $$ = grub_script_create_cmdif ($2, $5, $7);
-                   grub_script_lexer_deref ();
+                   $$ = grub_script_create_cmdif (state, $2, $5, $7);
+                   grub_script_lexer_deref (state->lexerstate);
                  }
 ;
index d427994a73d5f3a5a4551a3fcff922c0e64ff352..e9b33ac51c7e1ea4cb0cd7835025ac6ca64d7d18 100644 (file)
    allocations.  The memory is free'ed in case of an error, or
    assigned to the parsed script when parsing was successful.  */
 
-/* The memory that was used while parsing and scanning.  */
-static struct grub_script_mem *grub_script_memused;
-
-/* The result of the parser.  */
-struct grub_script_cmd *grub_script_parsed = 0;
+/* XXX */
 
 /* In case of the normal malloc, some additional bytes are allocated
    for this datastructure.  All reserved memory is stored in a linked
@@ -46,15 +42,15 @@ struct grub_script_mem
 
 /* Return malloc'ed memory and keep track of the allocation.  */
 void *
-grub_script_malloc (grub_size_t size)
+grub_script_malloc (struct grub_parser_param *state, grub_size_t size)
 {
   struct grub_script_mem *mem;
   mem = (struct grub_script_mem *) grub_malloc (size + sizeof (*mem)
                                                - sizeof (char));
 
   grub_dprintf ("scripting", "malloc %p\n", mem);
-  mem->next = grub_script_memused;
-  grub_script_memused = mem;
+  mem->next = state->memused;
+  state->memused = mem;
   return (void *) &mem->mem;
 }
 
@@ -76,20 +72,22 @@ grub_script_mem_free (struct grub_script_mem *mem)
 /* Start recording memory usage.  Returns the memory that should be
    restored when calling stop.  */
 struct grub_script_mem *
-grub_script_mem_record (void)
+grub_script_mem_record (struct grub_parser_param *state)
 {
-  struct grub_script_mem *mem = grub_script_memused;
-  grub_script_memused = 0;
+  struct grub_script_mem *mem = state->memused;
+  state->memused = 0;
+
   return mem;
 }
 
 /* Stop recording memory usage.  Restore previous recordings using
    RESTORE.  Return the recorded memory.  */
 struct grub_script_mem *
-grub_script_mem_record_stop (struct grub_script_mem *restore)
+grub_script_mem_record_stop (struct grub_parser_param *state,
+                            struct grub_script_mem *restore)
 {
-  struct grub_script_mem *mem = grub_script_memused;
-  grub_script_memused = restore;
+  struct grub_script_mem *mem = state->memused;
+  state->memused = restore;
   return mem;
 }
 
@@ -108,13 +106,13 @@ grub_script_free (struct grub_script *script)
 /* Extend the argument arg with a variable or string of text.  If ARG
    is zero a new list is created.  */
 struct grub_script_arg *
-grub_script_arg_add (struct grub_script_arg *arg,
+grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *arg,
                     grub_script_arg_type_t type, char *str)
 {
   struct grub_script_arg *argpart;
   struct grub_script_arg *ll;
   
-  argpart = (struct grub_script_arg *) grub_script_malloc (sizeof (*arg));
+  argpart = (struct grub_script_arg *) grub_script_malloc (state, sizeof (*arg));
   argpart->type = type;
   argpart->str = str;
   argpart->next = 0;
@@ -131,14 +129,15 @@ grub_script_arg_add (struct grub_script_arg *arg,
 /* Add the argument ARG to the end of the argument list LIST.  If LIST
    is zero, a new list will be created.  */
 struct grub_script_arglist *
-grub_script_add_arglist (struct grub_script_arglist *list, struct grub_script_arg *arg)
+grub_script_add_arglist (struct grub_parser_param *state,
+                        struct grub_script_arglist *list, struct grub_script_arg *arg)
 {
   struct grub_script_arglist *link;
   struct grub_script_arglist *ll;
 
   grub_dprintf ("scripting", "arglist\n");
 
-  link = (struct grub_script_arglist *) grub_script_malloc (sizeof (*link));
+  link = (struct grub_script_arglist *) grub_script_malloc (state, sizeof (*link));
   link->next = 0;
   link->arg = arg;
   link->argcount = 0;
@@ -162,13 +161,14 @@ grub_script_add_arglist (struct grub_script_arglist *list, struct grub_script_ar
    contains the name of the command that should be executed.  ARGLIST
    holds all arguments for this command.  */
 struct grub_script_cmd *
-grub_script_create_cmdline (char *cmdname, struct grub_script_arglist *arglist)
+grub_script_create_cmdline (struct grub_parser_param *state,
+                           char *cmdname, struct grub_script_arglist *arglist)
 {
   struct grub_script_cmdline *cmd;
 
   grub_dprintf ("scripting", "cmdline\n");
 
-  cmd = grub_script_malloc (sizeof (*cmd));
+  cmd = grub_script_malloc (state, sizeof (*cmd));
   cmd->cmd.exec = grub_script_execute_cmdline;
   cmd->cmd.next = 0;
   cmd->arglist = arglist;
@@ -182,7 +182,8 @@ grub_script_create_cmdline (char *cmdname, struct grub_script_arglist *arglist)
    interpreter will run the command TRUE, otherwise the interpreter
    runs the command FALSE.  */
 struct grub_script_cmd *
-grub_script_create_cmdif (struct grub_script_cmd *bool,
+grub_script_create_cmdif (struct grub_parser_param *state,
+                         struct grub_script_cmd *bool,
                          struct grub_script_cmd *true,
                          struct grub_script_cmd *false)
 {
@@ -190,7 +191,7 @@ grub_script_create_cmdif (struct grub_script_cmd *bool,
 
   grub_dprintf ("scripting", "cmdif\n");
 
-  cmd = grub_script_malloc (sizeof (*cmd));
+  cmd = grub_script_malloc (state, sizeof (*cmd));
   cmd->cmd.exec = grub_script_execute_cmdif;
   cmd->cmd.next = 0;
   cmd->bool = bool;
@@ -205,7 +206,8 @@ grub_script_create_cmdif (struct grub_script_cmd *bool,
    the title.  The sourcecode for this entry is passed in SOURCECODE.
    The options for this entry are passed in OPTIONS.  */
 struct grub_script_cmd *
-grub_script_create_cmdmenu (struct grub_script_arg *title,
+grub_script_create_cmdmenu (struct grub_parser_param *state,
+                           struct grub_script_arg *title,
                            char *sourcecode,
                            int options)
 {
@@ -221,7 +223,7 @@ grub_script_create_cmdmenu (struct grub_script_arg *title,
       sourcecode[i] = '\0';
     }
 
-  cmd = grub_script_malloc (sizeof (*cmd));
+  cmd = grub_script_malloc (state, sizeof (*cmd));
   cmd->cmd.exec = grub_script_execute_menuentry;
   cmd->cmd.next = 0;
   cmd->sourcecode = sourcecode;
@@ -235,7 +237,9 @@ grub_script_create_cmdmenu (struct grub_script_arg *title,
    be added at the end of CMDBLOCK's list.  If CMDBLOCK is zero, a new
    cmdblock will be created.  */
 struct grub_script_cmd *
-grub_script_add_cmd (struct grub_script_cmdblock *cmdblock, struct grub_script_cmd *cmd)
+grub_script_add_cmd (struct grub_parser_param *state,
+                    struct grub_script_cmdblock *cmdblock,
+                    struct grub_script_cmd *cmd)
 {
   grub_dprintf ("scripting", "cmdblock\n");
 
@@ -244,7 +248,8 @@ grub_script_add_cmd (struct grub_script_cmdblock *cmdblock, struct grub_script_c
 
   if (! cmdblock)
     {
-      cmdblock = (struct grub_script_cmdblock *) grub_script_malloc (sizeof (*cmdblock));
+      cmdblock = (struct grub_script_cmdblock *) grub_script_malloc (state,
+                                                                    sizeof (*cmdblock));
       cmdblock->cmd.exec = grub_script_execute_cmdblock;
       cmdblock->cmd.next = 0;
       cmdblock->cmdlist = cmd;
@@ -289,31 +294,53 @@ struct grub_script *
 grub_script_parse (char *script, grub_err_t (*getline) (char **))
 {
   struct grub_script *parsed;
+  struct grub_script_mem *memfree;
   struct grub_script_mem *membackup;
+  struct grub_lexer_param *lexstate;
+  struct grub_parser_param *parsestate;
 
   parsed = grub_malloc (sizeof (*parsed));
   if (! parsed)
     return 0;
 
+  parsestate = grub_malloc (sizeof (*parsestate));
+  if (! parsestate)
+    return 0;
+
+  parsestate->err = 0;
+  parsestate->func_mem = 0;
+  parsestate->memused = 0;
+  parsestate->parsed = 0;
+
   /* Initialize the lexer.  */
-  grub_script_lexer_init (script, getline);
+  lexstate = grub_script_lexer_init (script, getline);
+  if (! lexstate)
+    {
+      grub_free (parsed);
+      grub_free (parsestate);
+      return 0;
+    }
 
-  grub_script_parsed = 0;
+  parsestate->lexerstate = lexstate;
 
-  membackup = grub_script_mem_record ();
+  membackup = grub_script_mem_record (parsestate);
 
-  /* Parse the script, the result is stored in
-     `grub_script_parsed'.  */
-  if (grub_script_yyparse () || ! grub_script_parsed)
+  /* Parse the script.  */
+  if (grub_script_yyparse (parsestate) || parsestate->err)
     {
       struct grub_script_mem *memfree;
-      memfree = grub_script_mem_record_stop (membackup);
+      memfree = grub_script_mem_record_stop (parsestate, membackup);
       grub_script_mem_free (memfree);
+      grub_free (lexstate);
+      grub_free (parsestate);
       return 0;
     }
 
-  parsed->mem = grub_script_mem_record_stop (membackup);
-  parsed->cmd = grub_script_parsed;
+  parsed->mem = grub_script_mem_record_stop (parsestate, membackup);
+  parsed->cmd = parsestate->parsed;
+
+  grub_free (lexstate);
+  grub_free (parsestate);
 
   return parsed;
 }