All of lore.kernel.org
 help / color / mirror / Atom feed
From: Colin D Bennett <colin@gibibit.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [PATCH] GSoC #05 Menu entry class attribute (v2)
Date: Mon, 13 Oct 2008 09:35:53 -0700	[thread overview]
Message-ID: <20081013093553.4f3e978e@gibibit.com> (raw)
In-Reply-To: <48E891E4.1000507@nic.fi>


[-- Attachment #1.1: Type: text/plain, Size: 927 bytes --]

On Sun, 05 Oct 2008 13:07:32 +0300
Vesa Jääskeläinen <chaac@nic.fi> 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

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 05_menu-entry-class_v2.patch --]
[-- Type: text/x-patch; name=05_menu-entry-class_v2.patch, Size: 10182 bytes --]

2008-10-13  Colin D Bennett  <colin@gibibit.com>

	Support classes for menu entries via the '--class CLASSNAME' argument
	to the menuentry command.  Argument list parsing functionality by Vesa
	Jääskeläinen <chaac@nic.fi>.

	* 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;
 }
 
 \f

=== 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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

  reply	other threads:[~2008-10-13 16:36 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-31  6:52 [PATCH] GSoC #05 Menu entry class attribute Colin D Bennett
2008-10-05 10:07 ` Vesa Jääskeläinen
2008-10-13 16:35   ` Colin D Bennett [this message]
2009-01-31  9:19     ` [PATCH] GSoC #05 Menu entry class attribute (v2) Vesa Jääskeläinen
2009-01-31 17:49       ` Colin D Bennett

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081013093553.4f3e978e@gibibit.com \
    --to=colin@gibibit.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.