submenu snapshot: it compiles now...
authorH. Peter Anvin <hpa@zytor.com>
Tue, 19 Feb 2008 19:15:20 +0000 (11:15 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 20 Feb 2008 00:51:23 +0000 (16:51 -0800)
com32/menu/Makefile
com32/menu/background.c [new file with mode: 0644]
com32/menu/colors.c
com32/menu/menu.h
com32/menu/menumain.c
com32/menu/printmsg.c
com32/menu/readconfig.c
com32/menu/refstr.c
com32/menu/refstr.h

index 8fdfb26..7de42dd 100644 (file)
@@ -50,7 +50,8 @@ COM32DIR = $(AUXDIR)/com32
 MODULES          = menu.c32 vesamenu.c32
 TESTFILES =
 
-COMMONOBJS = menumain.o readconfig.o passwd.o printmsg.o
+COMMONOBJS = menumain.o readconfig.o passwd.o printmsg.o colors.o \
+       background.o refstr.o
 
 all: $(MODULES) $(TESTFILES)
 
diff --git a/com32/menu/background.c b/com32/menu/background.c
new file mode 100644 (file)
index 0000000..1792cf1
--- /dev/null
@@ -0,0 +1,27 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <consoles.h>
+#include <string.h>
+#include "menu.h"
+
+const char *current_background = NULL;
+
+void set_background(const char *new_background)
+{
+  if (!current_background ||
+      strcmp(current_background, new_background)) {
+    draw_background(new_background);
+    current_background = new_background;
+  }
+}
+
index 92f446d..0529d64 100644 (file)
@@ -10,6 +10,9 @@
  *
  * ----------------------------------------------------------------------- */
 
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
 #include <colortbl.h>
 #include "menu.h"
 
@@ -36,7 +39,7 @@
  * 17 - disabled        Disabled menu item
  */
 
-static const struct color_table default_color_table[] = {
+static const struct color_table default_colors[] = {
   { "screen",      "37;40",     0x80ffffff, 0x00000000, SHADOW_NORMAL },
   { "border",      "30;44",     0x40000000, 0x00000000, SHADOW_NORMAL },
   { "title",       "1;36;44",   0xc00090f0, 0x00000000, SHADOW_NORMAL },
@@ -57,10 +60,10 @@ static const struct color_table default_color_table[] = {
   { "disabled",    "1;30;44",   0x60cccccc, 0x00000000, SHADOW_NORMAL },
 };
 
-#define NCOLORS (sizeof default_color_table/sizeof(struct color_table))
+#define NCOLORS (sizeof default_colors/sizeof default_colors[0])
 const int message_base_color = NCOLORS;
 
-
+/* Algorithmically generate the msgXX colors */
 void set_msg_colors_global(struct color_table *tbl,
                           unsigned int fg, unsigned int bg,
                           enum color_table_shadow shadow)
@@ -115,59 +118,67 @@ void set_msg_colors_global(struct color_table *tbl,
   }
 }
 
-struct color_table *default_color_table(const struct color_table *base)
+struct color_table *default_color_table(void)
 {
-  unsigned int i, ncolors;
+  unsigned int i;
   const struct color_table *dp;
   struct color_table *cp;
   struct color_table *color_table;
   static const int pc2ansi[8] = {0, 4, 2, 6, 1, 5, 3, 7};
-
-  if (!base)
-    base = default_color_table;
+  static char msg_names[6*256];
+  char *mp;
 
   color_table = calloc(NCOLORS+256, sizeof(struct color_table));
 
-  dp = base;
+  dp = default_colors;
   cp = color_table;
 
-  if (base == default_color_table)
-    ncolors = NCOLORS;
-  else
-    ncolors = NCOLORS+256;
-
-  for (i = 0; i < ncolors; i++) {
-    if (cp->ansi)
-      free((void *)cp->ansi);
-
+  for (i = 0; i < NCOLORS; i++) {
     *cp = *dp;
-    cp->ansi = strdup(dp->ansi);
-
+    cp->ansi = refstrdup(dp->ansi);
     cp++;
     dp++;
   }
 
-  if (base == default_color_table) {
-    for (i = 0; i < 256; i++) {
-      if (!cp->name)
-       asprintf((char **)&cp->name, "msg%02x", i);
-      
-      if (cp->ansi)
-       free((void *)cp->ansi);
-      
-      asprintf((char **)&cp->ansi, "%s3%d;4%d", (i & 8) ? "1;" : "",
-              pc2ansi[i & 7], pc2ansi[(i >> 4) & 7]);
-      
-      cp++;
-    }
+  mp = msg_names;
+  for (i = 0; i < 256; i++) {
+    cp->name = mp;
+    mp += sprintf(mp, "msg%02x", i)+1;
     
-    /*** XXX: This needs to move to run_menu() ***/
-    console_color_table = color_table;
-    console_color_table_size = NCOLORS+256;
+    rsprintf(&cp->ansi, "%s3%d;4%d", (i & 8) ? "1;" : "",
+            pc2ansi[i & 7], pc2ansi[(i >> 4) & 7]);
+    cp++;
+  }
     
-    set_msg_colors_global(color_table, MSG_COLORS_DEF_FG, MSG_COLORS_DEF_BG,
-                         MSG_COLORS_DEF_SHADOW);
+  /*** XXX: This needs to move to run_menu() ***/
+  console_color_table = color_table;
+  console_color_table_size = NCOLORS+256;
+  
+  set_msg_colors_global(color_table, MSG_COLORS_DEF_FG,
+                       MSG_COLORS_DEF_BG, MSG_COLORS_DEF_SHADOW);
+
+  return color_table;
+}
+
+struct color_table *copy_color_table(const struct color_table *master)
+{
+  const struct color_table *dp;
+  struct color_table *color_table, *cp;
+  unsigned int i;
+
+  color_table = calloc(NCOLORS+256, sizeof(struct color_table));
+
+  dp = master;
+  cp = color_table;
+
+  for (i = 0; i < NCOLORS+256; i++) {
+    *cp = *dp;
+    cp->ansi = refstr_get(dp->ansi);
+    cp++;
+    dp++;
   }
 
   return color_table;
 }
+
+  
index 0d13b54..bf014b0 100644 (file)
@@ -25,6 +25,8 @@
 #include <inttypes.h>
 #include <unistd.h>
 #include <colortbl.h>
+#include <stdbool.h>
+#include "refstr.h"
 
 #ifndef CLK_TCK
 # define CLK_TCK sysconf(_SC_CLK_TCK)
 
 struct menu;
 
+enum menu_action {
+  MA_CMD,                      /* Execute a command */
+  MA_DISABLED,                 /* Disabled menu entry */
+  MA_SUBMENU,                  /* This is a submenu entry */
+  MA_GOTO,                     /* Go to another menu */
+  MA_GOTO_UNRES,               /* Unresolved go to */
+  MA_QUIT,                     /* Quit to CLI */
+};
+
 struct menu_entry {
   char *displayname;
   char *label;
@@ -39,10 +50,16 @@ struct menu_entry {
   char *helptext;
   char *cmdline;
   struct menu *submenu;
+  struct menu_entry *next;     /* Linked list of all labels across menus */
+  enum menu_action action;
   unsigned char hotkey;
-  unsigned char disabled;
 };
 
+static inline bool is_disabled(struct menu_entry *me)
+{
+  return me->action == MA_DISABLED;
+}
+
 enum kernel_type {
   /* Meta-types for internal use */
   KT_NONE,
@@ -62,6 +79,26 @@ enum kernel_type {
 
 extern const char * const kernel_types[];
 
+/* Configurable integer parameters */
+enum parameter_number {
+  P_WIDTH,
+  P_MARGIN,
+  P_PASSWD_MARGIN,
+  P_MENU_ROWS,
+  P_TABMSG_ROW,
+  P_CMDLINE_ROW,
+  P_END_ROW,
+  P_PASSWD_ROW,
+  P_TIMEOUT_ROW,
+  P_HELPMSG_ROW,
+  P_HELPMSGEND_ROW,
+  P_HSHIFT,
+  P_VSHIFT,
+  P_HIDDEN_ROW,
+  
+  NPARAMS
+};
+
 /* Configurable messages */
 enum message_number {
   MSG_TITLE,
@@ -93,7 +130,10 @@ struct fkey_help {
 };
 
 struct menu {
+  struct menu *next;           /* Linked list of all menus */
+  const char *label;           /* Goto label for this menu */
   struct menu *parent;
+  int parent_entry;
 
   struct menu_entry *menu_entries;
   struct menu_entry *menu_hotkeys[256];
@@ -120,11 +160,16 @@ struct menu {
   struct fkey_help fkeyhelp[12];
 };
 
-extern struct menu *root_menu;
+extern struct menu *root_menu, *start_menu, *hide_menu, *menu_list;
 
 /* 2048 is the current definition inside syslinux */
 #define MAX_CMDLINE_LEN         2048
 
+/* These are global parameters regardless of which menu we're displaying */
+extern int shiftkey;
+extern int hiddenmenu;
+extern long long totaltimeout;
+
 void parse_configs(char **argv);
 int draw_background(const char *filename);
 
@@ -146,13 +191,22 @@ extern const int message_base_color;
 int mygetkey(clock_t timeout);
 int show_message_file(const char *filename, const char *background);
 
+/* passwd.c */
+int passwd_compare(const char *passwd, const char *entry);
+
+/* colors.c */
 #define MSG_COLORS_DEF_FG      0x90ffffff
 #define MSG_COLORS_DEF_BG      0x80ffffff
 #define MSG_COLORS_DEF_SHADOW  SHADOW_NORMAL
-void set_msg_colors_global(unsigned int fg, unsigned int bg,
+void set_msg_colors_global(struct color_table *tbl,
+                          unsigned int fg, unsigned int bg,
                           enum color_table_shadow shadow);
+struct color_table *default_color_table(void);
+struct color_table *copy_color_table(const struct color_table *master);
+extern const int message_base_color;
 
-/* passwd.c */
-int passwd_compare(const char *passwd, const char *entry);
+/* background.c */
+extern const char *current_background;
+void set_background(const char *new_background);
 
 #endif /* MENU_H */
index 8daf1f3..9891c2a 100644 (file)
 
 #include "menu.h"
 
+/* The symbol "cm" always refers to the current menu across this file... */
+static const struct menu *cm;
+
 const struct menu_parameter mparm[NPARAMS] = {
-  { "width", 80 },
-  { "margin", 10 },
-  { "passwordmargin", 3 },
-  { "rows", 12 },
-  { "tabmsgrow", 18 },
-  { "cmdlinerow", 18 },
-  { "endrow", -1 },
-  { "passwordrow", 11 },
-  { "timeoutrow", 20 },
-  { "helpmsgrow", 22 },
-  { "helpmsgendrow", -1 },
-  { "hshift", 0 },
-  { "vshift", 0 },
-  { "hiddenrow", -2 },
+  [P_WIDTH]            = { "width", 0 },
+  [P_MARGIN]           = { "margin", 10 },
+  [P_PASSWD_MARGIN]    = { "passwordmargin", 3 },
+  [P_MENU_ROWS]                = { "rows", 12 },
+  [P_TABMSG_ROW]       = { "tabmsgrow", 18 },
+  [P_CMDLINE_ROW]      = { "cmdlinerow", 18 },
+  [P_END_ROW]          = { "endrow", -1 },
+  [P_PASSWD_ROW]       = { "passwordrow", 11 },
+  [P_TIMEOUT_ROW]      = { "timeoutrow", 20 },
+  [P_HELPMSG_ROW]      = { "helpmsgrow", 22 },
+  [P_HELPMSGEND_ROW]   = { "helpmsgendrow", -1 },
+  [P_HSHIFT]           = { "hshift", 0 },
+  [P_VSHIFT]           = { "vshift", 0 },
+  [P_HIDDEN_ROW]       = { "hiddenrow", -2 },
 };
 
-#define WIDTH          mparm[0].value
-#define MARGIN         mparm[1].value
-#define PASSWD_MARGIN  mparm[2].value
-#define MENU_ROWS      mparm[3].value
-#define TABMSG_ROW     (mparm[4].value+VSHIFT)
-#define CMDLINE_ROW    (mparm[5].value+VSHIFT)
-#define END_ROW                mparm[6].value
-#define PASSWD_ROW     (mparm[7].value+VSHIFT)
-#define TIMEOUT_ROW    (mparm[8].value+VSHIFT)
-#define HELPMSG_ROW    (mparm[9].value+VSHIFT)
-#define HELPMSGEND_ROW mparm[10].value
-#define HSHIFT         mparm[11].value
-#define VSHIFT         mparm[12].value
-#define HIDDEN_ROW     mparm[13].value
+/* These macros assume "cm" is a pointer to the current menu */
+#define WIDTH          (cm->mparm[P_WIDTH])
+#define MARGIN         (cm->mparm[P_MARGIN])
+#define PASSWD_MARGIN  (cm->mparm[P_PASSWD_MARGIN])
+#define MENU_ROWS      (cm->mparm[P_MENU_ROWS])
+#define TABMSG_ROW     (cm->mparm[P_TABMSG_ROW]+VSHIFT)
+#define CMDLINE_ROW    (cm->mparm[P_CMDLINE_ROW]+VSHIFT)
+#define END_ROW                (cm->mparm[P_END_ROW])
+#define PASSWD_ROW     (cm->mparm[P_PASSWD_ROW]+VSHIFT)
+#define TIMEOUT_ROW    (cm->mparm[P_TIMEOUT_ROW]+VSHIFT)
+#define HELPMSG_ROW    (cm->mparm[P_HELPMSG_ROW]+VSHIFT)
+#define HELPMSGEND_ROW (cm->mparm[P_HELPMSGEND_ROW])
+#define HSHIFT         (cm->mparm[P_HSHIFT])
+#define VSHIFT         (cm->mparm[P_VSHIFT])
+#define HIDDEN_ROW     (cm->mparm[P_HIDDEN_ROW])
 
 static char *
 pad_line(const char *text, int align, int width)
@@ -117,22 +121,22 @@ static void
 draw_row(int y, int sel, int top, int sbtop, int sbbot)
 {
   int i = (y-4-VSHIFT)+top;
-  int dis = (i < nentries) && menu_entries[i].disabled;
+  int dis = (i < cm->nentries) && is_disabled(&cm->menu_entries[i]);
 
   printf("\033[%d;%dH\1#1\016x\017%s ",
         y, MARGIN+1+HSHIFT,
         (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3");
 
-  if ( i >= nentries ) {
+  if ( i >= cm->nentries ) {
     fputs(pad_line("", 0, WIDTH-2*MARGIN-4), stdout);
   } else {
-    display_entry(&menu_entries[i],
+    display_entry(&cm->menu_entries[i],
                  (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3",
                  (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4",
                  WIDTH-2*MARGIN-4);
   }
 
-  if ( nentries <= MENU_ROWS ) {
+  if ( cm->nentries <= MENU_ROWS ) {
     printf(" \1#1\016x\017");
   } else if ( sbtop > 0 ) {
     if ( y >= sbtop && y <= sbbot )
@@ -201,8 +205,8 @@ ask_passwd(const char *menu_entry)
     putchar('q');
 
   printf("j\017\033[%d;%dH\2#12 %s \033[%d;%dH\2#13",
-        PASSWD_ROW, (WIDTH-(strlen(messages[MSG_PASSPROMPT].msg)+2))/2,
-        messages[MSG_PASSPROMPT].msg, PASSWD_ROW+1, PASSWD_MARGIN+3);
+        PASSWD_ROW, (WIDTH-(strlen(cm->messages[MSG_PASSPROMPT])+2))/2,
+        cm->messages[MSG_PASSPROMPT], PASSWD_ROW+1, PASSWD_MARGIN+3);
 
   /* Actually allow user to type a password, then compare to the SHA1 */
   done = 0;
@@ -254,7 +258,8 @@ ask_passwd(const char *menu_entry)
 
   *p = '\0';
 
-  return (menu_master_passwd && passwd_compare(menu_master_passwd, user_passwd))
+  return (cm->menu_master_passwd &&
+         passwd_compare(cm->menu_master_passwd, user_passwd))
     || (menu_entry && passwd_compare(menu_entry, user_passwd));
 }
 
@@ -267,9 +272,9 @@ draw_menu(int sel, int top, int edit_line)
   const char *tabmsg;
   int tabmsg_len;
 
-  if ( nentries > MENU_ROWS ) {
-    int sblen = MENU_ROWS*MENU_ROWS/nentries;
-    sbtop = (MENU_ROWS-sblen+1)*top/(nentries-MENU_ROWS+1);
+  if ( cm->nentries > MENU_ROWS ) {
+    int sblen = MENU_ROWS*MENU_ROWS/cm->nentries;
+    sbtop = (MENU_ROWS-sblen+1)*top/(cm->nentries-MENU_ROWS+1);
     sbbot = max(sbtop, sbtop+sblen-1);
 
     sbtop += 4;  sbbot += 4;   /* Starting row of scrollbar */
@@ -282,7 +287,7 @@ draw_menu(int sel, int top, int edit_line)
   printf("k\033[%d;%dH\1#1x\017\1#2 %s \1#1\016x",
         VSHIFT+2,
         HSHIFT+MARGIN+1,
-        pad_line(messages[MSG_TITLE].msg, 1, WIDTH-2*MARGIN-4));
+        pad_line(cm->messages[MSG_TITLE], 1, WIDTH-2*MARGIN-4));
 
   printf("\033[%d;%dH\1#1t", VSHIFT+3, HSHIFT+MARGIN+1);
   for ( x = 2+HSHIFT ; x <= (WIDTH-2*MARGIN-1)+HSHIFT ; x++ )
@@ -297,10 +302,10 @@ draw_menu(int sel, int top, int edit_line)
     putchar('q');
   fputs("j\017", stdout);
 
-  if ( edit_line && allowedit && !menu_master_passwd )
-    tabmsg = messages[MSG_TAB].msg;
+  if ( edit_line && cm->allowedit && !cm->menu_master_passwd )
+    tabmsg = cm->messages[MSG_TAB];
   else
-    tabmsg = messages[MSG_NOTAB].msg;
+    tabmsg = cm->messages[MSG_NOTAB];
 
   tabmsg_len = strlen(tabmsg);
 
@@ -374,9 +379,9 @@ static void show_fkey(int key)
     if (fkey == -1)
       break;
 
-    if (fkeyhelp[fkey].textname)
-      key = show_message_file(fkeyhelp[fkey].textname,
-                             fkeyhelp[fkey].background);
+    if (cm->fkeyhelp[fkey].textname)
+      key = show_message_file(cm->fkeyhelp[fkey].textname,
+                             cm->fkeyhelp[fkey].background);
     else
       break;
   }
@@ -626,6 +631,15 @@ print_timeout_message(int tol, int row, const char *msg)
   printf("\033[%d;%dH\2#14    %s    ", row, HSHIFT+1+((WIDTH-nc-8)>>1), buf);
 }
 
+/* Set the background screen, etc. */
+static void
+prepare_screen_for_menu(void)
+{
+  console_color_table = cm->color_table;
+  console_color_table_size = message_base_color+256;
+  set_background(cm->menu_background);
+}
+
 static const char *
 do_hidden_menu(void)
 {
@@ -635,12 +649,12 @@ do_hidden_menu(void)
   clear_screen();
 
   if ( !setjmp(timeout_jump) ) {
-    timeout_left = timeout;
+    timeout_left = cm->timeout;
 
-    while (!timeout || timeout_left) {
+    while (!cm->timeout || timeout_left) {
       int tol = timeout_left/CLK_TCK;
 
-      print_timeout_message(tol, HIDDEN_ROW, messages[MSG_AUTOBOOT].msg);
+      print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);
 
       this_timeout = min(timeout_left, CLK_TCK);
       key = mygetkey(this_timeout);
@@ -652,7 +666,7 @@ do_hidden_menu(void)
     }
   }
 
-  return menu_entries[defentry].cmdline; /* Default entry */
+  return cm->menu_entries[cm->defentry].cmdline; /* Default entry */
 }
 
 static const char *
@@ -660,20 +674,26 @@ run_menu(void)
 {
   int key;
   int done = 0;
-  volatile int entry = defentry, prev_entry = -1;
+  volatile int entry = cm->defentry, prev_entry = -1;
   int top = 0, prev_top = -1;
   int clear = 1, to_clear;
   const char *cmdline = NULL;
   volatile clock_t key_timeout, timeout_left, this_timeout;
 
   /* Note: for both key_timeout and timeout == 0 means no limit */
-  timeout_left = key_timeout = timeout;
+  timeout_left = key_timeout = cm->timeout;
 
-  /* If we're in shiftkey mode, exit immediately unless a shift key is pressed */
+  /* If we're in shiftkey mode, exit immediately unless a shift key
+     is pressed */
   if ( shiftkey && !shift_is_held() ) {
-    return menu_entries[defentry].cmdline;
+    return cm->menu_entries[cm->defentry].cmdline;
+  } else {
+    shiftkey = 0;
   }
 
+  /* Do this before hiddenmenu handling, so we show the background */
+  prepare_screen_for_menu();
+
   /* Handle hiddenmenu */
   if ( hiddenmenu ) {
     cmdline = do_hidden_menu();
@@ -688,33 +708,35 @@ run_menu(void)
 
   /* Handle both local and global timeout */
   if ( setjmp(timeout_jump) ) {
-    entry = defentry;
+    entry = cm->defentry;
 
     if ( top < 0 || top < entry-MENU_ROWS+1 )
       top = max(0, entry-MENU_ROWS+1);
-    else if ( top > entry || top > max(0,nentries-MENU_ROWS) )
-      top = min(entry, max(0,nentries-MENU_ROWS));
+    else if ( top > entry || top > max(0, cm->nentries-MENU_ROWS) )
+      top = min(entry, max(0, cm->nentries-MENU_ROWS));
 
-    draw_menu(ontimeout ? -1 : entry, top, 1);
-    cmdline = ontimeout ? ontimeout : menu_entries[entry].cmdline;
+    draw_menu(cm->ontimeout ? -1 : entry, top, 1);
+    cmdline = cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry].cmdline;
     done = 1;
   }
 
   while ( !done ) {
     if ( entry <= 0 ) {
       entry = 0;
-      while ( entry < nentries && menu_entries[entry].disabled ) entry++;
+      while (entry < cm->nentries && is_disabled(&cm->menu_entries[entry]))
+       entry++;
     }
 
-    if ( entry >= nentries ) {
-      entry = nentries-1;
-      while ( entry > 0 && menu_entries[entry].disabled ) entry--;
+    if ( entry >= cm->nentries ) {
+      entry = cm->nentries-1;
+      while (entry > 0 && is_disabled(&cm->menu_entries[entry]))
+       entry--;
     }
 
     if ( top < 0 || top < entry-MENU_ROWS+1 )
       top = max(0, entry-MENU_ROWS+1);
-    else if ( top > entry || top > max(0,nentries-MENU_ROWS) )
-      top = min(entry, max(0,nentries-MENU_ROWS));
+    else if ( top > entry || top > max(0, cm->nentries-MENU_ROWS) )
+      top = min(entry, max(0, cm->nentries-MENU_ROWS));
 
     /* Start with a clear screen */
     if ( clear ) {
@@ -728,22 +750,22 @@ run_menu(void)
 
     if ( top != prev_top ) {
       draw_menu(entry, top, 1);
-      display_help(menu_entries[entry].helptext);
+      display_help(cm->menu_entries[entry].helptext);
     } else if ( entry != prev_entry ) {
       draw_row(prev_entry-top+4+VSHIFT, entry, top, 0, 0);
       draw_row(entry-top+4+VSHIFT, entry, top, 0, 0);
-      display_help(menu_entries[entry].helptext);
+      display_help(cm->menu_entries[entry].helptext);
     }
 
     prev_entry = entry;  prev_top = top;
 
     /* Cursor movement cancels timeout */
-    if ( entry != defentry )
+    if ( entry != cm->defentry )
       key_timeout = 0;
 
     if ( key_timeout ) {
       int tol = timeout_left/CLK_TCK;
-      print_timeout_message(tol, TIMEOUT_ROW, messages[MSG_AUTOBOOT].msg);
+      print_timeout_message(tol, TIMEOUT_ROW, cm->messages[MSG_AUTOBOOT]);
       to_clear = 1;
     } else {
       to_clear = 0;
@@ -781,37 +803,38 @@ run_menu(void)
     case KEY_ENTER:
     case KEY_CTRL('J'):
       key_timeout = 0;         /* Cancels timeout */
-      if ( menu_entries[entry].passwd ) {
+      if ( cm->menu_entries[entry].passwd ) {
        clear = 1;
-       done = ask_passwd(menu_entries[entry].passwd);
+       done = ask_passwd(cm->menu_entries[entry].passwd);
       } else {
        done = 1;
       }
-      cmdline = menu_entries[entry].cmdline;
+      cmdline = cm->menu_entries[entry].cmdline;
       break;
 
     case KEY_UP:
     case KEY_CTRL('P'):
-      while ( entry > 0 && entry-- && menu_entries[entry].disabled ) {
+      while (entry > 0 && entry-- && is_disabled(&cm->menu_entries[entry])) {
        if ( entry < top )
          top -= MENU_ROWS;
       }
 
       if ( entry == 0 ) {
-        while ( menu_entries[entry].disabled )
+        while (is_disabled(&cm->menu_entries[entry]))
           entry++;
       }
       break;
 
     case KEY_DOWN:
     case KEY_CTRL('N'):
-      while ( entry < nentries-1 && entry++ && menu_entries[entry].disabled ) {
+      while (entry < cm->nentries-1 && entry++ &&
+            is_disabled(&cm->menu_entries[entry])) {
        if ( entry >= top+MENU_ROWS )
          top += MENU_ROWS;
       }
 
-      if ( entry == nentries-1 ) {
-        while ( menu_entries[entry].disabled )
+      if ( entry >= cm->nentries-1 ) {
+        while (is_disabled(&cm->menu_entries[entry]))
           entry--;
       }
       break;
@@ -850,8 +873,8 @@ run_menu(void)
 
     case KEY_CTRL('E'):
     case KEY_END:
-      entry = nentries - 1;
-      top = max(0, nentries-MENU_ROWS);
+      entry = cm->nentries - 1;
+      top = max(0, cm->nentries-MENU_ROWS);
       break;
 
     case KEY_F1:
@@ -871,13 +894,13 @@ run_menu(void)
       break;
 
     case KEY_TAB:
-      if ( allowedit ) {
+      if ( cm->allowedit ) {
        int ok = 1;
 
        key_timeout = 0;        /* Cancels timeout */
        draw_row(entry-top+4+VSHIFT, -1, top, 0, 0);
 
-       if ( menu_master_passwd ) {
+       if ( cm->menu_master_passwd ) {
          ok = ask_passwd(NULL);
          clear_screen();
          draw_menu(-1, top, 0);
@@ -888,7 +911,7 @@ run_menu(void)
        }
 
        if ( ok ) {
-         cmdline = edit_cmdline(menu_entries[entry].cmdline, top);
+         cmdline = edit_cmdline(cm->menu_entries[entry].cmdline, top);
          done = !!cmdline;
          clear = 1;            /* In case we hit [Esc] and done is null */
        } else {
@@ -898,23 +921,23 @@ run_menu(void)
       break;
     case KEY_CTRL('C'):                /* Ctrl-C */
     case KEY_ESC:              /* Esc */
-      if ( allowedit ) {
+      if ( cm->allowedit ) {
        done = 1;
        clear = 1;
        key_timeout = 0;
 
        draw_row(entry-top+4+VSHIFT, -1, top, 0, 0);
 
-       if ( menu_master_passwd )
+       if ( cm->menu_master_passwd )
          done = ask_passwd(NULL);
       }
       break;
     default:
       if ( key > 0 && key < 0xFF ) {
        key &= ~0x20;           /* Upper case */
-       if ( menu_hotkeys[key] ) {
+       if ( cm->menu_hotkeys[key] ) {
          key_timeout = 0;
-         entry = menu_hotkeys[key] - menu_entries;
+         entry = cm->menu_hotkeys[key] - cm->menu_entries;
          /* Should we commit at this point? */
        }
       }
@@ -933,7 +956,7 @@ static void
 execute(const char *cmdline, enum kernel_type type)
 {
   com32sys_t ireg;
-  const char *p, **pp;
+  const char *p, * const *pp;
   char *q = __com32.cs_bounce;
   const char *kernel, *args;
 
@@ -986,6 +1009,7 @@ execute(const char *cmdline, enum kernel_type type)
 int menu_main(int argc, char *argv[])
 {
   const char *cmdline;
+  struct menu *m;
   int rows, cols;
   int i;
 
@@ -993,26 +1017,29 @@ int menu_main(int argc, char *argv[])
 
   console_prepare();
 
-  install_default_color_table();
   if (getscreensize(1, &rows, &cols)) {
     /* Unknown screen size? */
     rows = 24;
     cols = 80;
   }
 
-  WIDTH = cols;
   parse_configs(argv+1);
+  cm = start_menu;
+
+  /* Some postprocessing for all menus */
+  for (m = menu_list; m; m = m->next) {
+    if (!m->mparm[P_WIDTH])
+      m->mparm[P_WIDTH] = cols;
+
+    /* If anyone has specified negative parameters, consider them
+       relative to the bottom row of the screen. */
+    for (i = 0; i < NPARAMS; i++)
+      if (m->mparm[i] < 0)
+       m->mparm[i] = max(m->mparm[i]+rows, 0);
+  }
 
-  /* If anyone has specified negative parameters, consider them
-     relative to the bottom row of the screen. */
-  for (i = 0; mparm[i].name; i++)
-    if (mparm[i].value < 0)
-      mparm[i].value = max(mparm[i].value+rows, 0);
-
-  draw_background(menu_background);
-
-  if ( !nentries ) {
-    fputs("No LABEL entries found in configuration file!\n", stdout);
+  if ( !cm->nentries ) {
+    fputs("Initial menu has no LABEL entries!\n", stdout);
     return 1;                  /* Error! */
   }
 
@@ -1024,8 +1051,8 @@ int menu_main(int argc, char *argv[])
 
     if ( cmdline ) {
       execute(cmdline, KT_NONE);
-      if ( onerror )
-       execute(onerror, KT_NONE);
+      if ( cm->onerror )
+       execute(cm->onerror, KT_NONE);
     } else {
       return 0;                        /* Exit */
     }
index 5455b70..cef5508 100644 (file)
@@ -102,17 +102,18 @@ static int draw_message_file(const char *filename)
 int show_message_file(const char *filename, const char *background)
 {
   int rv = KEY_NONE;
+  const char *old_background = NULL;
 
-  if (background && (!menu_background || strcmp(background, menu_background)))
-    draw_background(background);
-  else
-    background = NULL;
+  if (background) {
+    old_background = current_background;
+    set_background(background);
+  }
 
   if ( !(rv = draw_message_file(filename)) )
     rv = mygetkey(0);          /* Wait for keypress */
 
-  if (background)
-    draw_background(menu_background);
+  if (old_background)
+    set_background(old_background);
 
   return rv;
 }
index 9c60268..98b7160 100644 (file)
 #include <alloca.h>
 #include <inttypes.h>
 #include <colortbl.h>
-#ifdef __COM32__
-# include <com32.h>
-#endif
+#include <com32.h>
+#include <syslinux/config.h>
 
 #include "menu.h"
 
-int nentries     = 0;
-int nhidden      = 0;
-int defentry     = 0;
-int allowedit    = 1;          /* Allow edits of the command line */
-int timeout      = 0;
+/* Root menu, starting menu, hidden menu, and list of all menus */
+struct menu *root_menu, *start_menu, *hide_menu, *menu_list;
+
+/* These are global parameters regardless of which menu we're displaying */
 int shiftkey     = 0;          /* Only display menu if shift key pressed */
 int hiddenmenu   = 0;
 long long totaltimeout = 0;
 
-char *ontimeout   = NULL;
-char *onerror     = NULL;
-
-char *menu_master_passwd = NULL;
-char *menu_background = NULL;
-
-struct fkey_help fkeyhelp[12];
-
-struct menu_entry *menu_entries = NULL;
-struct menu_entry *hide_entries = NULL;
-static int menu_entries_space = 0, hide_entries_space = 0;
-struct menu_entry *menu_hotkeys[256];
+/* Linked list of all entires, hidden or not; used by unlabel() */
+static struct menu_entry *all_entries;
+static struct menu_entry **all_entries_end = &all_entries;
 
-struct messages messages[MSG_COUNT] = {
+const struct messages messages[MSG_COUNT] = {
   [MSG_TITLE]      =  { "title",    "" },
   [MSG_AUTOBOOT]   =  { "autoboot", "Automatic boot in # second{,s}..." },
-  [MSG_TAB]        =  { "tabmsg",   "Press [Tab] to edit options", NULL },
+  [MSG_TAB]        =  { "tabmsg",   "Press [Tab] to edit options" },
   [MSG_NOTAB]      =  { "notabmsg", "" },
-  [MSG_PASSPROMPT] =  { "passprompt", "Password required", NULL },
+  [MSG_PASSPROMPT] =  { "passprompt", "Password required" },
 };
 
 #define astrdup(x) ({ char *__x = (x); \
@@ -60,7 +49,7 @@ struct messages messages[MSG_COUNT] = {
                       __p; })
 
 /* Must match enum kernel_type */
-const char *kernel_types[] = {
+const char * const kernel_types[] = {
   "none",
   "localboot",
   "kernel",
@@ -75,44 +64,20 @@ const char *kernel_types[] = {
   NULL
 };
 
-const char *ipappends[32];
-
-static void
-get_ipappend(void)
+/*
+ * Search the list of all menus for a specific label
+ */
+static struct menu *
+find_menu(const char *label)
 {
-#ifdef __COM32__
-  static com32sys_t r;
-  uint16_t *ipp;
-  int i;
-  int nipappends;
-
-  r.eax.w[0] = 0x000F;
-  __intcall(0x22, &r, &r);
-
-  nipappends = min(r.ecx.w[0], 32);
-  ipp        = MK_PTR(r.es, r.ebx.w[0]);
-  for ( i = 0 ; i < nipappends ; i++ ) {
-    ipappends[i] = MK_PTR(r.es, *ipp++);
+  struct menu *m;
+  
+  for (m = menu_list; m; m = m->next) {
+    if (!strcmp(label, m->label))
+      return m;
   }
-#else
-  ipappends[0] = "ip=foo:bar:baz:quux";
-  ipappends[1] = "BOOTIF=01-aa-bb-cc-dd-ee-ff";
-#endif
-}
-
-static const char *
-get_config(void)
-{
-#ifdef __COM32__
-  static com32sys_t r;
-
-  r.eax.w[0] = 0x000E;
-  __intcall(0x22, &r, &r);
 
-  return MK_PTR(r.es, r.ebx.w[0]);
-#else
-  return "syslinux.cfg";       /* Dummy default name */
-#endif
+  return NULL;
 }
 
 #define MAX_LINE 4096
@@ -145,7 +110,7 @@ looking_at(char *line, const char *kwd)
   return my_isspace(*p) ? p : NULL; /* Must be EOL or whitespace */
 }
 
-struct menu *start_menu(struct menu *parent)
+static struct menu *new_menu(struct menu *parent, const char *label)
 {
   struct menu *m = malloc(sizeof(struct menu));
   int i;
@@ -158,23 +123,28 @@ struct menu *start_menu(struct menu *parent)
     memset(m->menu_hotkeys, 0, sizeof m->menu_hotkeys);
 
     m->parent = parent;
+    m->parent_entry = parent->nentries-1; /* Last current entry */
     m->nentries = 0;
     m->nentries_space = 0;
     m->defentry = 0;
-    m->color_table = default_color_table(parent->color_table);
+    m->color_table = copy_color_table(parent->color_table);
   } else {
     /* Root menu */
-
     memset(m, 0, sizeof *m);
 
     for (i = 0; i < MSG_COUNT; i++)
-      m->messages[i] = messages.defmsg[i];
+      m->messages[i] = strdup(messages[i].defmsg);
     for (i = 0; i < NPARAMS; i++)
       m->mparm[i] = mparm[i].value;
 
-    m->color_table = default_color_table(NULL);
+    m->allowedit = 1;          /* Allow edits of the command line */
+    m->color_table = default_color_table();
   }
 
+  m->label = strdup(label);
+  m->next = menu_list;
+  menu_list = m;
+
   return m;
 }
 
@@ -195,22 +165,30 @@ struct labeldata {
 };
 
 static void
-record(struct labeldata *ld, char *append)
+record(struct menu *m, struct labeldata *ld, char *append)
 {
   char ipoptions[256], *ipp;
   int i;
   struct menu_entry *me;
+  const struct syslinux_ipappend_strings *ipappend;
+
+  if (!ld->label)
+    return;                    /* Nothing defined */
 
-  if (nentries >= menu_entries_space) {
-    if (!menu_entries_space)
-      menu_entries_space = 1;
+  /* Hidden entries are recorded on a special "hidden menu" */
+  if (ld->menuhide)
+    m = hide_menu;
+
+  if (m->nentries >= m->nentries_space) {
+    if (!m->nentries_space)
+      m->nentries_space = 1;
     else
-      menu_entries_space <<= 1;
+      m->nentries_space <<= 1;
 
-    menu_entries = realloc(menu_entries,
-                          menu_entries_space*sizeof *menu_entries);
+    m->menu_entries = realloc(m->menu_entries, m->nentries_space*
+                             sizeof(struct menu_entry));
   }
-  me = &menu_entries[nentries];
+  me = &m->menu_entries[m->nentries];
 
   if ( ld->label ) {
     char *a, *s;
@@ -219,11 +197,11 @@ record(struct labeldata *ld, char *append)
     me->passwd      = ld->passwd;
     me->helptext    = ld->helptext;
     me->hotkey = 0;
-    me->disabled = 0;
+    me->action = MA_CMD;
 
     if ( ld->menuindent ) {
       char *n = malloc(ld->menuindent + strlen(me->displayname) + 1);
-      memset(n, 32, ld->menuindent);
+      memset(n, ' ', ld->menuindent);
       strcpy(n + ld->menuindent, me->displayname);
       me->displayname = n;
     }
@@ -232,7 +210,7 @@ record(struct labeldata *ld, char *append)
       unsigned char *p = (unsigned char *)strchr(ld->menulabel, '^');
       if ( p && p[1] ) {
        int hotkey = p[1] & ~0x20;
-       if ( !menu_hotkeys[hotkey] ) {
+       if ( !m->menu_hotkeys[hotkey] ) {
          me->hotkey = hotkey;
        }
       }
@@ -240,9 +218,10 @@ record(struct labeldata *ld, char *append)
 
     ipp = ipoptions;
     *ipp = '\0';
-    for ( i = 0 ; i < 32 ; i++ ) {
-      if ( (ld->ipappend & (1U << i)) && ipappends[i] )
-       ipp += sprintf(ipp, " %s", ipappends[i]);
+    ipappend = syslinux_ipappend_strings();
+    for (i = 0; i < ipappend->count; i++) {
+      if ( (ld->ipappend & (1U << i)) && ipappend->ptr[i] )
+       ipp += sprintf(ipp, " %s", ipappend->ptr[i]);
     }
 
     a = ld->append;
@@ -263,7 +242,7 @@ record(struct labeldata *ld, char *append)
     if ( ld->menuseparator || ld->menudisabled ) {
       me->label    = NULL;
       me->passwd   = NULL;
-      me->disabled = 1;
+      me->action   = MA_DISABLED;
 
       if ( me->cmdline )
         free(me->cmdline);
@@ -282,41 +261,16 @@ record(struct labeldata *ld, char *append)
       ld->append = NULL;
     }
 
-    if ( !ld->menuhide ) {
-      if ( me->hotkey )
-       menu_hotkeys[me->hotkey] = me;
-
-      if ( ld->menudefault && !ld->menudisabled && !ld->menuseparator )
-       defentry = nentries;
-
-      nentries++;
-    }
-    else {
-      struct menu_entry *he;
+    if ( me->hotkey )
+      m->menu_hotkeys[me->hotkey] = me;
+    
+    if ( ld->menudefault && !ld->menudisabled && !ld->menuseparator )
+      m->defentry = m->nentries;
 
-      if (nhidden >= hide_entries_space) {
-       if (!hide_entries_space)
-         hide_entries_space = 1;
-       else
-         hide_entries_space <<= 1;
+    *all_entries_end = me;
+    all_entries_end = &me->next;
 
-       hide_entries = realloc(hide_entries,
-                              hide_entries_space*sizeof *hide_entries);
-      }
-      he = &hide_entries[nhidden];
-
-      he->displayname = me->displayname;
-      he->label       = me->label;
-      he->cmdline     = me->cmdline;
-      he->passwd      = me->passwd;
-
-      me->displayname = NULL;
-      me->label       = NULL;
-      me->cmdline     = NULL;
-      me->passwd      = NULL;
-
-      nhidden++;
-    }
+    m->nentries++;
   }
 }
 
@@ -327,7 +281,7 @@ unlabel(char *str)
   const char *p;
   char *q;
   struct menu_entry *me;
-  int i, pos;
+  int pos;
 
   p = str;
   while ( *p && !my_isspace(*p) )
@@ -336,24 +290,7 @@ unlabel(char *str)
   /* p now points to the first byte beyond the kernel name */
   pos = p-str;
 
-  for ( i = 0 ; i < nentries ; i++ ) {
-    me = &menu_entries[i];
-
-    if ( !strncmp(str, me->label, pos) && !me->label[pos] ) {
-      /* Found matching label */
-      q = malloc(strlen(me->cmdline) + strlen(p) + 1);
-      strcpy(q, me->cmdline);
-      strcat(q, p);
-
-      free(str);
-
-      return q;
-    }
-  }
-
-  for ( i = 0 ; i < nhidden ; i++ ) {
-    me = &hide_entries[i];
-
+  for ( me = all_entries ; me ; me = me->next ) {
     if ( !strncmp(str, me->label, pos) && !me->label[pos] ) {
       /* Found matching label */
       q = malloc(strlen(me->cmdline) + strlen(p) + 1);
@@ -490,7 +427,7 @@ static int parse_one_config(const char *filename);
 
 static char *is_kernel_type(char *cmdstr, enum kernel_type *type)
 {
-  const char **p;
+  const char * const *p;
   char *q;
   enum kernel_type t = KT_NONE;
 
@@ -504,14 +441,14 @@ static char *is_kernel_type(char *cmdstr, enum kernel_type *type)
   return NULL;
 }
 
-static char *is_message_name(char *cmdstr, struct messages **msgptr)
+static char *is_message_name(char *cmdstr, enum message_number *msgnr)
 {
   char *q;
-  int i;
+  enum message_number i;
 
   for (i = 0; i < MSG_COUNT; i++) {
     if ((q = looking_at(cmdstr, messages[i].name))) {
-      *msgptr = &messages[i];
+      *msgnr = i;
       return q;
     }
   }
@@ -538,12 +475,15 @@ static char *is_fkey(char *cmdstr, int *fkeyno)
   return q;
 }
 
+static struct menu *current_menu;
+
 static void parse_config_file(FILE *f)
 {
   char line[MAX_LINE], *p, *ep, ch;
   enum kernel_type type;
-  struct messages *msgptr;
+  enum message_number msgnr;
   int fkeyno;
+  struct menu *m = current_menu;
 
   while ( fgets(line, sizeof line, f) ) {
     p = strchr(line, '\r');
@@ -570,25 +510,29 @@ static void parse_config_file(FILE *f)
       } else if ( looking_at(p, "shiftkey") ) {
        shiftkey = 1;
       } else if ( looking_at(p, "onerror") ) {
-       onerror = strdup(skipspace(p+7));
+       m->onerror = strdup(skipspace(p+7));
       } else if ( looking_at(p, "master") ) {
        p = skipspace(p+6);
        if ( looking_at(p, "passwd") ) {
-         menu_master_passwd = strdup(skipspace(p+6));
+         /* XXX: need refcount */
+         m->menu_master_passwd = strdup(skipspace(p+6));
        }
       } else if ( (ep = looking_at(p, "include")) ) {
        p = skipspace(ep);
        parse_one_config(p);
       } else if ( (ep = looking_at(p, "background")) ) {
        p = skipspace(ep);
-       if (menu_background)
-         free(menu_background);
-       menu_background = dup_word(&p);
+       /* XXX: need refcount */
+       if (m->menu_background)
+         free(m->menu_background);
+       m->menu_background = dup_word(&p);
       } else if ( (ep = looking_at(p, "hidden")) ) {
        hiddenmenu = 1;
-      } else if ( (ep = is_message_name(p, &msgptr)) ) {
-       free(msgptr->msg);
-       msgptr->msg = strdup(skipspace(ep));
+      } else if ( (ep = is_message_name(p, &msgnr)) ) {
+       /* XXX: need refcount */
+       if (m->messages[msgnr])
+         free((void *)m->messages[msgnr]);
+       m->messages[msgnr] = strdup(skipspace(ep));
       } else if ((ep = looking_at(p, "color")) ||
                 (ep = looking_at(p, "colour"))) {
        int i;
@@ -674,13 +618,13 @@ static void parse_config_file(FILE *f)
            }
          }
        }
-       set_msg_colors_global(fg_mask, bg_mask, shadow);
+       set_msg_colors_global(m->color_table, fg_mask, bg_mask, shadow);
       } else if ( looking_at(p, "separator") ) {
-        record(&ld, append);
+        record(root_menu, &ld, append);
         memset(&ld, 0, sizeof(struct labeldata));
         ld.label = "";
        ld.menuseparator = 1;
-        record(&ld, append);
+        record(root_menu, &ld, append);
         memset(&ld, 0, sizeof(struct labeldata));
       } else if ( looking_at(p, "disable") ||
                  looking_at(p, "disabled")) {
@@ -689,10 +633,10 @@ static void parse_config_file(FILE *f)
         ld.menuindent = atoi(skipspace(p+6));
       } else {
        /* Unknown, check for layout parameters */
-       struct menu_parameter *pp;
-       for ( pp = mparm ; pp->name ; pp++ ) {
-         if ( (ep = looking_at(p, pp->name)) ) {
-           pp->value = atoi(skipspace(ep));
+       enum parameter_number mp;
+       for (mp = 0; mp < NPARAMS; mp++) {
+         if ( (ep = looking_at(p, mparm[mp].name)) ) {
+           m->mparm[mp] = atoi(skipspace(ep));
            break;
          }
        }
@@ -729,19 +673,23 @@ static void parse_config_file(FILE *f)
       }
     } else if ( (ep = is_fkey(p, &fkeyno)) ) {
       p = skipspace(ep);
-      if (fkeyhelp[fkeyno].textname) {
-       free((void *)fkeyhelp[fkeyno].textname);
-       fkeyhelp[fkeyno].textname = NULL;
+      if (m->fkeyhelp[fkeyno].textname) {
+       /* XXX: refcount */
+       free((void *)m->fkeyhelp[fkeyno].textname);
+       m->fkeyhelp[fkeyno].textname = NULL;
       }
-      if (fkeyhelp[fkeyno].background) {
-       free((void *)fkeyhelp[fkeyno].background);
-       fkeyhelp[fkeyno].background = NULL;
+      if (m->fkeyhelp[fkeyno].background) {
+       /* XXX: refcount */
+       free((void *)m->fkeyhelp[fkeyno].background);
+       m->fkeyhelp[fkeyno].background = NULL;
       }
 
-      fkeyhelp[fkeyno].textname = dup_word(&p);
+      /* XXX: refcount */
+      m->fkeyhelp[fkeyno].textname = dup_word(&p);
       if (*p) {
        p = skipspace(p);
-       fkeyhelp[fkeyno].background = dup_word(&p);
+       /* XXX: refcount */
+       m->fkeyhelp[fkeyno].background = dup_word(&p);
       }
     } else if ( (ep = looking_at(p, "include")) ) {
       p = skipspace(ep);
@@ -754,7 +702,7 @@ static void parse_config_file(FILE *f)
        append = a;
     } else if ( looking_at(p, "label") ) {
       p = skipspace(p+5);
-      record(&ld, append);
+      record(root_menu, &ld, append);
       ld.label     = strdup(p);
       ld.kernel    = strdup(p);
       ld.type      = KT_KERNEL;
@@ -772,13 +720,13 @@ static void parse_config_file(FILE *f)
        ld.type = type;
       }
     } else if ( looking_at(p, "timeout") ) {
-      timeout = (atoi(skipspace(p+7))*CLK_TCK+9)/10;
+      m->timeout = (atoi(skipspace(p+7))*CLK_TCK+9)/10;
     } else if ( looking_at(p, "totaltimeout") ) {
       totaltimeout = (atoll(skipspace(p+13))*CLK_TCK+9)/10;
     } else if ( looking_at(p, "ontimeout") ) {
-      ontimeout = strdup(skipspace(p+9));
+      m->ontimeout = strdup(skipspace(p+9));
     } else if ( looking_at(p, "allowoptions") ) {
-      allowedit = atoi(skipspace(p+12));
+      m->allowedit = atoi(skipspace(p+12));
     } else if ( looking_at(p, "ipappend") ) {
       if (ld.label)
         ld.ipappend = atoi(skipspace(p+8));
@@ -793,7 +741,7 @@ static int parse_one_config(const char *filename)
   FILE *f;
 
   if (!strcmp(filename, "~"))
-    filename = get_config();
+    filename = syslinux_config_file();
 
   f = fopen(filename, "r");
   if ( !f )
@@ -805,26 +753,39 @@ static int parse_one_config(const char *filename)
   return 0;
 }
 
+static void resolve_gotos(void)
+{
+  struct menu_entry *me;
+  struct menu *m;
+
+  for (me = all_entries; me; me = me->next) {
+    if (me->action == MA_GOTO_UNRES) {
+      m = find_menu(me->cmdline);
+      if (m) {
+       me->submenu = m;
+       me->action = MA_GOTO;
+      } else {
+       me->action = MA_DISABLED;
+      }
+    }
+  }
+}
+
 void parse_configs(char **argv)
 {
   const char *filename;
-  int i;
+  struct menu *m;
 
-  /* Initialize defaults */
-
-  for (i = 0; i < MSG_COUNT; i++) {
-    if (messages[i].msg)
-      free(messages[i].msg);
-    messages[i].msg = strdup(messages[i].defmsg);
-  }
+  /* Initialize defaults for the root and hidden menus */
+  hide_menu = new_menu(NULL, ".hidden");
+  root_menu = new_menu(NULL, ".top");
+  start_menu = root_menu;
 
   /* Other initialization */
-
-  get_ipappend();
   memset(&ld, 0, sizeof(struct labeldata));
 
   /* Actually process the files */
-
+  current_menu = root_menu;
   if ( !*argv ) {
     parse_one_config("~");
   } else {
@@ -833,13 +794,15 @@ void parse_configs(char **argv)
   }
 
   /* On final EOF process the last label statement */
-
-  record(&ld, append);
+  record(current_menu, &ld, append);
 
   /* Common postprocessing */
+  resolve_gotos();
 
-  if ( ontimeout )
-    ontimeout = unlabel(ontimeout);
-  if ( onerror )
-    onerror = unlabel(onerror);
+  for (m = menu_list; m; m = m->next) {
+    if ( m->ontimeout )
+      m->ontimeout = unlabel(m->ontimeout);
+    if ( m->onerror )
+      m->onerror = unlabel(m->onerror);
+  }
 }
index 745bc92..5f35729 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 #include "refstr.h"
 
-const char *refstr_mkn(const char *str, size_t len)
+const char *refstrndup(const char *str, size_t len)
 {
   char *r;
 
@@ -33,9 +34,9 @@ const char *refstr_mkn(const char *str, size_t len)
   return r;
 }
 
-const char *refstr_mk(const char *str)
+const char *refstrdup(const char *str)
 {
-  refstr *r;
+  char *r;
   size_t len;
 
   len = strlen(str);
@@ -47,10 +48,48 @@ const char *refstr_mk(const char *str)
   return r;
 }
 
+int vrsprintf(const char **bufp, const char *fmt, va_list ap)
+{
+  va_list ap1;
+  int bytes;
+  char *p;
+
+  va_copy(ap1, ap);
+  bytes = vsnprintf(NULL, 0, fmt, ap1)+1;
+  va_end(ap1);
+
+  p = malloc(bytes+sizeof(unsigned int));
+  if ( !p ) {
+    *bufp = NULL;
+    return -1;
+  }
+
+  *(unsigned int *)p = 1;
+  p += sizeof(unsigned int);
+
+  return vsnprintf(p, bytes, fmt, ap);
+}
+
+int rsprintf(const char **bufp, const char *fmt, ...)
+{
+  int rv;
+  va_list ap;
+
+  va_start(ap, fmt);
+  rv = vrsprintf(bufp, fmt, ap);
+  va_end(ap);
+
+  return rv;
+}
+
 void refstr_put(const char *r)
 {
-  unsigned int *ref = (unsigned int *)r - 1;
+  unsigned int *ref;
 
-  if (!--*ref)
-    free(ref);
+  if (r) {
+    ref = (unsigned int *)r - 1;
+    
+    if (!--*ref)
+      free(ref);
+  }
 }
index 93c9b0e..593b0ab 100644 (file)
@@ -20,6 +20,7 @@
 #define REFSTR_H
 
 #include <stddef.h>
+#include <stdarg.h>
 
 static inline const char *refstr_get(const char *r)
 {
@@ -28,8 +29,10 @@ static inline const char *refstr_get(const char *r)
   return r;
 }
 
-const char *refstr_mk(const char *);
-const char *refstr_mkn(const char *, size_t);
 void refstr_put(const char *);
+const char *refstrdup(const char *);
+const char *refstrndup(const char *, size_t);
+int rsprintf(const char **, const char *, ...);
+int vrsprintf(const char **, const char *, va_list);
 
 #endif