On Sun, 05 Oct 2008 13:07:32 +0300
Vesa Jääskeläinen <[EMAIL PROTECTED]> wrote:

> Colin D Bennett wrote:
> > This patch adds support for a 'class' attribute on menu entries.
> > It is somewhat of a kludge, however since currently you just append
> > "|class=this,that" to the menu entry title to specify the classes.
> > 
> > Classes are used to provide a simple and flexible way for the best
> > available icon to be used in a graphical menu, but there are other
> > possible uses for them as well.  The idea originates from the CSS
> > (cascading style sheets) and HTML 'class' concept.
> 
> Here is the patch snipped for using menuentry --class foo "title" { }.
> 
> Please try it out and see if it fits.

Hi Vesa,

Thanks for the argument parsing improvement.  I'm glad to rip out the
'|class=' title kludge.  Here is the result of merging your patch into
the menu entry class code.

Regards,
Colin
2008-10-13  Colin D Bennett  <[EMAIL PROTECTED]>

	Support classes for menu entries via the '--class CLASSNAME' argument
	to the menuentry command.  Argument list parsing functionality by Vesa
	Jääskeläinen <[EMAIL PROTECTED]>.

	* include/grub/menu.h (grub_menu_entry_class): New struct type.
	(grub_menu_entry): Added 'classes' field.
	* include/grub/normal.h (grub_normal_menu_addentry): Changed signature
	to take a list of arguments instead of just a title.
	* include/grub/script.h (grub_script_cmd_menuentry): Replaced title
	with arglist.
	(grub_script_create_cmdmenu): Changed signature to take an arglist
	instead of just a single arg (title).
	* normal/execute.c (grub_script_execute_menuentry): Parse arguments to
	the 'menuentry' script command.
	* normal/main.c (free_menu_entry_classes): New function.
	(grub_normal_menu_addentry): Take and process a list of arguments;
	handle '--class CLASSNAME' arguments and store the list of class names
	in the menu entry.
	* normal/parser.y (menuentry): Take a list of arguments.
	* normal/script.c (grub_script_create_cmdmenu): Take an argument list,
	store it in the command.


=== modified file 'include/grub/menu.h'
--- include/grub/menu.h	2008-08-30 19:20:13 +0000
+++ include/grub/menu.h	2008-10-13 16:15:06 +0000
@@ -20,12 +20,24 @@
 #ifndef GRUB_MENU_HEADER
 #define GRUB_MENU_HEADER 1
 
+struct grub_menu_entry_class
+{
+  char *name;
+  struct grub_menu_entry_class *next;
+};
+
 /* The menu entry.  */
 struct grub_menu_entry
 {
   /* The title name.  */
   const char *title;
 
+  /* The classes associated with the menu entry:
+     used to choose an icon or other style attributes.
+     This is a dummy head node for the linked list, so for an entry E,
+     E.classes->next is the first class if it is not NULL.  */
+  struct grub_menu_entry_class *classes;
+
   /* The commands associated with this menu entry.  */
   struct grub_script *commands;
 

=== modified file 'include/grub/normal.h'
--- include/grub/normal.h	2008-10-03 14:26:41 +0000
+++ include/grub/normal.h	2008-10-13 16:15:06 +0000
@@ -141,7 +141,7 @@
 char *grub_normal_do_completion (char *buf, int *restore,
 				 void (*hook) (const char *item, grub_completion_type_t type, int count));
 grub_err_t grub_normal_print_device_info (const char *name);
-grub_err_t grub_normal_menu_addentry (const char *title,
+grub_err_t grub_normal_menu_addentry (int argc, const char **args,
 				      struct grub_script *script,
 				      const char *sourcecode);
 char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);

=== modified file 'include/grub/script.h'
--- include/grub/script.h	2008-05-30 02:26:56 +0000
+++ include/grub/script.h	2008-10-13 16:15:06 +0000
@@ -113,8 +113,8 @@
 {
   struct grub_script_cmd cmd;
 
-  /* The title of the menu entry.  */
-  struct grub_script_arg *title;
+  /* The arguments for this menu entry.  */
+  struct grub_script_arglist *arglist;
 
   /* The sourcecode the entry will be generated from.  */
   const char *sourcecode;
@@ -204,7 +204,7 @@
 
 struct grub_script_cmd *
 grub_script_create_cmdmenu (struct grub_parser_param *state,
-			    struct grub_script_arg *title,
+			    struct grub_script_arglist *arglist,
 			    char *sourcecode,
 			    int options);
 

=== modified file 'normal/execute.c'
--- normal/execute.c	2008-01-15 15:32:17 +0000
+++ normal/execute.c	2008-10-13 16:15:06 +0000
@@ -216,29 +216,50 @@
 grub_script_execute_menuentry (struct grub_script_cmd *cmd)
 {
   struct grub_script_cmd_menuentry *cmd_menuentry;
-  char *title;
+  struct grub_script_arglist *arglist;
   struct grub_script *script;
+  char **args = 0;
+  int argcount = 0;
+  int i = 0;
 
   cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
 
-  /* The title can contain variables, parse them and generate a string
-     from it.  */
-  title = grub_script_execute_argument_to_string (cmd_menuentry->title);
-  if (! title)
-    return grub_errno;
+  if (cmd_menuentry->arglist)
+    {
+      argcount = cmd_menuentry->arglist->argcount;
+
+      /* Create argv from the arguments.  */
+      args = grub_malloc (sizeof (char *) * argcount);
+
+      if (! args)
+	{
+	  return grub_errno;
+	}
+
+      for (arglist = cmd_menuentry->arglist; arglist; arglist = arglist->next)
+	{
+	  char *str;
+	  str = grub_script_execute_argument_to_string (arglist->arg);
+	  args[i++] = str;
+	}
+    }
 
   /* Parse the menu entry *again*.  */
   script = grub_script_parse ((char *) cmd_menuentry->sourcecode, 0);
 
-  if (! script)
+  /* Add new menu entry.  */
+  if (script)
     {
-      grub_free (title);
-      return grub_errno;
+      grub_normal_menu_addentry (argcount, args,
+				 script, cmd_menuentry->sourcecode);
     }
 
-  /* XXX: When this fails, the memory should be freed?  */
-  return grub_normal_menu_addentry (title, script,
-				    cmd_menuentry->sourcecode);
+  /* Free arguments.  */
+  for (i = 0; i < argcount; i++)
+    grub_free (args[i]);
+  grub_free (args);
+
+  return grub_errno;
 }
 
 

=== modified file 'normal/main.c'
--- normal/main.c	2008-08-30 19:20:13 +0000
+++ normal/main.c	2008-10-13 16:15:06 +0000
@@ -148,14 +148,41 @@
   grub_env_unset_data_slot ("menu");
 }
 
+static void
+free_menu_entry_classes (struct grub_menu_entry_class *head)
+{
+  /* Free all the classes.  */
+  while (head)
+    {
+      struct grub_menu_entry_class *next;
+
+      grub_free (head->name);
+      next = head->next;
+      grub_free (head);
+      head = next;
+    }
+}
+
 grub_err_t
-grub_normal_menu_addentry (const char *title, struct grub_script *script,
+grub_normal_menu_addentry (int argc, const char **args, struct grub_script *script,
 			   const char *sourcecode)
 {
-  const char *menutitle;
+  const char *menutitle = 0;
   const char *menusourcecode;
   grub_menu_t menu;
   grub_menu_entry_t *last;
+  int failed = 0;
+  int i;
+  struct grub_menu_entry_class *classes_head;  /* Dummy head node for list.  */
+  struct grub_menu_entry_class *classes_tail;
+
+  /* Allocate dummy head node for class list.  */
+  classes_head = grub_malloc (sizeof (struct grub_menu_entry_class));
+  if (! classes_head)
+    return grub_errno;
+  classes_head->name = 0;
+  classes_head->next = 0;
+  classes_tail = classes_head;
 
   menu = grub_env_get_data_slot("menu");
   if (! menu)
@@ -167,10 +194,81 @@
   if (! menusourcecode)
     return grub_errno;
 
-  menutitle = grub_strdup (title);
-  if (! menutitle)
-    {
+  /* Parse menu arguments.  */
+  for (i = 0; i < argc; i++)
+    {
+      /* Capture arguments.  */
+      if (grub_strncmp ("--", args[i], 2) == 0)
+	{
+	  const char *arg = &args[i][2];
+
+	  /* Handle menu class.  */
+	  if (grub_strcmp(arg, "class") == 0)
+	    {
+	      char *class_name;
+	      struct grub_menu_entry_class *new_class;
+
+	      i++;
+	      class_name = grub_strdup (args[i]);
+	      if (! class_name)
+		{
+		  failed = 1;
+		  break;
+		}
+
+	      /* Create a new class and add it at the tail of the list.  */
+	      new_class = grub_malloc (sizeof (struct grub_menu_entry_class));
+	      if (! new_class)
+		{
+		  grub_free (class_name);
+		  failed = 1;
+		  break;
+		}
+	      /* Fill in the new class node.  */
+	      new_class->name = class_name;
+	      new_class->next = 0;
+	      /* Link the tail to it, and make it the new tail.  */
+	      classes_tail->next = new_class;
+	      classes_tail = new_class;
+	      continue;
+	    }
+	  else
+	    {
+	      /* Handle invalid argument.  */
+	      failed = 1;
+	      grub_error (GRUB_ERR_MENU, "invalid argument for menuentry: %s", args[i]);
+	      break;
+	    }
+	}
+
+      /* Capture title.  */
+      if (! menutitle)
+	{
+	  menutitle = grub_strdup (args[i]);
+	}
+      else
+	{
+	  failed = 1;
+	  grub_error (GRUB_ERR_MENU, "too many titles for menuentry: %s", args[i]);
+	  break;
+	}
+    }
+
+  /* Validate arguments.  */
+  if ((! failed) && (! menutitle))
+    {
+      grub_error (GRUB_ERR_MENU, "menuentry is missing title");
+      failed = 1;
+    }
+
+  /* If argument parsing failed, free any allocated resources.  */
+  if (failed)
+    {
+      free_menu_entry_classes (classes_head);
+      grub_free ((void *) menutitle);
       grub_free ((void *) menusourcecode);
+
+      /* Here we assume that grub_error has been used to specify failure details.  */
       return grub_errno;
     }
 
@@ -181,6 +279,7 @@
   *last = grub_malloc (sizeof (**last));
   if (! *last)
     {
+      free_menu_entry_classes (classes_head);
       grub_free ((void *) menutitle);
       grub_free ((void *) menusourcecode);
       return grub_errno;
@@ -188,6 +287,7 @@
 
   (*last)->commands = script;
   (*last)->title = menutitle;
+  (*last)->classes = classes_head;
   (*last)->next = 0;
   (*last)->sourcecode = menusourcecode;
 

=== modified file 'normal/parser.y'
--- normal/parser.y	2008-07-02 00:00:37 +0000
+++ normal/parser.y	2008-10-13 16:15:06 +0000
@@ -204,7 +204,7 @@
 ;
 
 /* A menu entry.  Carefully save the memory that is allocated.  */
-menuentry:	"menuentry" argument
+menuentry:	"menuentry" arguments
 		  {
 		    grub_script_lexer_ref (state->lexerstate);
 		  } newlines '{'

=== modified file 'normal/script.c'
--- normal/script.c	2007-12-30 08:52:06 +0000
+++ normal/script.c	2008-10-13 16:15:06 +0000
@@ -206,7 +206,7 @@
    The options for this entry are passed in OPTIONS.  */
 struct grub_script_cmd *
 grub_script_create_cmdmenu (struct grub_parser_param *state,
-			    struct grub_script_arg *title,
+			    struct grub_script_arglist *arglist,
 			    char *sourcecode,
 			    int options)
 {
@@ -232,9 +232,9 @@
   cmd->cmd.next = 0;
   /* XXX: Check if this memory is properly freed.  */
   cmd->sourcecode = sourcecode;
-  cmd->title = title;
+  cmd->arglist = arglist;
   cmd->options = options;
- 
+
   return (struct grub_script_cmd *) cmd;
 }
 

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to