Fix the handling of hotkeys in MENU LABEL on submenus syslinux-3.62-pre14
authorH. Peter Anvin <hpa@zytor.com>
Fri, 22 Feb 2008 19:03:34 +0000 (11:03 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Fri, 22 Feb 2008 19:03:34 +0000 (11:03 -0800)
Two bugs:

- We didn't strip ^ symbols inheriting from MENU LABEL to MENU TITLE
- We did consider_for_hotkey() with the wrong menu (the submenu
  itself, as opposed to the parent menu.)

As part of these changes, make a function available to create an
uninitialized, mutable refstring (that can be constructed and then
used as a refstring, that is.)

com32/menu/readconfig.c
com32/menu/refstr.c
com32/menu/refstr.h

index a17beb2..65e230d 100644 (file)
@@ -93,6 +93,36 @@ skipspace(char *p)
   return p;
 }
 
+/* Strip ^ from a string, returning a new reference to the same refstring
+   if none present */
+static const char *strip_caret(const char *str)
+{
+  const char *p, *r;
+  char *q;
+  int carets = 0;
+
+  p = str;
+  for (;;) {
+    p = strchr(p, '^');
+    if (!p)
+      break;
+    carets++;
+    p++;
+  }
+
+  if (!carets)
+    return refstr_get(str);
+
+  r = q = refstr_alloc(strlen(str)-carets);
+  for (p = str; *p; p++)
+    if (*p != '^')
+      *q++ = *p;
+
+  *q = '\0';                   /* refstr_alloc() already did this... */
+
+  return r;
+}
+
 /* Check to see if we are at a certain keyword (case insensitive) */
 /* Returns a pointer to the first character past the keyword */
 static char *
@@ -223,12 +253,11 @@ static struct menu_entry *new_entry(struct menu *m)
 
 static void consider_for_hotkey(struct menu *m, struct menu_entry *me)
 {
-  unsigned char *p =
-    (unsigned char *)strchr(me->displayname, '^');
+  const char *p = strchr(me->displayname, '^');
 
   if (me->action != MA_DISABLED) {
     if ( p && p[1] ) {
-      int hotkey = p[1] & ~0x20;
+      unsigned char hotkey = p[1] & ~0x20;
       if ( !m->menu_hotkeys[hotkey] ) {
        me->hotkey = hotkey;
        m->menu_hotkeys[hotkey] = me;
@@ -571,11 +600,11 @@ static void parse_config_file(FILE *f)
        } else if ( m->parent_entry ) {
          refstr_put(m->parent_entry->displayname);
          m->parent_entry->displayname = refstrdup(skipspace(p+5));
-         consider_for_hotkey(m, m->parent_entry);
+         consider_for_hotkey(m->parent, m->parent_entry);
          if (!m->title[0]) {
            /* MENU LABEL -> MENU TITLE on submenu */
            refstr_put(m->title);
-           m->title = refstr_get(m->parent_entry->displayname);
+           m->title = strip_caret(m->parent_entry->displayname);
          }
        }
       } else if ( looking_at(p, "title") ) {
index 868a8ac..f727abc 100644 (file)
 #include <stdio.h>
 #include "refstr.h"
 
+/* Allocate space for a refstring of len bytes, plus final null */
+/* The final null is inserted in the string; the rest is uninitialized. */
+char *refstr_alloc(size_t len)
+{
+  char *r = malloc(sizeof(unsigned int)+len+1);
+  if (!r)
+    return NULL;
+  *(unsigned int *)r = 1;
+  r += sizeof(unsigned int);
+  r[len] = '\0';
+  return r;
+}
+
 const char *refstrndup(const char *str, size_t len)
 {
   char *r;
@@ -29,11 +42,9 @@ const char *refstrndup(const char *str, size_t len)
     return NULL;
 
   len = strnlen(str, len);
-  r = malloc(sizeof(unsigned int)+len+1);
-  *(unsigned int *)r = 1;
-  r += sizeof(unsigned int);
-  memcpy(r, str, len);
-  r[len] = '\0';
+  r = refstr_alloc(len);
+  if (r)
+    memcpy(r, str, len);
   return r;
 }
 
@@ -46,35 +57,27 @@ const char *refstrdup(const char *str)
     return NULL;
 
   len = strlen(str);
-  r = malloc(sizeof(unsigned int)+len+1);
-  *(unsigned int *)r = 1;
-  r += sizeof(unsigned int);
-  memcpy(r, str, len);
-  r[len] = '\0';
+  r = refstr_alloc(len);
+  if (r)
+    memcpy(r, str, len);
   return r;
 }
 
 int vrsprintf(const char **bufp, const char *fmt, va_list ap)
 {
   va_list ap1;
-  int bytes;
+  int len;
   char *p;
 
   va_copy(ap1, ap);
-  bytes = vsnprintf(NULL, 0, fmt, ap1)+1;
+  len = vsnprintf(NULL, 0, fmt, ap1);
   va_end(ap1);
 
-  p = malloc(bytes+sizeof(unsigned int));
-  if ( !p ) {
-    *bufp = NULL;
+  *bufp = p = refstr_alloc(len);
+  if ( !p )
     return -1;
-  }
-
-  *(unsigned int *)p = 1;
-  p += sizeof(unsigned int);
-  *bufp = p;
 
-  return vsnprintf(p, bytes, fmt, ap);
+  return vsnprintf(p, len+1, fmt, ap);
 }
 
 int rsprintf(const char **bufp, const char *fmt, ...)
index 8bec018..f51777d 100644 (file)
@@ -31,6 +31,7 @@ const char *refstr_get(const char *r)
 }
 
 void refstr_put(const char *);
+char *refstr_alloc(size_t);
 const char *refstrdup(const char *);
 const char *refstrndup(const char *, size_t);
 int rsprintf(const char **, const char *, ...);