Module Name:    src
Committed By:   martin
Date:           Wed Nov 21 20:04:48 UTC 2018

Modified Files:
        src/usr.bin/menuc: defs.h mdb.c mdb.h menu_sys.def menuc.1 parse.y
            scan.l

Log Message:
Add (optional) support for expanded static menu texts - that is: whatever
the application programmer defines as expansion, e.g. to implement
parameter substitution.
While here add rudimentary documentation of the dynamic messages
feature (so at least the parser and the syntax documented here
are in sync).
The man page could use some typesetting help...


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/menuc/defs.h
cvs rdiff -u -r1.46 -r1.47 src/usr.bin/menuc/mdb.c
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/menuc/mdb.h
cvs rdiff -u -r1.59 -r1.60 src/usr.bin/menuc/menu_sys.def
cvs rdiff -u -r1.31 -r1.32 src/usr.bin/menuc/menuc.1
cvs rdiff -u -r1.16 -r1.17 src/usr.bin/menuc/parse.y src/usr.bin/menuc/scan.l

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/menuc/defs.h
diff -u src/usr.bin/menuc/defs.h:1.10 src/usr.bin/menuc/defs.h:1.11
--- src/usr.bin/menuc/defs.h:1.10	Fri Oct 18 20:19:36 2013
+++ src/usr.bin/menuc/defs.h	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: defs.h,v 1.10 2013/10/18 20:19:36 christos Exp $	 */
+/*	$NetBSD: defs.h,v 1.11 2018/11/21 20:04:48 martin Exp $	 */
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -65,6 +65,7 @@ EXTERN char *sys_name INIT("menu_sys.def
 
 EXTERN int do_dynamic INIT(0);
 EXTERN int do_msgxlat INIT(0);
+EXTERN int do_expands INIT(0);
 EXTERN int line_no INIT(1);
 EXTERN int had_errors INIT(FALSE);
 EXTERN int max_strlen INIT(1);

Index: src/usr.bin/menuc/mdb.c
diff -u src/usr.bin/menuc/mdb.c:1.46 src/usr.bin/menuc/mdb.c:1.47
--- src/usr.bin/menuc/mdb.c:1.46	Tue Mar  6 16:55:18 2012
+++ src/usr.bin/menuc/mdb.c	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdb.c,v 1.46 2012/03/06 16:55:18 mbalmer Exp $	*/
+/*	$NetBSD: mdb.c,v 1.47 2018/11/21 20:04:48 martin Exp $	*/
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -41,7 +41,7 @@
 #include <sys/cdefs.h>
 
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: mdb.c,v 1.46 2012/03/06 16:55:18 mbalmer Exp $");
+__RCSID("$NetBSD: mdb.c,v 1.47 2018/11/21 20:04:48 martin Exp $");
 #endif
 
 
@@ -163,6 +163,8 @@ write_menu_file(char *initcode)
 		(void)fprintf(out_file, "#define MSG_XLAT(x) (x)\n");
 	if (do_dynamic)
 		(void)fprintf(out_file, "#define DYNAMIC_MENUS\n");
+	if (do_expands)
+		(void)fprintf(out_file, "#define MENU_EXPANDS\n");
 	if (do_dynamic || do_msgxlat)
 		(void)fprintf(out_file, "\n");
 
@@ -171,6 +173,9 @@ write_menu_file(char *initcode)
 		"typedef struct menu_ent menu_ent;\n"	
 		"struct menu_ent {\n"
 		"	const char	*opt_name;\n"
+		"#ifdef	MENU_EXPANDS\n"
+		"	const char	*opt_exp_name;\n"
+		"#endif\n"
 		"	int		opt_menu;\n"
 		"	int		opt_flags;\n"
 		"	int		(*opt_action)(menudesc *, void *);\n"
@@ -192,7 +197,12 @@ write_menu_file(char *initcode)
 		"	WINDOW		*mw;\n"
 		"	WINDOW		*sv_mw;\n"
 		"	const char	*helpstr;\n"
-		"	const char	*exitstr;\n"
+		"	const char	*exitstr;\n");
+	if (do_expands)
+		(void)fprintf(out_file,
+			"	void		(*expand_act)(menudesc *, "
+			    "void *);\n");
+	(void)fprintf(out_file,
 		"	void		(*post_act)(menudesc *, void *);\n"
 		"	void		(*exit_act)(menudesc *, void *);\n"
 		"	void		(*draw_line)(menudesc *, int, void *);\n"
@@ -263,6 +273,14 @@ write_menu_file(char *initcode)
 
 	/* func defs */
 	for (i = 0; i < menu_no; i++) {
+		if (do_expands && strlen(menus[i]->info->expact.code)) {
+			(void)fprintf(out_file, "/*ARGSUSED*/\n"
+			    "static void menu_%d_expact(menudesc *menu, void *arg)\n{\n", i);
+			if (menus[i]->info->expact.endwin)
+				(void)fprintf(out_file, "\tendwin();\n");
+			(void)fprintf(out_file, "\t%s\n}\n\n",
+			    menus[i]->info->expact.code);
+		}
 		if (strlen(menus[i]->info->postact.code)) {
 			(void)fprintf(out_file, "/*ARGSUSED*/\n"
 			    "static void menu_%d_postact(menudesc *menu, void *arg)\n{\n", i);
@@ -307,7 +325,8 @@ write_menu_file(char *initcode)
 		for (j = 0, toptn = menus[i]->info->optns; toptn;
 		    toptn = toptn->next, j++) {
 			name_is_code += toptn->name_is_code;
-			(void)fprintf(out_file, "\t{%s,%d,%d,",
+			(void)fprintf(out_file, "\t{ .opt_name = %s, "
+				".opt_menu=%d, .opt_flags=%d, .opt_action=",
 				toptn->name_is_code ? "0" : toptn->name,
 				toptn->menu,
 				(toptn->issub ? OPT_SUB : 0)
@@ -380,6 +399,12 @@ write_menu_file(char *initcode)
 			(void)fprintf(out_file, "%s", menus[i]->info->exitstr);
 		else
 			(void)fprintf(out_file, "\"Exit\"");
+		if (do_expands) {
+			if (strlen(menus[i]->info->expact.code))
+				(void)fprintf(out_file, ",menu_%d_expact", i);
+			else
+				(void)fprintf(out_file, ",NULL");
+		}
 		if (strlen(menus[i]->info->postact.code))
 			(void)fprintf(out_file, ",menu_%d_postact", i);
 		else
@@ -397,7 +422,10 @@ write_menu_file(char *initcode)
 
 	}
 	(void)fprintf(out_file, "{NULL, 0, 0, 0, 0, 0, 0, 0, 0, "
-		"NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};\n\n");
+		"NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL");
+	if (do_expands)
+		(void)fprintf(out_file, ", NULL");
+	(void)fprintf(out_file, "}};\n\n");
 
 	/* __menu_initerror: initscr failed. */
 	(void)fprintf(out_file, 

Index: src/usr.bin/menuc/mdb.h
diff -u src/usr.bin/menuc/mdb.h:1.9 src/usr.bin/menuc/mdb.h:1.10
--- src/usr.bin/menuc/mdb.h:1.9	Tue Mar  6 16:55:18 2012
+++ src/usr.bin/menuc/mdb.h	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdb.h,v 1.9 2012/03/06 16:55:18 mbalmer Exp $	*/
+/*	$NetBSD: mdb.h,v 1.10 2018/11/21 20:04:48 martin Exp $	*/
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -81,6 +81,7 @@ struct menu_info {
 	int numopt;
 	int name_is_code;
 	optn_info *optns;
+	action expact;
 	action postact;
 	action exitact;
 };

Index: src/usr.bin/menuc/menu_sys.def
diff -u src/usr.bin/menuc/menu_sys.def:1.59 src/usr.bin/menuc/menu_sys.def:1.60
--- src/usr.bin/menuc/menu_sys.def:1.59	Tue Mar  6 16:55:18 2012
+++ src/usr.bin/menuc/menu_sys.def	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: menu_sys.def,v 1.59 2012/03/06 16:55:18 mbalmer Exp $	*/
+/*	$NetBSD: menu_sys.def,v 1.60 2018/11/21 20:04:48 martin Exp $	*/
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -213,7 +213,13 @@ init_menu(menudesc *m)
 	if (w == 0) {
 		int l;
 		for (i = 0; i < m->numopts; i++) {
+#ifdef MENU_EXPANDS
+			tp = m->opts[i].opt_exp_name ?
+			    m->opts[i].opt_exp_name :
+			    MSG_XLAT(m->opts[i].opt_name);
+#else
 			tp = MSG_XLAT(m->opts[i].opt_name);
+#endif
 			if (tp == NULL)
 				continue;
 			l = strlen(tp);
@@ -359,7 +365,14 @@ draw_menu(menudesc *m, void *arg)
 	for (opt = m->topline; opt < m->numopts; opt++) {
 		if (cury >= maxy)
 			break;
-		draw_menu_line(m, opt, cury++, arg, m->opts[opt].opt_name);
+		draw_menu_line(m, opt, cury++, arg,
+#ifdef MENU_EXPANDS
+		    m->opts[opt].opt_exp_name ?
+		    	m->opts[opt].opt_exp_name : m->opts[opt].opt_name
+#else
+		    m->opts[opt].opt_name
+#endif
+		    );
 	}
 
 	/* Add the exit option. */
@@ -482,6 +495,21 @@ process_help(menudesc *m)
 	wclear(stdscr);
 }
 
+#ifdef MENU_EXPANDS
+static void
+free_exp_menu_items(menudesc *m)
+{
+	int i;
+
+	for (i = 0; i < m->numopts; i++) {
+		if (m->opts[i].opt_exp_name != NULL) {
+			free(__UNCONST(m->opts[i].opt_exp_name));
+			m->opts[i].opt_exp_name = NULL;
+		}
+	}
+}
+#endif
+
 static void
 process_req(menudesc *m, void *arg, int req)
 {
@@ -667,6 +695,12 @@ process_menu(int num, void *arg)
 		if (isendwin())
 			/* I'm not sure this is needed with netbsd's curses */
 			doupdate();
+#ifdef MENU_EXPANDS
+		/* Expand the menu items, if needed */
+		if (m->expand_act && m->mw == NULL)
+			(*m->expand_act)(m, arg);
+#endif
+
 		/* Process the display action */
 		if (m->post_act)
 			(*m->post_act)(m, arg);
@@ -726,6 +760,11 @@ process_menu(int num, void *arg)
 		wnoutrefresh(m->mw);
 	}
 
+#ifdef MENU_EXPANDS
+	/* Free expanded menu items, if any */
+	free_exp_menu_items(m);
+#endif
+
 	/* Process the exit action */
 	if (m->exit_act)
 		(*m->exit_act)(m, arg);
@@ -801,6 +840,9 @@ new_menu(const char *title, menu_ent *op
 	m->h = h;
 	m->w = w;
 	m->mopt = mopt | MC_VALID;
+#ifdef MENU_EXPANDS
+	m->expand_act = NULL;
+#endif
 	m->post_act = post_act;
 	m->draw_line = draw_line;
 	m->exit_act = exit_act;

Index: src/usr.bin/menuc/menuc.1
diff -u src/usr.bin/menuc/menuc.1:1.31 src/usr.bin/menuc/menuc.1:1.32
--- src/usr.bin/menuc/menuc.1:1.31	Mon Jul  3 21:34:20 2017
+++ src/usr.bin/menuc/menuc.1	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-.\"	$NetBSD: menuc.1,v 1.31 2017/07/03 21:34:20 wiz Exp $
+.\"	$NetBSD: menuc.1,v 1.32 2018/11/21 20:04:48 martin Exp $
 .\"
 .\" Copyright 1997 Piermont Information Systems Inc.
 .\" All rights reserved.
@@ -29,7 +29,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd August 2, 2004
+.Dd November 20, 2018
 .Dt MENUC 1
 .Os
 .Sh NAME
@@ -130,12 +130,13 @@ The
 is as described above.
 .Pp
 There are four kinds of menu definition elements.
-The first one just declares whether the programmer wants dynamic menus
-available.
-The default is static menus only.
-The static menus are the ones defined by the menu definitions and do not
+The first one just declares whether the programmer wants dynamic menus,
+dynamic messages and argument expansion in menus available.
+All these option default to off (or static only).
+.Pp
+Static menus are the ones defined by the menu definitions and do not
 change at run time.
-The dynamic menus provide the programmer with a method to create and
+Dynamic menus provide the programmer with a method to create and
 modify menus during the running of the program.
 To include dynamic menus, one needs only add the declaration:
 .Dl allow dynamic menus ;
@@ -143,6 +144,18 @@ The semicolon is required to terminate t
 This declaration may appear anywhere in the
 .Ar file ,
 but usually appears before any menus are defined.
+See below for a detailed explanation of dynamic menus.
+.Pp
+To allow dynamic messages, one needs to add the declaration:
+.Dl allow dynamic messages ;
+This enables internationalization by loading message files at
+run time.
+.Pp
+To allow argument expansion on static menu strings, one needs to add
+the declaration:
+.Dl allow expand ;
+This enables the expand action.
+See below for a detailed explanation.
 .Pp
 The next element is a code block to execute if the curses
 screen can not be successfully initialized.
@@ -249,6 +262,7 @@ The final element is the actual static m
 The format and order for a menu definition is:
 .Bd -ragged -offset indent
 menu <name> <options> ;
+  <expand action>
   <display action>
   <menu items>
   <exit action>
@@ -272,6 +286,11 @@ The options are a comma separated list o
 declaration.
 These override the options from the most recent default declaration.
 .Pp
+The expand action is optional and only available if the global option
+.Dq allow expand
+has been declared (see above).
+For an example see below.
+.Pp
 The display action is optional and provides C code to
 execute at each and every time the menu is displayed for processing.
 If it is included, the format is:
@@ -407,6 +426,20 @@ int new_menu(const char *title, menu_ent
 void free_menu (int menu_no);
 .Ed
 .Pp
+If
+.Dq allow expand
+has been declared, the menudesc structure contains another member, expand_act:
+.Bd -literal
+        void       (*expand_act)(struct menudesc *, void *);
+        void       (*post_act)(struct menudesc *, void *);
+        void       (*exit_act)(struct menudesc *, void *);
+        void       (*draw_line)(struct menudesc *, int, void *);
+.Ed
+This function is called (if not NULL) once when initializing
+a menu, before the display action
+.Dv post_act
+is called.
+.Pp
 The
 .Ar title
 is the title displayed at the top of the menu.
@@ -458,6 +491,45 @@ If
 A
 .Dv NULL
 help pointer will disable the help feature for the menu.
+.Sh MENU ITEM EXPANSION
+With the
+.Dq enable expansion
+declaration in effect, static menus may be customized before being displayed.
+This allows parameter substition or special formatting of the menu item
+strings without having to resort to a full dynamic menu.
+Expanded strings are stored in the
+.Dv opt_exp_name
+member of struct
+.Dv menu_ent .
+This string is prefered over the non-expanded string
+.Dv opt_name
+when displaying the menu.
+The expand action code is responsible for filling this pointers.
+When leaving the menu, all
+.Dv opt_exp_name
+pointers that are populated will be automatically freed (by calling
+.Fn free 3 . )
+.Pp
+A very simple (and nonsensial) example for an expand option would
+be:
+.Bd -literal
+	expand action {
+		int i;
+		for (i = 0; i < menu->numopts; i++) {
+			const char *s = MSG_XLAT(menu->opts[i].opt_name);
+			if (s == NULL) continue;
+			char *t = strdup(s);
+			t[0] = tolower((unsigned char)t[0]);
+			menu->opts[i].opt_exp_name = t;
+		}
+	};
+.Ed
+which would force the first character of all menu items to lower case.
+The
+.Fn free 3
+call for the
+.Fn strdup 3
+call in above code is automatically handled on menu exit.
 .Sh FILES
 .Bl -item
 .It

Index: src/usr.bin/menuc/parse.y
diff -u src/usr.bin/menuc/parse.y:1.16 src/usr.bin/menuc/parse.y:1.17
--- src/usr.bin/menuc/parse.y:1.16	Tue Mar  6 16:55:18 2012
+++ src/usr.bin/menuc/parse.y	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.y,v 1.16 2012/03/06 16:55:18 mbalmer Exp $	*/
+/*	$NetBSD: parse.y,v 1.17 2018/11/21 20:04:48 martin Exp $	*/
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -52,8 +52,8 @@ static optn_info *cur_optn;
 
 
 %token <i_value> X Y W H NO BOX SUB HELP MENU NEXT EXIT ACTION ENDWIN OPTION 
-%token <i_value> TITLE DEFAULT DISPLAY ERROR EXITSTRING ALLOW DYNAMIC MENUS
-		 SCROLLABLE SHORTCUT CLEAR MESSAGES ALWAYS SCROLL
+%token <i_value> TITLE DEFAULT DISPLAY ERROR EXITSTRING EXPAND ALLOW DYNAMIC
+		 MENUS SCROLLABLE SHORTCUT CLEAR MESSAGES ALWAYS SCROLL
 %token <s_value> STRING NAME CODE INT_CONST CHAR_CONST
 
 %type <s_value> init_code system helpstr text
@@ -80,6 +80,7 @@ menu_list :  /* empty */
 	  |  menu_list menu_def
 	  |  menu_list default_def
 	  |  menu_list initerror_def
+	  |  menu_list expand_def
 	  |  menu_list dynamic_def
 	  |  menu_list msgxlat_def
 	  ;
@@ -87,6 +88,9 @@ menu_list :  /* empty */
 dynamic_def : ALLOW DYNAMIC MENUS ';'
 		{ do_dynamic = 1; }
 
+expand_def : ALLOW EXPAND ';'
+		{ do_expands = 1; }
+
 msgxlat_def : ALLOW DYNAMIC MESSAGES ';'
 		{ do_msgxlat = 1; }
 
@@ -107,12 +111,12 @@ menu_def  :  MENU NAME
 			  *(cur_menu->info) = default_info;
 		  }
 		}
-	     opts ";" dispact option_list exitact helpstr
+	     opts ";" expaction dispact option_list exitact helpstr
 		{ optn_info *t;
 		  cur_menu->info->optns = NULL;
-		  while ($7 != NULL) {
-			  t = $7;
-			  $7 = $7->next;
+		  while ($8 != NULL) {
+			  t = $8;
+			  $8 = $8->next;
 			  t->next = cur_menu->info->optns;
 			  cur_menu->info->optns = t;
 			  cur_menu->info->numopt++;
@@ -213,6 +217,12 @@ act_opt	  : /* empty */		{ $$ = 0; }
 	  | "(" ENDWIN ")"	{ $$ = 1; }
 	  ;
 
+expaction : /* empty */ 	{ cur_menu->info->expact.code = ""; }
+	  | EXPAND action ";"	{ if (!do_expands) yyerror ("Menu expands "
+	  						     "not enabled");
+	  			  cur_menu->info->expact = $2; }
+	  ;
+
 dispact	  : /* empty */ 	{ cur_menu->info->postact.code = ""; }
 	  | DISPLAY action ";"	{ cur_menu->info->postact = $2; }
 	  ;
Index: src/usr.bin/menuc/scan.l
diff -u src/usr.bin/menuc/scan.l:1.16 src/usr.bin/menuc/scan.l:1.17
--- src/usr.bin/menuc/scan.l:1.16	Tue Mar  6 16:55:18 2012
+++ src/usr.bin/menuc/scan.l	Wed Nov 21 20:04:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: scan.l,v 1.16 2012/03/06 16:55:18 mbalmer Exp $	*/
+/*	$NetBSD: scan.l,v 1.17 2018/11/21 20:04:48 martin Exp $	*/
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -96,6 +96,8 @@ default { return DEFAULT; }
 
 display { return DISPLAY; }
 
+expand { return EXPAND; }
+
 error { return ERROR; }
 
 allow { return ALLOW; }

Reply via email to