mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/2] rework menu so that it can support multiline titles
@ 2016-08-17  7:58 Aleksey Kuleshov
  2016-08-17  7:58 ` [PATCH 1/2] hush: do not do anything if string is zero length Aleksey Kuleshov
  2016-08-17  7:58 ` [PATCH 2/2] rework menu so that it can support multiline titles Aleksey Kuleshov
  0 siblings, 2 replies; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-17  7:58 UTC (permalink / raw)
  To: barebox; +Cc: Aleksey Kuleshov

Aleksey Kuleshov (2):
  hush: do not do anything if string is zero length
  rework menu so that it can support multiline titles

 commands/menu.c   | 14 +++++++---
 common/boot.c     |  8 ++++--
 common/hush.c     |  3 +++
 common/menu.c     | 78 +++++++++++++++++++++++++++++++++++++++++++++++++------
 common/menutree.c | 13 ++++++++--
 include/menu.h    |  8 +++++-
 6 files changed, 107 insertions(+), 17 deletions(-)

-- 
2.8.0.rc3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] hush: do not do anything if string is zero length
  2016-08-17  7:58 [PATCH 0/2] rework menu so that it can support multiline titles Aleksey Kuleshov
@ 2016-08-17  7:58 ` Aleksey Kuleshov
  2016-08-18  6:35   ` Sascha Hauer
  2016-08-17  7:58 ` [PATCH 2/2] rework menu so that it can support multiline titles Aleksey Kuleshov
  1 sibling, 1 reply; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-17  7:58 UTC (permalink / raw)
  To: barebox; +Cc: Aleksey Kuleshov

Signed-off-by: Aleksey Kuleshov <rndfax@yandex.ru>
---
 common/hush.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/hush.c b/common/hush.c
index d3f7bf3..d8fd64b 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1655,6 +1655,9 @@ char *shell_expand(char *str)
 	o_string o = {};
 	char *res, *parsed;
 
+	if (strlen(str) == 0)
+		return xstrdup("");
+
 	remove_quotes_in_str(str);
 
 	o.quote = 1;
-- 
2.8.0.rc3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/2] rework menu so that it can support multiline titles
  2016-08-17  7:58 [PATCH 0/2] rework menu so that it can support multiline titles Aleksey Kuleshov
  2016-08-17  7:58 ` [PATCH 1/2] hush: do not do anything if string is zero length Aleksey Kuleshov
@ 2016-08-17  7:58 ` Aleksey Kuleshov
  2016-08-18  7:11   ` Sascha Hauer
  1 sibling, 1 reply; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-17  7:58 UTC (permalink / raw)
  To: barebox; +Cc: Aleksey Kuleshov

Signed-off-by: Aleksey Kuleshov <rndfax@yandex.ru>
---
 commands/menu.c   | 14 +++++++---
 common/boot.c     |  8 ++++--
 common/menu.c     | 78 +++++++++++++++++++++++++++++++++++++++++++++++++------
 common/menutree.c | 13 ++++++++--
 include/menu.h    |  8 +++++-
 5 files changed, 104 insertions(+), 17 deletions(-)

diff --git a/commands/menu.c b/commands/menu.c
index e1079fd..d413020 100644
--- a/commands/menu.c
+++ b/commands/menu.c
@@ -146,9 +146,7 @@ static int do_menu_add(struct cmd_menu *cm)
 	if (!m->name)
 		goto free;
 
-	m->display = strdup(cm->description);
-	if (!m->display)
-		goto free;
+	menu_add_title(m, cm->description, NULL);
 
 	ret = menu_add(m);
 
@@ -271,7 +269,15 @@ static int do_menu_list(struct cmd_menu *cm)
 	}
 
 	list_for_each_entry(m, &menus->list, list) {
-		printf("%s: %s\n", m->name, m->display? m->display : m->name);
+		printf("%s: ", m->name);
+		if (m->display_lines) {
+			int i;
+			printf("\n");
+			for (i = 0; i < m->display_lines; i++)
+				printf("\t%s\n", m->display[i]);
+		} else {
+			printf("%s\n", m->name);
+		}
 		if (is_entry(cm))
 			print_entries(m);
 	}
diff --git a/common/boot.c b/common/boot.c
index e66bacb..a2f5a81 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -43,7 +43,7 @@ struct bootentries *bootentries_alloc(void)
 
 	if (IS_ENABLED(CONFIG_MENU)) {
 		bootentries->menu = menu_alloc();
-		bootentries->menu->display = basprintf("boot");
+		menu_add_title(bootentries->menu, "boot", NULL);
 	}
 
 	return bootentries;
@@ -61,8 +61,12 @@ void bootentries_free(struct bootentries *bootentries)
 		be->release(be);
 	}
 
-	if (bootentries->menu)
+	if (bootentries->menu) {
+		int i;
+		for (i = 0; i < bootentries->menu->display_lines; i++)
+			free(bootentries->menu->display[i]);
 		free(bootentries->menu->display);
+	}
 	free(bootentries->menu);
 	free(bootentries);
 }
diff --git a/common/menu.c b/common/menu.c
index 9819569..1f23e45 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -43,10 +43,13 @@ EXPORT_SYMBOL(menu_get_menus);
 void menu_free(struct menu *m)
 {
 	struct menu_entry *me, *tmp;
+	int i;
 
 	if (!m)
 		return;
 	free(m->name);
+	for (i = 0; i < m->display_lines; i++)
+		free(m->display[i]);
 	free(m->display);
 	free(m->auto_display);
 
@@ -164,7 +167,7 @@ static void __print_entry(const char *str)
 static void print_menu_entry(struct menu *m, struct menu_entry *me,
 			     int selected)
 {
-	gotoXY(3, me->num + 1);
+	gotoXY(3, me->num + m->display_lines + m->skip_lines);
 
 	if (me->type == MENU_ENTRY_BOX) {
 		if (me->box_state)
@@ -234,12 +237,19 @@ static void print_menu(struct menu *m)
 	struct menu_entry *me;
 
 	clear();
-	gotoXY(2, 1);
-	if(m->display) {
-		__print_entry(m->display);
+	if (m->display) {
+		int i;
+		for (i = 0; i < m->display_lines; i++) {
+			gotoXY(2, 1 + i);
+			__print_entry(m->display[i]);
+		}
+		m->skip_lines = 0;
 	} else {
+		gotoXY(2, 1);
 		puts("Menu : ");
-		puts(m->name);
+		if (m->name)
+			puts(m->name);
+		m->skip_lines = 1;
 	}
 
 	list_for_each_entry(me, &m->entries, list) {
@@ -269,7 +279,7 @@ int menu_show(struct menu *m)
 
 	countdown = m->auto_select;
 	if (m->auto_select >= 0) {
-		gotoXY(3, m->nb_entries + 2);
+		gotoXY(3, m->nb_entries + m->display_lines + m->skip_lines + 1);
 		if (!m->auto_display) {
 			printf("Auto Select in");
 		} else {
@@ -293,10 +303,10 @@ int menu_show(struct menu *m)
 		}
 	}
 
-	gotoXY(3, m->nb_entries + 2);
+	gotoXY(3, m->nb_entries + m->display_lines + m->skip_lines + 1);
 	printf("%*c", auto_display_len + 4, ' ');
 
-	gotoXY(3, m->selected->num + 1);
+	gotoXY(3, m->selected->num + m->display_lines + m->skip_lines);
 
 	do {
 		struct menu_entry *old_selected = m->selected;
@@ -517,3 +527,55 @@ err_free:
 	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(menu_add_command_entry);
+
+/*
+ * Add multiline title to menu applying (if not NULL) parser to each line.
+ * Symbols "\\n" and '\n' ARE newline indicators.
+ */
+void menu_add_title(struct menu *m, const char *display, char *(*parser)(char *str))
+{
+	char *tmp, *src, *dst;
+	int lines = 1;
+	int i;
+
+	if (!strlen(display))
+		return;
+
+	src = dst = tmp = xstrdup(display);
+	/* Count lines and separate single string into multiple strings */
+	while (*src) {
+		if (*src == '\\') {
+			if (*(src + 1) == 'n') {
+				*dst = 0;
+				src += 2;
+				dst++;
+				lines++;
+				continue;
+			}
+		}
+		if (*src == '\n') {
+			*dst = 0;
+			src++;
+			dst++;
+			lines++;
+			continue;
+		}
+		*dst++ = *src++;
+	}
+	*dst = 0;
+
+	m->display = xzalloc(sizeof(*m->display) * lines);
+	m->display_lines = lines;
+
+	for (src = tmp, i = 0; i < lines; i++) {
+		if (parser)
+			m->display[i] = parser(src);
+		else
+			m->display[i] = xstrdup(src);
+		/* Go to the next line */
+		src += strlen(src) + 1;
+	}
+
+	free(tmp);
+}
+EXPORT_SYMBOL(menu_add_title);
diff --git a/common/menutree.c b/common/menutree.c
index eb14da0..e2d364d 100644
--- a/common/menutree.c
+++ b/common/menutree.c
@@ -19,6 +19,7 @@
 #include <shell.h>
 #include <libfile.h>
 
+#include <linux/ctype.h>
 #include <linux/stat.h>
 
 struct menutree {
@@ -95,6 +96,7 @@ int menutree(const char *path, int toplevel)
 	glob_t g;
 	int i;
 	char *globpath, *display;
+	size_t size;
 
 	menu = menu_alloc();
 
@@ -106,14 +108,21 @@ int menutree(const char *path, int toplevel)
 		goto out;
 	}
 
-	display = read_file_line("%s/title", path);
+	globpath = basprintf("%s/title", path);
+	display = read_file(globpath, &size);
+	/* Remove trailing whitespaces */
+	while (size > 0 && isspace(display[size - 1]))
+		size--;
+	display[size] = '\0';
+	free(globpath);
 	if (!display) {
 		eprintf("no title found in %s/title\n", path);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	menu->display = shell_expand(display);
+	menu_add_title(menu, display, shell_expand);
+
 	free(display);
 
 	for (i = 0; i < g.gl_pathc; i++) {
diff --git a/include/menu.h b/include/menu.h
index 8b0ffb1..cc3ac5f 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -47,7 +47,12 @@ struct menu_entry {
 
 struct menu {
 	char *name;
-	char *display;
+	/* Multiline title */
+	char **display;
+	/* Number of lines */
+	int display_lines;
+	/* Private state for proper rendering when display_lines == 0 */
+	int skip_lines;
 
 	int auto_select;
 	char *auto_display;
@@ -88,6 +93,7 @@ int menu_set_selected_entry(struct menu *m, struct menu_entry* me);
 int menu_set_selected(struct menu *m, int num);
 int menu_set_auto_select(struct menu *m, int delay);
 struct menu* menu_get_menus(void);
+void menu_add_title(struct menu *m, const char *display, char *(*parser)(char *str));
 
 /*
  * menu entry functions
-- 
2.8.0.rc3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] hush: do not do anything if string is zero length
  2016-08-17  7:58 ` [PATCH 1/2] hush: do not do anything if string is zero length Aleksey Kuleshov
@ 2016-08-18  6:35   ` Sascha Hauer
  2016-08-18  8:52     ` Aleksey Kuleshov
  0 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2016-08-18  6:35 UTC (permalink / raw)
  To: Aleksey Kuleshov; +Cc: barebox

Hi Aleksey,

On Wed, Aug 17, 2016 at 10:58:06AM +0300, Aleksey Kuleshov wrote:
> Signed-off-by: Aleksey Kuleshov <rndfax@yandex.ru>
> ---
>  common/hush.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/common/hush.c b/common/hush.c
> index d3f7bf3..d8fd64b 100644
> --- a/common/hush.c
> +++ b/common/hush.c
> @@ -1655,6 +1655,9 @@ char *shell_expand(char *str)
>  	o_string o = {};
>  	char *res, *parsed;
>  
> +	if (strlen(str) == 0)
> +		return xstrdup("");
> +

Can you explain why this is necessary? What happens with an empty string
without this patch?

Sascha

>  	remove_quotes_in_str(str);
>  
>  	o.quote = 1;
> -- 
> 2.8.0.rc3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] rework menu so that it can support multiline titles
  2016-08-17  7:58 ` [PATCH 2/2] rework menu so that it can support multiline titles Aleksey Kuleshov
@ 2016-08-18  7:11   ` Sascha Hauer
  2016-08-18  9:36     ` Aleksey Kuleshov
  2016-08-18 11:24     ` Aleksey Kuleshov
  0 siblings, 2 replies; 10+ messages in thread
From: Sascha Hauer @ 2016-08-18  7:11 UTC (permalink / raw)
  To: Aleksey Kuleshov; +Cc: barebox

Hi Aleksey,

See comments inline.

On Wed, Aug 17, 2016 at 10:58:07AM +0300, Aleksey Kuleshov wrote:
> Signed-off-by: Aleksey Kuleshov <rndfax@yandex.ru>
> ---
>  commands/menu.c   | 14 +++++++---
>  common/boot.c     |  8 ++++--
>  common/menu.c     | 78 +++++++++++++++++++++++++++++++++++++++++++++++++------
>  common/menutree.c | 13 ++++++++--
>  include/menu.h    |  8 +++++-
>  5 files changed, 104 insertions(+), 17 deletions(-)
> 
> diff --git a/commands/menu.c b/commands/menu.c
> index e1079fd..d413020 100644
> --- a/commands/menu.c
> +++ b/commands/menu.c
> @@ -146,9 +146,7 @@ static int do_menu_add(struct cmd_menu *cm)
>  	if (!m->name)
>  		goto free;
>  
> -	m->display = strdup(cm->description);
> -	if (!m->display)
> -		goto free;
> +	menu_add_title(m, cm->description, NULL);
>  
>  	ret = menu_add(m);
>  
> @@ -271,7 +269,15 @@ static int do_menu_list(struct cmd_menu *cm)
>  	}
>  
>  	list_for_each_entry(m, &menus->list, list) {
> -		printf("%s: %s\n", m->name, m->display? m->display : m->name);
> +		printf("%s: ", m->name);
> +		if (m->display_lines) {
> +			int i;
> +			printf("\n");
> +			for (i = 0; i < m->display_lines; i++)
> +				printf("\t%s\n", m->display[i]);
> +		} else {
> +			printf("%s\n", m->name);
> +		}
>  		if (is_entry(cm))
>  			print_entries(m);
>  	}
> diff --git a/common/boot.c b/common/boot.c
> index e66bacb..a2f5a81 100644
> --- a/common/boot.c
> +++ b/common/boot.c
> @@ -43,7 +43,7 @@ struct bootentries *bootentries_alloc(void)
>  
>  	if (IS_ENABLED(CONFIG_MENU)) {
>  		bootentries->menu = menu_alloc();
> -		bootentries->menu->display = basprintf("boot");
> +		menu_add_title(bootentries->menu, "boot", NULL);
>  	}
>  
>  	return bootentries;
> @@ -61,8 +61,12 @@ void bootentries_free(struct bootentries *bootentries)
>  		be->release(be);
>  	}
>  
> -	if (bootentries->menu)
> +	if (bootentries->menu) {
> +		int i;
> +		for (i = 0; i < bootentries->menu->display_lines; i++)
> +			free(bootentries->menu->display[i]);
>  		free(bootentries->menu->display);
> +	}
>  	free(bootentries->menu);
>  	free(bootentries);
>  }
> diff --git a/common/menu.c b/common/menu.c
> index 9819569..1f23e45 100644
> --- a/common/menu.c
> +++ b/common/menu.c
> @@ -43,10 +43,13 @@ EXPORT_SYMBOL(menu_get_menus);
>  void menu_free(struct menu *m)
>  {
>  	struct menu_entry *me, *tmp;
> +	int i;
>  
>  	if (!m)
>  		return;
>  	free(m->name);
> +	for (i = 0; i < m->display_lines; i++)
> +		free(m->display[i]);
>  	free(m->display);
>  	free(m->auto_display);
>  
> @@ -164,7 +167,7 @@ static void __print_entry(const char *str)
>  static void print_menu_entry(struct menu *m, struct menu_entry *me,
>  			     int selected)
>  {
> -	gotoXY(3, me->num + 1);
> +	gotoXY(3, me->num + m->display_lines + m->skip_lines);
>  
>  	if (me->type == MENU_ENTRY_BOX) {
>  		if (me->box_state)
> @@ -234,12 +237,19 @@ static void print_menu(struct menu *m)
>  	struct menu_entry *me;
>  
>  	clear();
> -	gotoXY(2, 1);
> -	if(m->display) {
> -		__print_entry(m->display);
> +	if (m->display) {
> +		int i;
> +		for (i = 0; i < m->display_lines; i++) {
> +			gotoXY(2, 1 + i);
> +			__print_entry(m->display[i]);
> +		}
> +		m->skip_lines = 0;
>  	} else {
> +		gotoXY(2, 1);
>  		puts("Menu : ");
> -		puts(m->name);
> +		if (m->name)
> +			puts(m->name);
> +		m->skip_lines = 1;
>  	}

We could add this to menu_add():

       if (!m->display)
               m->display = xasprintf("Menu : %s", m->name);

Then we wouldn't need the if(m->display) here. Would that simplify the
code?

I haven't really understood why the m->skip_lines is necessary, but I
think it should be removed by making the if/else above unnecessary.

>  
>  	list_for_each_entry(me, &m->entries, list) {
> @@ -269,7 +279,7 @@ int menu_show(struct menu *m)
>  
>  	countdown = m->auto_select;
>  	if (m->auto_select >= 0) {
> -		gotoXY(3, m->nb_entries + 2);
> +		gotoXY(3, m->nb_entries + m->display_lines + m->skip_lines + 1);
>  		if (!m->auto_display) {
>  			printf("Auto Select in");
>  		} else {
> @@ -293,10 +303,10 @@ int menu_show(struct menu *m)
>  		}
>  	}
>  
> -	gotoXY(3, m->nb_entries + 2);
> +	gotoXY(3, m->nb_entries + m->display_lines + m->skip_lines + 1);
>  	printf("%*c", auto_display_len + 4, ' ');
>  
> -	gotoXY(3, m->selected->num + 1);
> +	gotoXY(3, m->selected->num + m->display_lines + m->skip_lines);
>  
>  	do {
>  		struct menu_entry *old_selected = m->selected;
> @@ -517,3 +527,55 @@ err_free:
>  	return ERR_PTR(ret);
>  }
>  EXPORT_SYMBOL(menu_add_command_entry);
> +
> +/*
> + * Add multiline title to menu applying (if not NULL) parser to each line.
> + * Symbols "\\n" and '\n' ARE newline indicators.
> + */
> +void menu_add_title(struct menu *m, const char *display, char *(*parser)(char *str))
> +{
> +	char *tmp, *src, *dst;
> +	int lines = 1;
> +	int i;
> +
> +	if (!strlen(display))
> +		return;
> +
> +	src = dst = tmp = xstrdup(display);
> +	/* Count lines and separate single string into multiple strings */
> +	while (*src) {
> +		if (*src == '\\') {
> +			if (*(src + 1) == 'n') {
> +				*dst = 0;
> +				src += 2;
> +				dst++;
> +				lines++;
> +				continue;
> +			}
> +		}
> +		if (*src == '\n') {
> +			*dst = 0;
> +			src++;
> +			dst++;
> +			lines++;
> +			continue;
> +		}
> +		*dst++ = *src++;
> +	}
> +	*dst = 0;
> +
> +	m->display = xzalloc(sizeof(*m->display) * lines);
> +	m->display_lines = lines;
> +
> +	for (src = tmp, i = 0; i < lines; i++) {
> +		if (parser)
> +			m->display[i] = parser(src);
> +		else
> +			m->display[i] = xstrdup(src);

What's the reason for running parser() over the separated strings? Can't
you run parser() over the original multiline string instead? What if one
of the variables expanded in shell_expand() contains a newline
character?

> +		/* Go to the next line */
> +		src += strlen(src) + 1;
> +	}
> +
> +	free(tmp);
> +}
> +EXPORT_SYMBOL(menu_add_title);
> diff --git a/common/menutree.c b/common/menutree.c
> index eb14da0..e2d364d 100644
> --- a/common/menutree.c
> +++ b/common/menutree.c
> @@ -19,6 +19,7 @@
>  #include <shell.h>
>  #include <libfile.h>
>  
> +#include <linux/ctype.h>
>  #include <linux/stat.h>
>  
>  struct menutree {
> @@ -95,6 +96,7 @@ int menutree(const char *path, int toplevel)
>  	glob_t g;
>  	int i;
>  	char *globpath, *display;
> +	size_t size;
>  
>  	menu = menu_alloc();
>  
> @@ -106,14 +108,21 @@ int menutree(const char *path, int toplevel)
>  		goto out;
>  	}
>  
> -	display = read_file_line("%s/title", path);
> +	globpath = basprintf("%s/title", path);
> +	display = read_file(globpath, &size);
> +	/* Remove trailing whitespaces */
> +	while (size > 0 && isspace(display[size - 1]))
> +		size--;

We have the strim() function for this purpose.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] hush: do not do anything if string is zero length
  2016-08-18  6:35   ` Sascha Hauer
@ 2016-08-18  8:52     ` Aleksey Kuleshov
  0 siblings, 0 replies; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-18  8:52 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

>>  diff --git a/common/hush.c b/common/hush.c
>>  index d3f7bf3..d8fd64b 100644
>>  --- a/common/hush.c
>>  +++ b/common/hush.c
>>  @@ -1655,6 +1655,9 @@ char *shell_expand(char *str)
>>           o_string o = {};
>>           char *res, *parsed;
>>
>>  + if (strlen(str) == 0)
>>  + return xstrdup("");
>>  +
>
> Can you explain why this is necessary? What happens with an empty string
> without this patch?

/*
 * shell_expand - Expand shell variables in a string.
 * @str:        The input string containing shell variables like
 *              $var or ${var}
 * Return:      The expanded string. Must be freed with free().
 */

If shell_expand should be called _only_ with string containing _at least one_ $var or ${var} then this patch is wrong.
And since shell_expand is called only from menutree.c then it's menutree.c's responsibility to verify the string.

Otherwise:
If you pass zero length string (i.e. shell_expand("")) you will end up with "Segmentation Fault"
because this line:

        parse_string(&o, &ctx, str);

will give you o.data = NULL
and then comes this line:

        parsed = xmemdup(o.data, o.length + 1);

PS. And if you will not fill 'title' file for menu with some data you will get "Segmentation Fault".

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] rework menu so that it can support multiline titles
  2016-08-18  7:11   ` Sascha Hauer
@ 2016-08-18  9:36     ` Aleksey Kuleshov
  2016-08-18 10:26       ` Sascha Hauer
  2016-08-18 11:24     ` Aleksey Kuleshov
  1 sibling, 1 reply; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-18  9:36 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

>>  @@ -234,12 +237,19 @@ static void print_menu(struct menu *m)
>>           struct menu_entry *me;
>>
>>           clear();
>>  - gotoXY(2, 1);
>>  - if(m->display) {
>>  - __print_entry(m->display);
>>  + if (m->display) {
>>  + int i;
>>  + for (i = 0; i < m->display_lines; i++) {
>>  + gotoXY(2, 1 + i);
>>  + __print_entry(m->display[i]);
>>  + }
>>  + m->skip_lines = 0;
>>           } else {
>>  + gotoXY(2, 1);
>>                   puts("Menu : ");
>>  - puts(m->name);
>>  + if (m->name)
>>  + puts(m->name);
>>  + m->skip_lines = 1;
>>           }
>
> We could add this to menu_add():
>
>        if (!m->display)
>                m->display = xasprintf("Menu : %s", m->name);
>
> Then we wouldn't need the if(m->display) here. Would that simplify the
> code?

Yes. But all title things are go into menu_add_titile, so how about this:

diff --git a/common/menu.c b/common/menu.c
index 1f23e45..636c2b8 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -235,21 +235,12 @@ EXPORT_SYMBOL(menu_set_auto_select);
 static void print_menu(struct menu *m)
 {
        struct menu_entry *me;
+       int i;

        clear();
-       if (m->display) {
-               int i;
-               for (i = 0; i < m->display_lines; i++) {
-                       gotoXY(2, 1 + i);
-                       __print_entry(m->display[i]);
-               }
-               m->skip_lines = 0;
-       } else {
-               gotoXY(2, 1);
-               puts("Menu : ");
-               if (m->name)
-                       puts(m->name);
-               m->skip_lines = 1;
+       for (i = 0; i < m->display_lines; i++) {
+               gotoXY(2, 1 + i);
+               __print_entry(m->display[i]);
        }

        list_for_each_entry(me, &m->entries, list) {
@@ -538,8 +529,12 @@ void menu_add_title(struct menu *m, const char *display, char *(*parser)(char *s
        int lines = 1;
        int i;

-       if (!strlen(display))
+       if (!strlen(display)) {
+               m->display_lines = 1;
+               m->display = xzalloc(sizeof(*m->display));
+               m->display[0] = xasprintf("Menu : %s", m->name ? m->name : "");
                return;
+       }

        src = dst = tmp = xstrdup(display);
        /* Count lines and separate single string into multiple strings */

+ remove skip_lines everywhere.

> I haven't really understood why the m->skip_lines is necessary, but I
> think it should be removed by making the if/else above unnecessary.

For proper spacing. But yes, it can be removed with patch above.

>>  + for (src = tmp, i = 0; i < lines; i++) {
>>  + if (parser)
>>  + m->display[i] = parser(src);
>>  + else
>>  + m->display[i] = xstrdup(src);
>
> What's the reason for running parser() over the separated strings? Can't
> you run parser() over the original multiline string instead?

I wanted to consume more CPU cycles so that the Earth will suffer from power starvation. But you ruined my evil plan, clap-clap-clap.

> What if one of the variables expanded in shell_expand() contains a newline
> character?

It will be incorrect rendering. C u in patch v2 series.

>
>>  + /* Go to the next line */
>>  + src += strlen(src) + 1;
>>  + }
>>  +
>>  + free(tmp);
>>  +}
>>  +EXPORT_SYMBOL(menu_add_title);
>>  diff --git a/common/menutree.c b/common/menutree.c
>>  index eb14da0..e2d364d 100644
>>  --- a/common/menutree.c
>>  +++ b/common/menutree.c
>>  @@ -19,6 +19,7 @@
>>   #include <shell.h>
>>   #include <libfile.h>
>>
>>  +#include <linux/ctype.h>
>>   #include <linux/stat.h>
>>
>>   struct menutree {
>>  @@ -95,6 +96,7 @@ int menutree(const char *path, int toplevel)
>>           glob_t g;
>>           int i;
>>           char *globpath, *display;
>>  + size_t size;
>>
>>           menu = menu_alloc();
>>
>>  @@ -106,14 +108,21 @@ int menutree(const char *path, int toplevel)
>>                   goto out;
>>           }
>>
>>  - display = read_file_line("%s/title", path);
>>  + globpath = basprintf("%s/title", path);
>>  + display = read_file(globpath, &size);
>>  + /* Remove trailing whitespaces */
>>  + while (size > 0 && isspace(display[size - 1]))
>>  + size--;
>
> We have the strim() function for this purpose.

 * strim - Removes leading and trailing whitespace from @s.

And mine does only:
>>  + /* Remove trailing whitespaces */

Because it's necessary to preserve identation in multiline title so that barebox will be able to display such text:
Barebox boot loader
Board: SomeSuperBoard
    CPU: ARMv8 @800MHz
    Mem: 512MB

Menu:
    ....

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] rework menu so that it can support multiline titles
  2016-08-18  9:36     ` Aleksey Kuleshov
@ 2016-08-18 10:26       ` Sascha Hauer
  2016-08-18 10:48         ` Aleksey Kuleshov
  0 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2016-08-18 10:26 UTC (permalink / raw)
  To: Aleksey Kuleshov; +Cc: barebox

On Thu, Aug 18, 2016 at 12:36:29PM +0300, Aleksey Kuleshov wrote:
> >>  @@ -234,12 +237,19 @@ static void print_menu(struct menu *m)
> >>           struct menu_entry *me;
> >>
> >>           clear();
> >>  - gotoXY(2, 1);
> >>  - if(m->display) {
> >>  - __print_entry(m->display);
> >>  + if (m->display) {
> >>  + int i;
> >>  + for (i = 0; i < m->display_lines; i++) {
> >>  + gotoXY(2, 1 + i);
> >>  + __print_entry(m->display[i]);
> >>  + }
> >>  + m->skip_lines = 0;
> >>           } else {
> >>  + gotoXY(2, 1);
> >>                   puts("Menu : ");
> >>  - puts(m->name);
> >>  + if (m->name)
> >>  + puts(m->name);
> >>  + m->skip_lines = 1;
> >>           }
> >
> > We could add this to menu_add():
> >
> >        if (!m->display)
> >                m->display = xasprintf("Menu : %s", m->name);
> >
> > Then we wouldn't need the if(m->display) here. Would that simplify the
> > code?
> 
> Yes. But all title things are go into menu_add_titile, so how about this:
> 
> diff --git a/common/menu.c b/common/menu.c
> index 1f23e45..636c2b8 100644
> --- a/common/menu.c
> +++ b/common/menu.c
> @@ -235,21 +235,12 @@ EXPORT_SYMBOL(menu_set_auto_select);
>  static void print_menu(struct menu *m)
>  {
>         struct menu_entry *me;
> +       int i;
> 
>         clear();
> -       if (m->display) {
> -               int i;
> -               for (i = 0; i < m->display_lines; i++) {
> -                       gotoXY(2, 1 + i);
> -                       __print_entry(m->display[i]);
> -               }
> -               m->skip_lines = 0;
> -       } else {
> -               gotoXY(2, 1);
> -               puts("Menu : ");
> -               if (m->name)
> -                       puts(m->name);
> -               m->skip_lines = 1;
> +       for (i = 0; i < m->display_lines; i++) {
> +               gotoXY(2, 1 + i);
> +               __print_entry(m->display[i]);
>         }
> 
>         list_for_each_entry(me, &m->entries, list) {
> @@ -538,8 +529,12 @@ void menu_add_title(struct menu *m, const char *display, char *(*parser)(char *s
>         int lines = 1;
>         int i;
> 
> -       if (!strlen(display))
> +       if (!strlen(display)) {
> +               m->display_lines = 1;
> +               m->display = xzalloc(sizeof(*m->display));
> +               m->display[0] = xasprintf("Menu : %s", m->name ? m->name : "");
>                 return;
> +       }

Ok, looks good.

> > What's the reason for running parser() over the separated strings? Can't
> > you run parser() over the original multiline string instead?
> 
> I wanted to consume more CPU cycles so that the Earth will suffer from power starvation. But you ruined my evil plan, clap-clap-clap.

Yes, strike! ;)

> >>
> >>  - display = read_file_line("%s/title", path);
> >>  + globpath = basprintf("%s/title", path);
> >>  + display = read_file(globpath, &size);
> >>  + /* Remove trailing whitespaces */
> >>  + while (size > 0 && isspace(display[size - 1]))
> >>  + size--;
> >
> > We have the strim() function for this purpose.
> 
>  * strim - Removes leading and trailing whitespace from @s.
> 
> And mine does only:
> >>  + /* Remove trailing whitespaces */

You can use strim for both cases:

	str = strim(str);

removes both leading and trailing whitespaces, but without reassigning
str to the return value of strim() you only remove trailing whitespaces.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] rework menu so that it can support multiline titles
  2016-08-18 10:26       ` Sascha Hauer
@ 2016-08-18 10:48         ` Aleksey Kuleshov
  0 siblings, 0 replies; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-18 10:48 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

>>  > We have the strim() function for this purpose.
>>
>>   * strim - Removes leading and trailing whitespace from @s.
>>
>>  And mine does only:
>>  >> + /* Remove trailing whitespaces */
>
> You can use strim for both cases:
>
>         str = strim(str);
>
> removes both leading and trailing whitespaces, but without reassigning
> str to the return value of strim() you only remove trailing whitespaces.

Well, this is rather hack than normal using.
Because this way of using has nothing to do with the description:

 * strim - Removes leading and trailing whitespace from @s.
 * @s: The string to be stripped.
 * Returns a pointer to the first non-whitespace character in @s.

Here is the patch which removes this misunderstanding:

diff --git a/lib/string.c b/lib/string.c
index a3e9fd8..1d491c9 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -641,7 +641,7 @@ char *skip_spaces(const char *str)
 }

 /**
- * strim - Removes leading and trailing whitespace from @s.
+ * strim - Removes trailing whitespace from @s.
  * @s: The string to be stripped.
  *
  * Note that the first trailing whitespace is replaced with a %NUL-terminator

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] rework menu so that it can support multiline titles
  2016-08-18  7:11   ` Sascha Hauer
  2016-08-18  9:36     ` Aleksey Kuleshov
@ 2016-08-18 11:24     ` Aleksey Kuleshov
  1 sibling, 0 replies; 10+ messages in thread
From: Aleksey Kuleshov @ 2016-08-18 11:24 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

>>  + for (src = tmp, i = 0; i < lines; i++) {
>>  + if (parser)
>>  + m->display[i] = parser(src);
>>  + else
>>  + m->display[i] = xstrdup(src);
>
> What's the reason for running parser() over the separated strings? Can't
> you run parser() over the original multiline string instead?

For example, shell_expand removes '\n' from the string making it just ' ' (space).
So, to not lose this information parser apllies to every single already expanded string.

But with new patch I'm working on this will be unnecessary.
menu_add_title will do only one thing: adding the title (which can be miltilined) and nothing else.

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-08-18 11:24 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-17  7:58 [PATCH 0/2] rework menu so that it can support multiline titles Aleksey Kuleshov
2016-08-17  7:58 ` [PATCH 1/2] hush: do not do anything if string is zero length Aleksey Kuleshov
2016-08-18  6:35   ` Sascha Hauer
2016-08-18  8:52     ` Aleksey Kuleshov
2016-08-17  7:58 ` [PATCH 2/2] rework menu so that it can support multiline titles Aleksey Kuleshov
2016-08-18  7:11   ` Sascha Hauer
2016-08-18  9:36     ` Aleksey Kuleshov
2016-08-18 10:26       ` Sascha Hauer
2016-08-18 10:48         ` Aleksey Kuleshov
2016-08-18 11:24     ` Aleksey Kuleshov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox