[cloud] Allow aws-import script to run on Python 3.6
[ipxe.git] / src / core / menu.c
1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /** @file
27 *
28 * Menu selection
29 *
30 */
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <ipxe/list.h>
36 #include <ipxe/menu.h>
37
38 /** List of all menus */
39 static LIST_HEAD ( menus );
40
41 /**
42 * Create menu
43 *
44 * @v name Menu name, or NULL
45 * @v title Menu title, or NULL
46 * @ret menu Menu, or NULL on failure
47 */
48 struct menu * create_menu ( const char *name, const char *title ) {
49 size_t name_len;
50 size_t title_len;
51 size_t len;
52 struct menu *menu;
53 char *name_copy;
54 char *title_copy;
55
56 /* Destroy any existing menu of this name */
57 menu = find_menu ( name );
58 if ( menu )
59 destroy_menu ( menu );
60
61 /* Use empty title if none given */
62 if ( ! title )
63 title = "";
64
65 /* Allocate menu */
66 name_len = ( name ? ( strlen ( name ) + 1 /* NUL */ ) : 0 );
67 title_len = ( strlen ( title ) + 1 /* NUL */ );
68 len = ( sizeof ( *menu ) + name_len + title_len );
69 menu = zalloc ( len );
70 if ( ! menu )
71 return NULL;
72 name_copy = ( ( void * ) ( menu + 1 ) );
73 title_copy = ( name_copy + name_len );
74
75 /* Initialise menu */
76 if ( name ) {
77 strcpy ( name_copy, name );
78 menu->name = name_copy;
79 }
80 strcpy ( title_copy, title );
81 menu->title = title_copy;
82 INIT_LIST_HEAD ( &menu->items );
83
84 /* Add to list of menus */
85 list_add_tail ( &menu->list, &menus );
86
87 DBGC ( menu, "MENU %s created with title \"%s\"\n",
88 menu->name, menu->title );
89
90 return menu;
91 }
92
93 /**
94 * Add menu item
95 *
96 * @v menu Menu
97 * @v label Label, or NULL
98 * @v text Text, or NULL
99 * @v shortcut Shortcut key
100 * @v is_default Item is the default item
101 * @ret item Menu item, or NULL on failure
102 */
103 struct menu_item * add_menu_item ( struct menu *menu, const char *label,
104 const char *text, int shortcut,
105 int is_default ) {
106 size_t label_len;
107 size_t text_len;
108 size_t len;
109 struct menu_item *item;
110 char *label_copy;
111 char *text_copy;
112
113 /* Use empty text if none given */
114 if ( ! text )
115 text = "";
116
117 /* Allocate item */
118 label_len = ( label ? ( strlen ( label ) + 1 /* NUL */ ) : 0 );
119 text_len = ( strlen ( text ) + 1 /* NUL */ );
120 len = ( sizeof ( *item ) + label_len + text_len );
121 item = zalloc ( len );
122 if ( ! item )
123 return NULL;
124 label_copy = ( ( void * ) ( item + 1 ) );
125 text_copy = ( label_copy + label_len );
126
127 /* Initialise item */
128 if ( label ) {
129 strcpy ( label_copy, label );
130 item->label = label_copy;
131 }
132 strcpy ( text_copy, text );
133 item->text = text_copy;
134 item->shortcut = shortcut;
135 item->is_default = is_default;
136
137 /* Add to list of items */
138 list_add_tail ( &item->list, &menu->items );
139
140 return item;
141 }
142
143 /**
144 * Destroy menu
145 *
146 * @v menu Menu
147 */
148 void destroy_menu ( struct menu *menu ) {
149 struct menu_item *item;
150 struct menu_item *tmp;
151
152 /* Remove from list of menus */
153 list_del ( &menu->list );
154
155 /* Free items */
156 list_for_each_entry_safe ( item, tmp, &menu->items, list ) {
157 list_del ( &item->list );
158 free ( item );
159 }
160
161 /* Free menu */
162 free ( menu );
163 }
164
165 /**
166 * Find menu
167 *
168 * @v name Menu name, or NULL
169 * @ret menu Menu, or NULL if not found
170 */
171 struct menu * find_menu ( const char *name ) {
172 struct menu *menu;
173
174 list_for_each_entry ( menu, &menus, list ) {
175 if ( ( menu->name == name ) ||
176 ( strcmp ( menu->name, name ) == 0 ) ) {
177 return menu;
178 }
179 }
180
181 return NULL;
182 }