Importing usr.bin/menuc

No Minix-specific changes needed.

Change-Id: Ie663e08a515a393efaaeecacea15ef807aa8ecfb
This commit is contained in:
Thomas Cort 2013-11-06 10:44:51 -05:00
parent 7d85156ac0
commit 525a267e81
19 changed files with 3339 additions and 1 deletions

View file

@ -402,6 +402,7 @@
./usr/bin/md2 minix-sys
./usr/bin/md4 minix-sys
./usr/bin/md5 minix-sys
./usr/bin/menuc minix-sys
./usr/bin/mesg minix-sys
./usr/bin/mined minix-sys
./usr/bin/ministat minix-sys
@ -1993,6 +1994,7 @@
./usr/man/man1/md2.1 minix-sys
./usr/man/man1/md4.1 minix-sys
./usr/man/man1/md5.1 minix-sys
./usr/man/man1/menuc.1 minix-sys
./usr/man/man1/mesg.1 minix-sys
./usr/man/man1/ministat.1 minix-sys
./usr/man/man1/mixer.1 minix-sys
@ -4669,6 +4671,7 @@
./usr/share/misc/magic.mgc minix-sys
./usr/share/misc/man.template minix-sys
./usr/share/misc/mdoc.template minix-sys
./usr/share/misc/menu_sys.def minix-sys
./usr/share/misc/na.phone minix-sys
./usr/share/misc/na.postal minix-sys
./usr/share/misc/NetBSD.el minix-sys

View file

@ -189,6 +189,7 @@
2012/10/17 12:00:00,usr.bin/Makefile
2012/10/17 12:00:00,usr.bin/Makefile.inc
2010/07/07 21:24:34,usr.bin/man
2012/10/17 12:00:00,usr.bin/menuc
2013/10/25 12:00:00,usr.bin/mesg
2010/10/15 05:46:48,usr.bin/mkdep
2012/10/17 12:00:00,usr.bin/mkstr

View file

@ -15,7 +15,7 @@ SUBDIR= asa \
head hexdump indent infocmp join \
lam ldd leave \
lock login logname lorder m4 \
machine make man mesg \
machine make man menuc mesg \
mkdep mkstr mktemp \
\
nbperf newgrp nice nl nohup nvi \

22
usr.bin/menuc/Makefile Normal file
View file

@ -0,0 +1,22 @@
# $NetBSD: Makefile,v 1.14 2009/10/29 14:36:14 christos Exp $
WARNS?= 1 # XXX -Wshadow -Wcast-qual issues
.include <bsd.own.mk>
PROG= menuc
SRCS= main.c parse.y scan.l avl.c mdb.c util.c
CPPFLAGS+= -I. -I${.CURDIR}
YHEADER=
.if ${MKSHARE} != "no"
FILES= menu_sys.def
FILESDIR= /usr/share/misc
.endif
.ifndef HOSTPROG
LDADD+= -ll
DPADD+= ${LIBL}
.endif
.include <bsd.prog.mk>

217
usr.bin/menuc/avl.c Normal file
View file

@ -0,0 +1,217 @@
/* $NetBSD: avl.c,v 1.7 2005/02/11 06:21:22 simonb Exp $ */
/*
* Copyright (c) 1997 Philip A. Nelson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Philip A. Nelson.
* 4. The name of Philip A. Nelson may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* avl.c: Routines for manipulation an avl tree.
*
* an include file should define the following minimum struct.:
* (Comments must be made into real comments.)
*
* typedef struct id_rec {
* / * The balanced binary tree fields. * /
* char *id; / * The name. * /
* short balance; / * For the balanced tree. * /
* struct id_rec *left, *right; / * Tree pointers. * /
*
* / * Other information fields. * /
* } id_rec;
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: avl.c,v 1.7 2005/02/11 06:21:22 simonb Exp $");
#endif
#include <string.h>
#include "defs.h"
/* find_id returns a pointer to node in TREE that has the correct
ID. If there is no node in TREE with ID, NULL is returned. */
id_rec *
find_id (id_rec *tree, char *id)
{
int cmp_result;
/* Check for an empty tree. */
if (tree == NULL)
return NULL;
/* Recursively search the tree. */
cmp_result = strcmp (id, tree->id);
if (cmp_result == 0)
return tree; /* This is the item. */
else if (cmp_result < 0)
return find_id (tree->left, id);
else
return find_id (tree->right, id);
}
/* insert_id inserts a NEW_ID rec into the tree whose ROOT is
provided. insert_id returns TRUE if the tree height from
ROOT down is increased otherwise it returns FALSE. This is a
recursive balanced binary tree insertion algorithm. */
int insert_id (id_rec **root, id_rec *new_id)
{
id_rec *A, *B;
/* If root is NULL, this where it is to be inserted. */
if (*root == NULL)
{
*root = new_id;
new_id->left = NULL;
new_id->right = NULL;
new_id->balance = 0;
return (TRUE);
}
/* We need to search for a leaf. */
if (strcmp (new_id->id, (*root)->id) < 0)
{
/* Insert it on the left. */
if (insert_id (&((*root)->left), new_id))
{
/* The height increased. */
(*root)->balance--;
switch ((*root)->balance)
{
case 0: /* no height increase. */
return (FALSE);
case -1: /* height increase. */
return (TRUE);
case -2: /* we need to do a rebalancing act. */
A = *root;
B = (*root)->left;
if (B->balance <= 0)
{
/* Single Rotate. */
A->left = B->right;
B->right = A;
*root = B;
A->balance = 0;
B->balance = 0;
}
else
{
/* Double Rotate. */
*root = B->right;
B->right = (*root)->left;
A->left = (*root)->right;
(*root)->left = B;
(*root)->right = A;
switch ((*root)->balance)
{
case -1:
A->balance = 1;
B->balance = 0;
break;
case 0:
A->balance = 0;
B->balance = 0;
break;
case 1:
A->balance = 0;
B->balance = -1;
break;
}
(*root)->balance = 0;
}
}
}
}
else
{
/* Insert it on the right. */
if (insert_id (&((*root)->right), new_id))
{
/* The height increased. */
(*root)->balance++;
switch ((*root)->balance)
{
case 0: /* no height increase. */
return (FALSE);
case 1: /* height increase. */
return (TRUE);
case 2: /* we need to do a rebalancing act. */
A = *root;
B = (*root)->right;
if (B->balance >= 0)
{
/* Single Rotate. */
A->right = B->left;
B->left = A;
*root = B;
A->balance = 0;
B->balance = 0;
}
else
{
/* Double Rotate. */
*root = B->left;
B->left = (*root)->right;
A->right = (*root)->left;
(*root)->left = A;
(*root)->right = B;
switch ((*root)->balance)
{
case -1:
A->balance = 0;
B->balance = 1;
break;
case 0:
A->balance = 0;
B->balance = 0;
break;
case 1:
A->balance = -1;
B->balance = 0;
break;
}
(*root)->balance = 0;
}
}
}
}
/* If we fall through to here, the tree did not grow in height. */
return (FALSE);
}

102
usr.bin/menuc/defs.h Normal file
View file

@ -0,0 +1,102 @@
/* $NetBSD: defs.h,v 1.9 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* defs.h: definitions needed for the menu system. */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <stdio.h>
#include "mdb.h"
#ifdef MAIN
#define EXTERN
#define INIT(x) = x
#else
#define EXTERN extern
#define INIT(x)
#endif
/* some constants */
#define TRUE 1
#define FALSE 0
/* Global variables .. to be defined in main.c, extern elsewhere. */
EXTERN char *prog_name;
EXTERN char *src_name;
EXTERN char *out_name INIT("menu_defs");
EXTERN char *sys_name INIT("menu_sys.def");
EXTERN int do_dynamic INIT(0);
EXTERN int do_msgxlat INIT(0);
EXTERN int line_no INIT(1);
EXTERN int had_errors INIT(FALSE);
EXTERN int max_strlen INIT(1);
EXTERN id_rec *root INIT(NULL);
EXTERN struct menu_info default_info;
EXTERN id_rec default_menu;
EXTERN action error_act INIT({NULL});
/* Prototypes. */
/* From util.c */
void yyerror(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
void buff_add_ch(char);
char *buff_copy(void);
/* from scan.l */
int yylex(void);
/* from parse.y */
int yyparse(void);
/* Vars not defined in main.c */
extern FILE *yyin;
/* from avl.c */
id_rec *find_id(id_rec *, char *);
int insert_id(id_rec **, id_rec *);
/* from mdb.c */
id_rec *get_menu(char *);
void check_defined(void);
void write_menu_file(char *);

115
usr.bin/menuc/main.c Normal file
View file

@ -0,0 +1,115 @@
/* $NetBSD: main.c,v 1.11 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* main.c - main program for menu compiler. */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: main.c,v 1.11 2012/03/06 16:55:18 mbalmer Exp $");
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAIN
#include "defs.h"
/* Local prototypes */
__dead void usage(void);
int
main(int argc, char **argv)
{
int ch;
/* Process the arguments. */
while ((ch = getopt(argc, argv, "o:")) != -1 ) {
switch (ch) {
case 'o': /* output file name */
out_name = optarg;
break;
default:
usage();
}
}
if (optind != argc - 1)
usage();
src_name = argv[optind];
yyin = fopen(src_name, "r");
if (yyin == NULL) {
(void)fprintf(stderr, "%s: could not open %s.\n", prog_name,
src_name);
exit(1);
}
/* The default menu */
default_menu.info = &default_info;
default_info.title = "\"\"";
default_info.helpstr = NULL;
default_info.exitstr = NULL;
default_info.mopt = 0;
default_info.x = -1;
default_info.y = 0;
default_info.h = 0;
default_info.w = 0;
default_info.numopt = 0;
default_info.optns = NULL;
default_info.postact.code = NULL;
default_info.postact.endwin = FALSE;
default_info.exitact.code = NULL;
default_info.exitact.endwin = FALSE;
/* Do the parse */
(void)yyparse();
return had_errors ? 1 : 0;
}
__dead void
usage(void)
{
(void)fprintf (stderr, "%s [-o name] file\n", getprogname());
exit(1);
}

431
usr.bin/menuc/mdb.c Normal file
View file

@ -0,0 +1,431 @@
/* $NetBSD: mdb.c,v 1.46 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* mdb.c - menu database manipulation */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: mdb.c,v 1.46 2012/03/06 16:55:18 mbalmer Exp $");
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mdb.h"
#include "defs.h"
#include "pathnames.h"
/* Data */
#undef MAX
#define MAX 1000
static int menu_no = 0;
static id_rec *menus[MAX];
/* Other defines */
#define OPT_SUB 1
#define OPT_ENDWIN 2
#define OPT_EXIT 4
/* get_menu returns a pointer to a newly created id_rec or an old one. */
id_rec *
get_menu(char *name)
{
id_rec *temp;
temp = find_id (root, name);
if (temp == NULL) {
if (menu_no < MAX) {
temp = (id_rec *)malloc(sizeof(id_rec));
temp->id = strdup(name);
temp->info = NULL;
temp->menu_no = menu_no;
menus[menu_no++] = temp;
insert_id(&root, temp);
} else {
(void)fprintf(stderr, "Too many menus. "
"Increase MAX.\n");
exit(1);
}
}
return temp;
}
/* Verify that all menus are defined. */
void
check_defined(void)
{
int i;
for (i = 0; i < menu_no; i++)
if (!menus[i]->info)
yyerror ("Menu '%s' undefined.", menus[i]->id);
}
/* Write out the menu file. */
void
write_menu_file(char *initcode)
{
FILE *out_file, *sys_file;
int i, j;
char hname[1024], cname[1024], sname[1024];
char *sys_prefix, *tmpstr;
int name_is_code, nlen, ch;
optn_info *toptn;
/* Generate file names */
snprintf(hname, 1024, "%s.h", out_name);
nlen = strlen(hname);
if (hname[nlen-2] != '.' || hname[nlen-1] != 'h') {
(void)fprintf(stderr, "%s: name `%s` too long.\n",
prog_name, out_name);
exit(1);
}
snprintf(cname, 1024, "%s.c", out_name);
/* Open the menu_sys file first. */
sys_prefix = getenv("MENUDEF");
if (sys_prefix == NULL)
sys_prefix = _PATH_DEFSYSPREFIX;
snprintf(sname, 1024, "%s/%s", sys_prefix, sys_name);
sys_file = fopen (sname, "r");
if (sys_file == NULL) {
(void)fprintf(stderr, "%s: could not open %s.\n",
prog_name, sname);
exit(1);
}
/* Output the .h file first. */
out_file = fopen(hname, "w");
if (out_file == NULL) {
(void)fprintf(stderr, "%s: could not open %s.\n",
prog_name, hname);
exit(1);
}
/* Write it */
(void)fprintf(out_file, "%s",
"/* menu system definitions. */\n"
"\n"
"#ifndef MENU_DEFS_H\n"
"#define MENU_DEFS_H\n"
"#include <stdlib.h>\n"
"#include <string.h>\n"
"#include <ctype.h>\n"
"#include <curses.h>\n\n"
);
if (do_msgxlat)
(void)fprintf(out_file, "#define MSG_XLAT(x) msg_string(x)\n");
else
(void)fprintf(out_file, "#define MSG_XLAT(x) (x)\n");
if (do_dynamic)
(void)fprintf(out_file, "#define DYNAMIC_MENUS\n");
if (do_dynamic || do_msgxlat)
(void)fprintf(out_file, "\n");
(void)fprintf(out_file,
"typedef struct menudesc menudesc;\n"
"typedef struct menu_ent menu_ent;\n"
"struct menu_ent {\n"
" const char *opt_name;\n"
" int opt_menu;\n"
" int opt_flags;\n"
" int (*opt_action)(menudesc *, void *);\n"
"};\n\n"
"#define OPT_SUB 1\n"
"#define OPT_ENDWIN 2\n"
"#define OPT_EXIT 4\n"
"#define OPT_IGNORE 8\n"
"#define OPT_NOMENU -1\n\n"
"struct menudesc {\n"
" const char *title;\n"
" int y, x;\n"
" int h, w;\n"
" int mopt;\n"
" int numopts;\n"
" int cursel;\n"
" int topline;\n"
" menu_ent *opts;\n"
" WINDOW *mw;\n"
" WINDOW *sv_mw;\n"
" const char *helpstr;\n"
" const char *exitstr;\n"
" void (*post_act)(menudesc *, void *);\n"
" void (*exit_act)(menudesc *, void *);\n"
" void (*draw_line)(menudesc *, int, void *);\n"
"};\n"
"\n"
"/* defines for mopt field. */\n"
#define STR(x) #x
#define MC_OPT(x) "#define " #x " " STR(x) "\n"
MC_OPT(MC_NOEXITOPT)
MC_OPT(MC_NOBOX)
MC_OPT(MC_SCROLL)
MC_OPT(MC_NOSHORTCUT)
MC_OPT(MC_NOCLEAR)
MC_OPT(MC_DFLTEXIT)
MC_OPT(MC_ALWAYS_SCROLL)
MC_OPT(MC_SUBMENU)
MC_OPT(MC_VALID)
#undef MC_OPT
#undef STR
);
(void)fprintf(out_file, "%s",
"\n"
"/* Prototypes */\n"
"int menu_init(void);\n"
"void process_menu(int, void *);\n"
"__dead void __menu_initerror(void);\n"
);
if (do_dynamic)
(void)fprintf(out_file, "%s",
"int new_menu(const char *, menu_ent *, int, \n"
"\tint, int, int, int, int,\n"
"\tvoid (*)(menudesc *, void *), "
"void (*)(menudesc *, int, void *),\n"
"\tvoid (*)(menudesc *, void *), "
"const char *, const char *);\n"
"void free_menu(int);\n"
"void set_menu_numopts(int, int);\n"
);
(void)fprintf(out_file, "\n/* Menu names */\n");
for (i = 0; i < menu_no; i++)
(void)fprintf(out_file, "#define MENU_%s\t%d\n",
menus[i]->id, i);
if (do_dynamic)
(void)fprintf(out_file, "\n#define DYN_MENU_START\t%d",
menu_no);
(void)fprintf (out_file, "\n#define MAX_STRLEN %d\n"
"#endif\n", max_strlen);
fclose(out_file);
/* Now the C file */
out_file = fopen(cname, "w");
if (out_file == NULL) {
(void)fprintf(stderr, "%s: could not open %s.\n",
prog_name, cname);
exit(1);
}
/* initial code */
fprintf(out_file, "#include \"%s\"\n\n", hname);
fprintf(out_file, "%s\n\n", initcode);
/* data definitions */
/* func defs */
for (i = 0; i < menu_no; i++) {
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);
if (menus[i]->info->postact.endwin)
(void)fprintf(out_file, "\tendwin();\n");
(void)fprintf(out_file, "\t%s\n}\n\n",
menus[i]->info->postact.code);
}
if (strlen(menus[i]->info->exitact.code)) {
(void)fprintf(out_file, "/*ARGSUSED*/\n"
"static void menu_%d_exitact(menudesc *menu, void *arg)\n{\n", i);
if (menus[i]->info->exitact.endwin)
(void)fprintf(out_file, "\tendwin();\n");
(void)fprintf(out_file, "\t%s\n}\n\n",
menus[i]->info->exitact.code);
}
j = 0;
toptn = menus[i]->info->optns;
for (; toptn != NULL; j++, toptn = toptn->next) {
if (strlen(toptn->optact.code) == 0)
continue;
(void)fprintf(out_file, "/*ARGSUSED*/\n"
"static int opt_act_%d_%d(menudesc *m, void *arg)\n"
"{\n\t%s\n\treturn %s;\n}\n\n",
i, j, toptn->optact.code,
(toptn->doexit ? "1" : "0"));
}
}
/* optentX */
for (i = 0; i < menu_no; i++) {
if (menus[i]->info->numopt > 53) {
(void)fprintf(stderr, "Menu %s has "
"too many options.\n",
menus[i]->info->title);
exit(1);
}
(void)fprintf(out_file, "static menu_ent optent%d[] = {\n", i);
name_is_code = 0;
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,",
toptn->name_is_code ? "0" : toptn->name,
toptn->menu,
(toptn->issub ? OPT_SUB : 0)
+(toptn->doexit ? OPT_EXIT : 0)
+(toptn->optact.endwin ? OPT_ENDWIN : 0));
if (strlen(toptn->optact.code))
(void)fprintf(out_file, "opt_act_%d_%d}", i, j);
else
(void)fprintf(out_file, "NULL}");
(void)fprintf(out_file, "%s\n",
(toptn->next ? "," : ""));
}
(void)fprintf(out_file, "\t};\n\n");
if (name_is_code) {
menus[i]->info->name_is_code = 1;
fprintf(out_file, "static void menu_%d_legend("
"menudesc *menu, int opt, void *arg)\n{\n"
"\tswitch (opt) {\n", i);
for (j = 0, toptn = menus[i]->info->optns; toptn;
toptn = toptn->next, j++) {
if (!toptn->name_is_code)
continue;
fprintf(out_file, "\tcase %d:\n\t\t{%s};\n"
"\t\tbreak;\n", j, toptn->name);
}
fprintf(out_file, "\t}\n}\n\n");
}
}
/* menus */
if (!do_dynamic)
(void)fprintf(out_file, "static int num_menus = %d;\n",
menu_no);
(void)fprintf(out_file, "static struct menudesc menu_def[] = {\n");
for (i = 0; i < menu_no; i++) {
(void)fprintf(out_file,
"\t{%s,%d,%d,%d,%d,%d,%d,0,0,optent%d,NULL,NULL,",
menus[i]->info->title, menus[i]->info->y,
menus[i]->info->x, menus[i]->info->h,
menus[i]->info->w, menus[i]->info->mopt,
menus[i]->info->numopt, i);
if (menus[i]->info->helpstr == NULL)
(void)fprintf(out_file, "NULL");
else {
tmpstr = menus[i]->info->helpstr;
if (*tmpstr != '"')
(void)fprintf(out_file, "%s", tmpstr);
else {
/* Skip an initial newline. */
if (tmpstr[1] == '\n')
*++tmpstr = '"';
(void)fprintf(out_file, "\n");
while (*tmpstr) {
if (*tmpstr != '\n') {
fputc(*tmpstr++, out_file);
continue;
}
(void)fprintf(out_file, "\\n\"\n\"");
tmpstr++;
}
}
}
(void)fprintf(out_file, ",");
if (menus[i]->info->mopt & MC_NOEXITOPT)
(void) fprintf (out_file, "NULL");
else if (menus[i]->info->exitstr != NULL)
(void)fprintf(out_file, "%s", menus[i]->info->exitstr);
else
(void)fprintf(out_file, "\"Exit\"");
if (strlen(menus[i]->info->postact.code))
(void)fprintf(out_file, ",menu_%d_postact", i);
else
(void)fprintf(out_file, ",NULL");
if (strlen(menus[i]->info->exitact.code))
(void)fprintf(out_file, ",menu_%d_exitact", i);
else
(void)fprintf(out_file, ",NULL");
if (menus[i]->info->name_is_code)
(void)fprintf(out_file, ",menu_%d_legend", i);
else
(void)fprintf(out_file, ",NULL");
(void)fprintf(out_file, "},\n");
}
(void)fprintf(out_file, "{NULL, 0, 0, 0, 0, 0, 0, 0, 0, "
"NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};\n\n");
/* __menu_initerror: initscr failed. */
(void)fprintf(out_file,
"/* __menu_initerror: initscr failed. */\n"
"void __menu_initerror (void) {\n");
if (error_act.code == NULL) {
(void)fprintf(out_file,
"\t(void) fprintf (stderr, "
"\"%%s: Could not initialize curses\\n\", "
"getprogname());\n"
"\texit(1);\n"
"}\n");
} else {
if (error_act.endwin)
(void)fprintf(out_file, "\tendwin();\n");
(void)fprintf(out_file, "%s\n}\n", error_act.code);
}
/* Copy menu_sys.def file. */
while ((ch = fgetc(sys_file)) != '\014') /* Control-L */
fputc(ch, out_file);
if (do_dynamic) {
while ((ch = fgetc(sys_file)) != '\n')
/* skip it */;
while ((ch = fgetc(sys_file)) != EOF)
fputc(ch, out_file);
}
fclose(out_file);
fclose(sys_file);
}

98
usr.bin/menuc/mdb.h Normal file
View file

@ -0,0 +1,98 @@
/* $NetBSD: mdb.h,v 1.9 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* mdb.h - definitions for the menu database. */
#ifndef MDB_H
#define MDB_H
/* forward declaration */
typedef struct menu_info menu_info;
/* The declarations for the balanced binary trees. */
typedef struct id_rec {
/* The balanced binary tree fields. */
char *id; /* The name. */
short balance; /* For the balanced tree. */
struct id_rec *left, *right; /* Tree pointers. */
/* Other information fields. */
menu_info *info;
int menu_no;
} id_rec;
/* menu definitions records. */
typedef struct action {
char *code;
int endwin;
} action;
typedef struct optn_info {
char *name;
int name_is_code;
int menu;
int issub;
int doexit;
action optact;
struct optn_info *next;
} optn_info;
struct menu_info {
char *title;
char *helpstr;
char *exitstr;
int mopt;
int y, x;
int h, w;
int numopt;
int name_is_code;
optn_info *optns;
action postact;
action exitact;
};
/* defines for mopt */
#define MC_NOEXITOPT 1
#define MC_NOBOX 2
#define MC_SCROLL 4
#define MC_NOSHORTCUT 8
#define MC_NOCLEAR 16
#define MC_DFLTEXIT 32
#define MC_ALWAYS_SCROLL 64
#define MC_SUBMENU 128
#define MC_VALID 0x10000
#endif

827
usr.bin/menuc/menu_sys.def Normal file
View file

@ -0,0 +1,827 @@
/* $NetBSD: menu_sys.def,v 1.59 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* menu_sys.defs -- Menu system standard routines. */
#include <string.h>
#include <ctype.h>
#define REQ_EXECUTE 1000
#define REQ_NEXT_ITEM 1001
#define REQ_PREV_ITEM 1002
#define REQ_REDISPLAY 1003
#define REQ_SCROLLDOWN 1004
#define REQ_SCROLLUP 1005
#define REQ_HELP 1006
/* Macros */
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
/* Initialization state. */
static int __menu_init = 0;
static int max_lines = 0, max_cols = 0;
#ifndef scrolltext
static const char *scrolltext = " <: page up, >: page down";
#endif
#ifdef DYNAMIC_MENUS
static int num_menus = 0;
#define DYN_INIT_NUM 32
static menudesc **menu_list;
#define MENUS(n) (*(menu_list[n]))
#else
#define MENUS(n) (menu_def[n])
#endif
/* prototypes for in here! */
static void init_menu(menudesc *m);
static char opt_ch(menudesc *m, int op_no);
static void draw_menu(menudesc *m, void *arg);
static void process_help(menudesc *m);
static void process_req(menudesc *m, void *arg, int req);
static int menucmd(WINDOW *w);
#ifndef NULL
#define NULL 0
#endif
/* menu system processing routines */
#define mbeep() (void)fputc('\a', stderr)
static int
menucmd(WINDOW *w)
{
int ch;
while (TRUE) {
ch = wgetch(w);
switch (ch) {
case '\n':
return REQ_EXECUTE;
case '\016': /* Control-P */
case KEY_DOWN:
return REQ_NEXT_ITEM;
case '\020': /* Control-N */
case KEY_UP:
return REQ_PREV_ITEM;
case '\014': /* Control-L */
return REQ_REDISPLAY;
case '<':
case '\010': /* Control-H (backspace) */
case KEY_PPAGE:
case KEY_LEFT:
return REQ_SCROLLUP;
case '\026': /* Control-V */
case '>':
case ' ':
case KEY_NPAGE:
case KEY_RIGHT:
return REQ_SCROLLDOWN;
case '?':
return REQ_HELP;
case '\033': /* esc-v is scroll down */
ch = wgetch(w);
if (ch == 'v')
return REQ_SCROLLUP;
else
ch = 0; /* zap char so we beep */
}
if (isalpha(ch))
return ch;
mbeep();
wrefresh(w);
}
}
static void
init_menu(menudesc *m)
{
int wmax;
int hadd, wadd, exithadd;
int i;
int x, y, w;
const char *title, *tp, *ep;
x = m->x;
y = m->y;
w = m->w;
wmax = 0;
hadd = ((m->mopt & MC_NOBOX) ? 0 : 2);
wadd = ((m->mopt & MC_NOBOX) ? 2 : 4);
if (!(m->mopt & MC_NOSHORTCUT))
wadd += 3;
if (m->title && *(title = MSG_XLAT(m->title)) != 0) {
/* Allow multiple line titles */
for (tp = title; (ep = strchr(tp, '\n')); tp = ep + 1) {
i = ep - tp;
wmax = MAX(wmax, i);
hadd++;
}
hadd++;
i = strlen(tp);
wmax = MAX(wmax, i);
if (i != 0)
hadd++;
} else {
m->title = NULL;
title = "untitled";
}
exithadd = ((m->mopt & MC_NOEXITOPT) ? 0 : 1);
#ifdef MSG_DEFS_H
if (y < 0) {
/* put menu box below message text */
y = -y;
i = msg_row();
if (i > y)
y = i;
}
#endif
/* Calculate h? h == number of visible options. */
if (m->h == 0)
m->h = m->numopts + exithadd;
if (m->h > max_lines - y - hadd) {
/* Not enough space for all the options */
if (m->h <= 4 || !(m->mopt & (MC_SCROLL | MC_ALWAYS_SCROLL))) {
/* move menu up screen */
y = max_lines - hadd - m->h;
if (y < 0)
y = 0;
}
m->h = max_lines - y - hadd;
}
if (m->h < m->numopts + exithadd || m->mopt & MC_ALWAYS_SCROLL) {
/* We need to add the scroll text...
* The used to be a check for MC_SCROLL here, but it is
* fairly pointless - you just don't want the program
* to exit on this sort of error.
*/
if (m->h < 3) {
endwin();
(void)fprintf(stderr,
"Window too short (m->h %d, m->numopts %d, exithadd %d, y %d, max_lines %d, hadd %d) for menu \"%.30s\"\n",
m->h, m->numopts, exithadd, y, max_lines, hadd,
title);
exit(1);
}
hadd++;
m->h = MIN(m->h, max_lines - y - hadd);
i = strlen(scrolltext);
wmax = MAX(wmax, i);
}
/* Calculate w? */
if (w == 0) {
int l;
for (i = 0; i < m->numopts; i++) {
tp = MSG_XLAT(m->opts[i].opt_name);
if (tp == NULL)
continue;
l = strlen(tp);
wmax = MAX(wmax, l);
}
w = wmax;
}
/* check and adjust for screen fit */
if (w + wadd > max_cols) {
endwin();
(void)fprintf(stderr,
"Screen too narrow (%d + %d > %d) for menu \"%s\"\n",
w, wadd, max_cols, title);
exit(1);
}
if (x == -1)
x = (max_cols - (w + wadd)) / 2; /* center */
else if (x + w + wadd > max_cols)
x = max_cols - (w + wadd); /* right align */
if (y == 0) {
/* Center - rather than top */
y = (max_lines - hadd - m->h) / 2;
}
/* Get the windows. */
m->mw = newwin(m->h + hadd, w + wadd, y, x);
if (m->mw == NULL) {
endwin();
(void)fprintf(stderr,
"Could not create window (%d + %d, %d + %d, %d, %d) for menu \"%s\"\n",
m->h, hadd, w, wadd, y, x, title);
exit(1);
}
keypad(m->mw, TRUE); /* enable multi-key assembling for win */
/* XXX is it even worth doing this right? */
if (has_colors()) {
wbkgd(m->mw, COLOR_PAIR(1));
wattrset(m->mw, COLOR_PAIR(1));
}
if (m->mopt & MC_SUBMENU) {
/* Keep a copy of what is on the screen under the window */
m->sv_mw = newwin(m->h + hadd, w + wadd, y, x);
/*
* cursrc contains post-doupdate() data, not post-refresh()
* data so we must call doupdate to ensure we save the
* correct data. Avoids PR 26660.
*/
doupdate();
if (m->sv_mw)
overwrite(curscr, m->sv_mw);
}
}
static char
opt_ch(menudesc *m, int op_no)
{
char c;
if (op_no == m->numopts)
return 'x';
if (op_no < 25) {
c = 'a' + op_no;
if (c >= 'x')
c++;
} else
c = 'A' + op_no - 25;
return c;
}
static void
draw_menu_line(menudesc *m, int opt, int cury, void *arg, const char *text)
{
int hasbox = m->mopt & MC_NOBOX ? 0 : 1;
if (m->cursel == opt) {
mvwaddstr(m->mw, cury, hasbox, ">");
wstandout(m->mw);
} else
mvwaddstr(m->mw, cury, hasbox, " ");
if (!(m->mopt & MC_NOSHORTCUT))
wprintw(m->mw, "%c: ", opt_ch(m, opt));
if (!text && m->draw_line)
m->draw_line(m, opt, arg);
else
waddstr(m->mw, MSG_XLAT(text));
if (m->cursel == opt)
wstandend(m->mw);
}
static void
draw_menu(menudesc *m, void *arg)
{
int opt;
int hasbox, cury, maxy;
int tadd;
int hasexit = (m->mopt & MC_NOEXITOPT ? 0 : 1);
const char *tp, *ep;
hasbox = (m->mopt & MC_NOBOX ? 0 : 1);
/* Clear the window */
wclear(m->mw);
tadd = hasbox;
if (m->title) {
for (tp = MSG_XLAT(m->title); ; tp = ep + 1) {
ep = strchr(tp , '\n');
mvwaddnstr(m->mw, tadd++, hasbox + 1, tp,
ep ? ep - tp : -1);
if (ep == NULL || *ep == 0)
break;
}
tadd++;
}
cury = tadd;
maxy = getmaxy(m->mw) - hasbox;
if (m->numopts + hasexit > m->h)
/* allow for scroll text */
maxy--;
if (m->cursel == -1) {
m->cursel = m->numopts;
if (m->h <= m->numopts)
m->topline = m->numopts + 1 - m->h;
}
while (m->cursel >= m->topline + m->h)
m->topline = MIN(m->topline + m->h,
m->numopts + hasexit - m->h);
while (m->cursel < m->topline)
m->topline = MAX(0, m->topline - m->h);
for (opt = m->topline; opt < m->numopts; opt++) {
if (cury >= maxy)
break;
draw_menu_line(m, opt, cury++, arg, m->opts[opt].opt_name);
}
/* Add the exit option. */
if (!(m->mopt & MC_NOEXITOPT)) {
if (cury < maxy)
draw_menu_line(m, m->numopts, cury++, arg, m->exitstr);
else
opt = 0;
}
/* Add the scroll line */
if (opt != m->numopts || m->topline != 0)
mvwaddstr(m->mw, cury, hasbox, scrolltext);
/* Add the box. */
if (!(m->mopt & MC_NOBOX))
box(m->mw, 0, 0);
wmove(m->mw, tadd + m->cursel - m->topline, hasbox);
wrefresh(m->mw);
}
static void
/*ARGSUSED*/
process_help(menudesc *m)
{
const char *help = m->helpstr;
WINDOW *sv_curscr;
int lineoff = 0;
int curoff = 0;
int again;
int winin;
/* Is there help? */
if (!help) {
mbeep();
return;
}
sv_curscr = newwin(getmaxy(curscr), getmaxx(curscr), 0, 0);
if (!sv_curscr) {
mbeep();
return;
}
/*
* Save screen contents so we can restore before returning.
* cursrc contains post-doupdate() data, not post-refresh()
* data so we must call doupdate to ensure we save the
* correct data. Avoids PR 26660.
*/
doupdate();
overwrite(curscr, sv_curscr);
touchwin(stdscr);
help = MSG_XLAT(help);
/* Display the help information. */
do {
if (lineoff < curoff) {
help = MSG_XLAT(m->helpstr);
curoff = 0;
}
while (*help && curoff < lineoff) {
if (*help == '\n')
curoff++;
help++;
}
wclear(stdscr);
mvwaddstr(stdscr, 0, 0,
"Help: exit: x, page up: u <, page down: d >");
mvwaddstr(stdscr, 2, 0, help);
wmove(stdscr, 1, 0);
wrefresh(stdscr);
do {
winin = wgetch(stdscr);
if (winin < KEY_MIN)
winin = tolower(winin);
again = 0;
switch (winin) {
case '<':
case 'u':
case KEY_UP:
case KEY_LEFT:
case KEY_PPAGE:
if (lineoff)
lineoff -= max_lines - 2;
else
again = 1;
break;
case '>':
case 'd':
case KEY_DOWN:
case KEY_RIGHT:
case KEY_NPAGE:
if (*help)
lineoff += max_lines - 2;
else
again = 1;
break;
case 'q':
break;
case 'x':
winin = 'q';
break;
default:
again = 1;
}
if (again)
mbeep();
} while (again);
} while (winin != 'q');
/* Restore the original screen contents */
touchwin(sv_curscr);
wnoutrefresh(sv_curscr);
delwin(sv_curscr);
/* Some code thinks that wrefresh(stdout) is a good idea... */
wclear(stdscr);
}
static void
process_req(menudesc *m, void *arg, int req)
{
int ch;
int hasexit = (m->mopt & MC_NOEXITOPT ? 0 : 1);
switch(req) {
case REQ_EXECUTE:
return;
case REQ_NEXT_ITEM:
ch = m->cursel;
for (;;) {
ch++;
if (ch >= m->numopts + hasexit) {
mbeep();
return;
}
if (hasexit && ch == m->numopts)
break;
if (!(m->opts[ch].opt_flags & OPT_IGNORE))
break;
}
m->cursel = ch;
if (m->cursel >= m->topline + m->h)
m->topline = m->cursel - m->h + 1;
break;
case REQ_PREV_ITEM:
ch = m->cursel;
for (;;) {
if (ch <= 0) {
mbeep();
return;
}
ch--;
if (!(m->opts[ch].opt_flags & OPT_IGNORE))
break;
}
m->cursel = ch;
if (m->cursel < m->topline)
m->topline = m->cursel;
break;
case REQ_HELP:
process_help(m);
break;
case REQ_REDISPLAY:
endwin();
doupdate();
break;
case REQ_SCROLLUP:
if (m->cursel == 0) {
mbeep();
return;
}
m->topline = MAX(0, m->topline - m->h);
m->cursel = MAX(0, m->cursel - m->h);
wclear(m->mw);
break;
case REQ_SCROLLDOWN:
if (m->cursel >= m->numopts + hasexit - 1) {
mbeep();
return;
}
m->topline = MIN(m->topline + m->h,
MAX(m->numopts + hasexit - m->h, 0));
m->cursel = MIN(m->numopts + hasexit - 1, m->cursel + m->h);
wclear(m->mw);
break;
default:
ch = req;
if (ch == 'x' && hasexit) {
m->cursel = m->numopts;
break;
}
if (m->mopt & MC_NOSHORTCUT) {
mbeep();
return;
}
if (ch > 'z')
ch = 255;
if (ch >= 'a') {
if (ch > 'x')
ch--;
ch = ch - 'a';
} else
ch = 25 + ch - 'A';
if (ch < 0 || ch >= m->numopts) {
mbeep();
return;
}
if (m->opts[ch].opt_flags & OPT_IGNORE) {
mbeep();
return;
}
m->cursel = ch;
}
draw_menu(m, arg);
}
int
menu_init(void)
{
int i;
if (__menu_init)
return 0;
#ifdef USER_MENU_INIT
if (USER_MENU_INIT)
return 1;
#endif
if (initscr() == NULL)
return 1;
cbreak();
noecho();
/* XXX Should be configurable but it almost isn't worth it. */
if (has_colors()) {
start_color();
init_pair(1, COLOR_WHITE, COLOR_BLUE);
bkgd(COLOR_PAIR(1));
attrset(COLOR_PAIR(1));
}
max_lines = getmaxy(stdscr);
max_cols = getmaxx(stdscr);
keypad(stdscr, TRUE);
#ifdef DYNAMIC_MENUS
num_menus = DYN_INIT_NUM;
while (num_menus < DYN_MENU_START)
num_menus *= 2;
menu_list = malloc(sizeof *menu_list * num_menus);
if (menu_list == NULL)
return 2;
(void)memset(menu_list, 0, sizeof *menu_list * num_menus);
for (i = 0; i < DYN_MENU_START; i++)
menu_list[i] = &menu_def[i];
#endif
__menu_init = 1;
return 0;
}
void
process_menu(int num, void *arg)
{
int sel = 0;
int req;
menu_ent *opt;
menudesc *m;
/* Initialize? */
if (menu_init()) {
__menu_initerror();
return;
}
if (num < 0 || num >= num_menus)
return;
m = &MENUS(num);
if (m == NULL)
return;
/* Default to select option 0 and display from 0 */
m->topline = 0;
if ((m->mopt & (MC_DFLTEXIT | MC_NOEXITOPT)) == MC_DFLTEXIT)
m->cursel = -1;
else
m->cursel = 0;
for (;;) {
if (isendwin())
/* I'm not sure this is needed with netbsd's curses */
doupdate();
/* Process the display action */
if (m->post_act)
(*m->post_act)(m, arg);
if (m->mw == NULL)
init_menu(m);
draw_menu(m, arg);
while ((req = menucmd(m->mw)) != REQ_EXECUTE)
process_req(m, arg, req);
sel = m->cursel;
if (!(m->mopt & MC_NOCLEAR)) {
wclear(m->mw);
if (m->sv_mw)
overwrite(m->sv_mw, m->mw);
wnoutrefresh(m->mw);
}
/* Process the items */
if (sel >= m->numopts)
/* exit option */
break;
opt = &m->opts[sel];
if (opt->opt_flags & OPT_IGNORE)
continue;
if (opt->opt_flags & OPT_ENDWIN)
endwin();
if (opt->opt_action && (*opt->opt_action)(m, arg))
break;
if (opt->opt_menu != -1) {
if (!(opt->opt_flags & OPT_SUB)) {
num = opt->opt_menu;
wclear(m->mw);
if (m->sv_mw) {
overwrite(m->sv_mw, m->mw);
delwin(m->sv_mw);
m->sv_mw = NULL;
}
wnoutrefresh(m->mw);
delwin(m->mw);
m->mw = NULL;
m = &MENUS(num);
continue;
}
process_menu(opt->opt_menu, arg);
}
if (opt->opt_flags & OPT_EXIT)
break;
}
if (m->mopt & MC_NOCLEAR) {
wclear(m->mw);
if (m->sv_mw)
overwrite(m->sv_mw, m->mw);
wnoutrefresh(m->mw);
}
/* Process the exit action */
if (m->exit_act)
(*m->exit_act)(m, arg);
delwin(m->mw);
m->mw = NULL;
if (m->sv_mw) {
delwin(m->sv_mw);
m->sv_mw = NULL;
}
}
void
set_menu_numopts(int menu, int numopts)
{
MENUS(menu).numopts = numopts;
}
/* Control L is end of standard routines, remaining only for dynamic. */
/* Beginning of routines for dynamic menus. */
static int
double_menus(void)
{
menudesc **temp;
int sz = sizeof *menu_list * num_menus;
temp = realloc(menu_list, sz * 2);
if (temp == NULL)
return 0;
(void)memset(temp + num_menus, 0, sz);
menu_list = temp;
num_menus *= 2;
return 1;
}
int
new_menu(const char *title, menu_ent *opts, int numopts,
int x, int y, int h, int w, int mopt,
void (*post_act)(menudesc *, void *),
void (*draw_line)(menudesc *, int, void *),
void (*exit_act)(menudesc *, void *),
const char *help, const char *exit_str)
{
int ix;
menudesc *m;
/* Find free menu entry. */
for (ix = DYN_MENU_START; ; ix++) {
if (ix >= num_menus && !double_menus())
return -1;
m = menu_list[ix];
if (m == NULL) {
m = calloc(sizeof *m, 1);
if (m == NULL)
return -1;
menu_list[ix] = m;
break;
}
if (!(m->mopt & MC_VALID))
break;
}
/* Set Entries */
m->title = title;
m->opts = opts;
m->numopts = numopts;
m->x = x;
m->y = y;
m->h = h;
m->w = w;
m->mopt = mopt | MC_VALID;
m->post_act = post_act;
m->draw_line = draw_line;
m->exit_act = exit_act;
m->helpstr = help;
m->exitstr = exit_str ? exit_str : "Exit";
return ix;
}
void
free_menu(int menu_no)
{
menudesc *m;
if (menu_no < 0 || menu_no >= num_menus)
return;
m = menu_list[menu_no];
if (!(m->mopt & MC_VALID))
return;
if (m->mw != NULL)
delwin(m->mw);
memset(m, 0, sizeof *m);
}

544
usr.bin/menuc/menuc.1 Normal file
View file

@ -0,0 +1,544 @@
.\" $NetBSD: menuc.1,v 1.30 2012/03/06 16:55:18 mbalmer Exp $
.\"
.\" Copyright 1997 Piermont Information Systems Inc.
.\" All rights reserved.
.\"
.\" Written by Philip A. Nelson for Piermont Information Systems Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of Piermont Information Systems Inc. may not be used to endorse
.\" or promote products derived from this software without specific prior
.\" written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 2, 2004
.Dt MENUC 1
.Os
.Sh NAME
.Nm menuc
.Nd menu compiler
.Sh SYNOPSIS
.Nm
.Op Fl o Ar name
.Ar file
.Sh DESCRIPTION
This implements a curses based menu system.
A source file that describes menus, their options, and how to process
the options is given to
.Nm
and produces both a .c and a .h file that implement the menu system.
The standard base name of the files is
.Pa menu_defs .
The
.Fl o Ar name
can be used to specify a different base name.
.Sh ENVIRONMENT
.Bl -tag -width MENUDEF
.It Ev MENUDEF
Can be set to point to a different set of definition files for
.Nm .
The current location defaults to
.Pa /usr/share/misc .
.El
.Sh MENU DESCRIPTIONS
The input
.Ar file
defines static menus and options for processing those menus.
It also contains comments, initial C code that is required to provide
for definitions and other code necessary for the menu system, and an
option declaration if dynamic menus are requested.
.Pp
Comments may appear anywhere in the input
.Ar file
and are like a space in the input.
They are like C comments starting with
.Em /*
and ending with
.Em */ .
They are unlike C comments in that they may be nested.
A comment does not end until a matching end comment is found.
.Pp
In many places, C code is included in the definition
.Ar file .
All C code is passed verbatim to the C output file.
.Nm
comments do not start in C code and comments in the C code are
passed verbatim to the output.
The C comments are not recognized by
.Nm .
In all cases, C code starts with a left brace
.Pq Em \&{
and ends with the matching right brace
.Pq Em \&} .
It is important to recognize that in code segments, any brace
will be counted, even if it is in a C comment inside the code.
.Pp
The
.Ar file
contains an initial (and optional) code block followed by any
number of menu definition elements in any order.
The initial code block usually contains includes of header files used by
code in the menu code blocks later in the
.Ar file .
If
.Dv USER_MENU_INIT
is #defined, then it will be evaluated before the
rest of the menu is initialised, if it evaluates to a non-zero value
then the initialisation will fail.
The file is free format, so the actual formatting of the input
.Ar file
is to the taste of the programmer.
.Pp
All other C code that will appear in an
.Em action .
This will be specified as
.Aq Em action
in later text.
Such an action will appear as:
.Dl action \*[Lt]opt_endwin\*[Gt] \*[Lt]code\*[Gt]
in the
.Ar file .
The
.Aq Em opt_endwin ,
if present is:
.Dl ( endwin )
and specifies that the curses
.Fn endwin
function should be called before executing the code and
then reinstating the current curses window after the
code has been run.
The
.Aq Em code
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
change at run time.
The 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 ;
The semicolon is required to terminate this declaration.
This declaration may appear anywhere in the
.Ar file ,
but usually appears before any menus are defined.
.Pp
The next element is a code block to execute if the curses
screen can not be successfully initialized.
The declaration
.Dl error code ;
tells the menu system to execute the associated code block
if the initialization fails.
If no code is provided, a default code block is used that prints
.Dl Could not initialize curses.
and exits.
This element may appear anywhere in the
.Ar file
but usually appears before any menus are defined.
.Pp
The next element defines default options for menus.
Each menu is built from a list of options.
These options include the location of the upper left corner of the menu,
whether there is a "box" drawn around the menu, whether the menu is
scrollable, the menu's title, whether shortcut letters are
allowed, whether a standard exit option should be included
in the menu and text associated with the standard exit option.
The general format is:
.Dl default \*[Lt]comma separated option list\*[Gt] ;
.Pp
The supported options are:
.Bl -tag -width ".Ic exitstring Va text"
.It Ic x = Va startx
The column number of the upper left corner of the menu window.
If
.Va startx
is -1 the menu will be centered horizontally.
.It Ic y = Va starty
The row number of the upper left corner of the menu window.
If
.Va starty
is negative then the menu will be placed below any message text, but
in at least row
.Va -starty .
.It Ic h = Va height
Specifies the number of menu entries to be displayed.
If zero, the height will be based on the number of entries.
.It Ic h = Va width
Specifies the width of the menu window.
If zero, the width will be that of the longest menu text line.
.It Ic title Va text
The specified
.Va text
will be displayed at the top of the menu window (inside any box).
.It Ic box
If specified, draw a box around the menu.
.It Ic clear
If specified, clear the window before performing the
.Va action .
.It Ic exit
If specified add an addition option to exit the menu.
.It Ic exitstring Va text
The menu label for the
.Va exit
option.
If not specified defaults to "exit".
.It Ic default exit
If specified, place the cursor on the
.Va exit
line of the menu, instead of the top line.
.It Ic shortcut
If specified, add alphabetic tags to each menu line.
.It Ic scrollable
If specified, and the menu has more lines than will fit in its window, then
only part of the menu will be displayed and the
.Sq \*[Lt]
and
.Sq \*[Gt]
keys will scroll the displayed menu lines.
.It Ic always scroll
If specified, allow for the scroll message line even if the menu doesn't
appear to have too many lines.
Useful for dynamic menus, when the number of entries isn't known when the
menu window is created..
.It Ic sub menu
If specified, the screen contents that the menu window overwrites are saved
and restored when the menu exits.
.El
The
.Ic box , clear , exit , default exit , shortcut , scrollable , always scroll ,
and
.Ic sub menu
options can be preceded by
.Ic no
in order to negate a default.
.Pp
The
.Va text
arguments can be either a quoted text string or a name #defined to something
suitable for initialising a const char * field.
.Pp
The default declaration may appear multiple times.
Each time, it sets the default values for menu definitions that follow
in the
.Ar file .
In each menu definition, any or all of these default definitions
may be overridden for that menu.
.Pp
The final element is the actual static menu definitions.
The format and order for a menu definition is:
.Bd -ragged -offset indent
menu \*[Lt]name\*[Gt] \*[Lt]options\*[Gt] ;
\*[Lt]display action\*[Gt]
\*[Lt]menu items\*[Gt]
\*[Lt]exit action\*[Gt]
\*[Lt]help text\*[Gt]
.Ed
.Pp
Names are unquoted strings of alpha-numeric and underscore
characters.
They must start with an alpha character.
In C source, a menu named
.Dq foo
is appears as
.Dq MENU_foo .
(Capitalization is important.)
This is important, because the menu is displayed and processed by
calling the function
.Dl process_menu (MENU_foo, arg) ;
.Pp
The options are a comma separated list of options as in the
.Dq default
declaration.
These override the options from the most recent default declaration.
.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:
.Dl display \*[Lt]action\*[Gt] ;
.Pp
The bulk of the menu definition is the specification
of the menu items.
The general format of a menu item is:
.Dl option \*[Lt]string\*[Gt], \*[Lt]element_list\*[Gt] ;
The
.Aq Em string
is the text displayed for the menu item, this must be a quoted string
or a name #defined to something that will initialise a const char * field.
There may be an arbitrary number of these items.
(If there are shortcuts in the menu, a practical limit
of 51 should be recognized.
It produces shortcuts a to w, y, z, and A to Z.
x is the shortcut for the exit item.)
.Pp
The
.Aq Em element_list
is a comma separated list of what to do when the item is selected.
They may appear in any order.
.Pp
The first element processed when a menu item
is selected is the associated action.
The next element to be processed is the sub or next menu option.
They are declared as:
.Dl next menu \*[Lt]name\*[Gt]
.Dl sub menu \*[Lt]name\*[Gt]
The difference between these two is that a sub
menu will return to the current menu when exited.
The next menu will just replace the current
menu and when exited, will return to where the
current menu would have gone.
Only one of menu element may be used for each menu item.
Finally, after processing both the action and a sub menu,
the current menu will be exited if the element
.Dl exit
is specified.
.Em Note :
If
.Em exit
is specified, next menu will not work because
the menu system will exit the
.Em current
menu, even if current has been set by
.Em next menu .
.Pp
After all menu items, the final two menu definition
elements may appear.
The exit action is optional and provides C code to
execute in the process of exiting a menu.
If it is included, the format is:
.Dl exit \*[Lt]action\*[Gt] ;
.Pp
The final part of the menu definition is the optional
help string.
The format is:
.Dl help \*[Lt]text\*[Gt] ;
This text is displayed in a full page
help window if the question mark is typed.
The actual help text starts with a left brace
.Pq Em \&{
and ends with the matching right brace
.Pq Em \&} .
The braces are not included in the
help string, but all other characters between
them are included.
Newlines in the code translate to newlines in the help text.
Alternatively, the name of a const char * variable may be given.
.Sh DYNAMIC MENUS
If requested,
.Nm
supports dynamic menus by allowing the user to create new
menus.
The related definitions for using dynamic menus are:
.Bd -literal
struct menudesc;
typedef
struct menu_ent {
const char *opt_name;
int opt_menu;
int opt_flags;
int (*opt_action)(struct menudesc *, void *);
} menu_ent ;
/* For opt_menu */
#define OPT_NOMENU -1
/* For opt_flags */
#define OPT_SUB 1
#define OPT_ENDWIN 2
#define OPT_EXIT 4
typedef
struct menudesc {
const char *title;
int y, x;
int h, w;
int mopt;
int numopts;
int cursel;
int topline;
menu_ent *opts;
WINDOW *mw;
WINDOW *sv_mw;
const char *helpstr;
const char *exitstr;
void (*post_act)(struct menudesc *, void *);
void (*exit_act)(struct menudesc *, void *);
void (*draw_line)(struct menudesc *, int, void *);
} menudesc ;
/* defines for mopt field. */
#define MC_NOEXITOPT 1
#define MC_NOBOX 2
#define MC_SCROLL 4
#define MC_NOSHORTCUT 8
#define MC_NOCLEAR 16
#define MC_DFLTEXIT 32
#define MC_ALWAYS_SCROLL 64
#define MC_SUBMENU 128
int new_menu(const char *title, menu_ent *opts, int numopts,
int x, int y, int h, int w, int mopt,
void (*post_act)(struct menudesc *, void *),
void (*draw_line)(struct menudesc *, int, void *),
void (*exit_act)(struct menudesc *, void *),
const char *help, const char *exitstr);
void free_menu (int menu_no);
.Ed
.Pp
The
.Ar title
is the title displayed at the top of the menu.
The
.Ar opts
is an array of menu entry definitions that has
.Ar numopts
elements.
The programmer must build this array and
fill in all of the fields before processing calling
.Fn process_menu
for the new menu.
The fields of the
.Ar opts
may change at any time.
For example,
.Em opt_name
may change as a result of selecting that option.
When the menu is redisplayed, the new text is printed.
Arguments,
.Ar x , y , h ,
and
.Ar w
are the same as the options in the menu description.
.Ar mopt
is the boolean options.
Note, box, clear, exit and shortcuts are enabled by default.
You need to add option flags to turn them off or turn on scrollable menus.
The options
.Ar post_act ,
and
.Ar exit_act
are function pointers to the display action and the exit action.
If they are
.Dv NULL ,
no call will be made.
.Ar draw_line
will be called to display the menu line if the corresponding opt_name
field is
.Dv NULL .
.Ar help
is the text to display in a help screen.
And finally,
.Ar exitstr
is the text for the 'exit' line of the menu.
If
.Dv NULL ,
"Exit" is used.
A
.Dv NULL
help pointer will disable the help feature for the menu.
.Sh FILES
.Bl -item
.It
.Pa /usr/share/misc/menu_sys.def
.El
.Sh EXAMPLES
The following is a simple menu definition file.
It is complete in that the output of
.Nm
may be compiled into a complete program.
For example, if the following was in a file called
.Pa example.mc ,
an executable program could be produced by the following commands.
.Bd -literal -offset indent
menuc -o example example.mc
cc -o example example.c -lcurses
.Ed
A much more complete example is available with the source
distribution in a subdirectory called
.Em testm .
.Bd -literal
/* This is an example menu definition file for menuc. */
{
#include \*[Lt]stdio.h\*[Gt]
#include \*[Lt]unistd.h\*[Gt]
/* Main program! This is often in a different file. */
int
main()
{
process_menu (MENU_main, NULL);
endwin();
return 0;
}
/* Example initialize function! */
void
init_main()
{
}
}
default x=20, y=10, box, scrollable, exit;
error action {
fprintf (stderr, "Example Menu: Could not initialize curses.");
exit(1);
};
menu main, title "Main Menu", no exit, no shortcut;
display action { init_main(); };
option "Option 1",
action (endwin) {
printf ("That was option 1!");
sleep(3);
};
option "Sub Menu", sub menu othermenu;
option "Next Menu", next menu othermenu;
option "Quit", exit;
help {
This is a simple help screen for an example menu definition file.
};
menu othermenu, title "Sub/Next Menu", x=5, y=5, no box;
option "Do Nothing!", action { };
.Ed
.Sh SEE ALSO
.Xr msgc 1
.Sh AUTHORS
.An Philip A. Nelson
for Piermont Information Systems Inc.
Initial ideas for this were developed and implemented in Pascal at the
Leiden University, Netherlands, in the summer of 1980.
.Sh BUGS
Both
.Nm
and
.Nm msgc
are probably only used by
.Nm sysinst .
The features of both have been tailored for
.Nm sysinst ,
and further changes are likely to occur.

228
usr.bin/menuc/parse.y Normal file
View file

@ -0,0 +1,228 @@
/* $NetBSD: parse.y,v 1.16 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
%{
#include <stdio.h>
#include "defs.h"
static id_rec *cur_menu;
static optn_info *cur_optn;
%}
%union {
char *s_value;
int i_value;
optn_info *optn_value;
action a_value;
}
%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 <s_value> STRING NAME CODE INT_CONST CHAR_CONST
%type <s_value> init_code system helpstr text
%type <optn_value> option option_list
%type <i_value> act_opt
%type <a_value> action exitact
%start system
%%
system : init_code menu_list
{ check_defined();
if (!had_errors)
write_menu_file($1);
}
;
init_code : /* empty */ { $$ = ""; }
| CODE
;
menu_list : /* empty */
| menu_list menu_def
| menu_list default_def
| menu_list initerror_def
| menu_list dynamic_def
| menu_list msgxlat_def
;
dynamic_def : ALLOW DYNAMIC MENUS ';'
{ do_dynamic = 1; }
msgxlat_def : ALLOW DYNAMIC MESSAGES ';'
{ do_msgxlat = 1; }
initerror_def : ERROR action ';'
{ error_act = $2; }
default_def : DEFAULT
{ cur_menu = &default_menu; }
opt opt_list ";"
menu_def : MENU NAME
{ cur_menu = get_menu ($2);
if (cur_menu->info != NULL)
yyerror ("Menu %s defined twice", $2);
else {
cur_menu->info =
(menu_info *) malloc (sizeof (menu_info));
*(cur_menu->info) = default_info;
}
}
opts ";" dispact option_list exitact helpstr
{ optn_info *t;
cur_menu->info->optns = NULL;
while ($7 != NULL) {
t = $7;
$7 = $7->next;
t->next = cur_menu->info->optns;
cur_menu->info->optns = t;
cur_menu->info->numopt++;
}
}
;
opts : /* empty */
| opt_list
;
opt_list : "," opt
| opt_list "," opt
;
text : NAME | STRING
opt : NO EXIT { cur_menu->info->mopt |= MC_NOEXITOPT; }
| EXIT { cur_menu->info->mopt &= ~MC_NOEXITOPT; }
| NO BOX { cur_menu->info->mopt |= MC_NOBOX; }
| BOX { cur_menu->info->mopt &= ~MC_NOBOX; }
| NO SCROLLABLE { cur_menu->info->mopt &= ~MC_SCROLL; }
| SCROLLABLE { cur_menu->info->mopt |= MC_SCROLL; }
| NO SHORTCUT { cur_menu->info->mopt |= MC_NOSHORTCUT; }
| SHORTCUT { cur_menu->info->mopt &= ~MC_NOSHORTCUT; }
| NO CLEAR { cur_menu->info->mopt |= MC_NOCLEAR; }
| CLEAR { cur_menu->info->mopt &= ~MC_NOCLEAR; }
| NO DEFAULT EXIT { cur_menu->info->mopt &= ~MC_DFLTEXIT; }
| DEFAULT EXIT { cur_menu->info->mopt |= MC_DFLTEXIT; }
| NO ALWAYS SCROLL { cur_menu->info->mopt &= ~MC_ALWAYS_SCROLL; }
| ALWAYS SCROLL { cur_menu->info->mopt |= MC_ALWAYS_SCROLL; }
| NO SUB MENU { cur_menu->info->mopt &= ~MC_SUBMENU; }
| SUB MENU { cur_menu->info->mopt |= MC_SUBMENU; }
| X "=" INT_CONST { cur_menu->info->x = atoi($3); }
| Y "=" INT_CONST { cur_menu->info->y = atoi($3); }
| W "=" INT_CONST { cur_menu->info->w = atoi($3); }
| H "=" INT_CONST { cur_menu->info->h = atoi($3); }
| TITLE text { cur_menu->info->title = $2; }
| EXITSTRING text { cur_menu->info->exitstr = $2;
cur_menu->info->mopt &= ~MC_NOEXITOPT; }
;
option_list : option
| option_list option { $2->next = $1; $$ = $2; }
;
option : OPTION
{ cur_optn = (optn_info *) malloc (sizeof(optn_info));
cur_optn->menu = -1;
cur_optn->name = NULL;
cur_optn->name_is_code = FALSE;
cur_optn->issub = FALSE;
cur_optn->doexit = FALSE;
cur_optn->optact.code = "";
cur_optn->optact.endwin = FALSE;
cur_optn->next = NULL;
}
option_legend ","
elem_list ";"
{ $$ = cur_optn; }
;
option_legend : text { cur_optn->name = $1; }
| CODE { cur_optn->name = $1; cur_optn->name_is_code = TRUE;}
elem_list : elem
| elem_list "," elem
;
elem : NEXT MENU NAME
{ id_rec *t = get_menu ($3);
if (cur_optn->menu != -1)
yyerror ("Double sub/next menu definition");
else {
cur_optn->menu = t->menu_no;
}
}
| SUB MENU NAME
{ id_rec *t = get_menu ($3);
if (cur_optn->menu != -1)
yyerror ("Double sub/next menu definition");
else {
cur_optn->menu = t->menu_no;
cur_optn->issub = TRUE;
}
}
| action { cur_optn->optact = $1; }
| EXIT { cur_optn->doexit = TRUE; }
;
action : ACTION act_opt CODE
{ $$.code = $3;
$$.endwin = $2;
}
;
act_opt : /* empty */ { $$ = 0; }
| "(" ENDWIN ")" { $$ = 1; }
;
dispact : /* empty */ { cur_menu->info->postact.code = ""; }
| DISPLAY action ";" { cur_menu->info->postact = $2; }
;
exitact : /* empty */ { cur_menu->info->exitact.code = ""; }
| EXIT action ";" { cur_menu->info->exitact = $2; }
;
helpstr : /* empty */ { cur_menu->info->helpstr = NULL; }
| HELP CODE ";" { asprintf(&cur_menu->info->helpstr, "\"%s\"", $2); }
| HELP text ";" { cur_menu->info->helpstr = $2; }
;

View file

@ -0,0 +1,5 @@
/* $NetBSD: pathnames.h,v 1.1 2001/10/15 22:20:03 bjh21 Exp $ */
#ifndef _PATH_DEFSYSPREFIX
#define _PATH_DEFSYSPREFIX "/usr/share/misc"
#endif

196
usr.bin/menuc/scan.l Normal file
View file

@ -0,0 +1,196 @@
/* $NetBSD: scan.l,v 1.16 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
%{
/* scan.l: scanner description for menu compiler. */
#include <stdio.h>
#include <string.h>
#include "defs.h"
#include "parse.h"
static int level; /* For nested comments. */
static int comstart; /* line number of comment start. */
%}
%x COMMENT
%x BRACE
%option noinput
%%
[ \t]+ { /* ignore spaces and tabs */ }
[\n] { line_no++; }
"="|";"|","|"("|")" { return (int)yytext[0]; }
x { return X; }
y { return Y; }
w { return W; }
h { return H; }
no { return NO; }
box { return BOX; }
sub { return SUB; }
help { return HELP; }
menu { return MENU; }
menus { return MENUS; }
next { return NEXT; }
exit { return EXIT; }
exitstring { return EXITSTRING; }
title { return TITLE; }
action { return ACTION; }
endwin { return ENDWIN; }
option { return OPTION; }
default { return DEFAULT; }
display { return DISPLAY; }
error { return ERROR; }
allow { return ALLOW; }
dynamic { return DYNAMIC; }
messages { return MESSAGES; }
scrollable { return SCROLLABLE; }
shortcut { return SHORTCUT; }
clear { return CLEAR; }
always { return ALWAYS; }
scroll { return SCROLL; }
\"([^\"\n]*(\\\")?)*\" {
yylval.s_value = strdup (yytext);
max_strlen = max_strlen > strlen(yytext)
? max_strlen : strlen(yytext) + 1;
return STRING;
}
[a-zA-Z][a-zA-Z0-9_]* {
yylval.s_value = strdup(yytext);
return(NAME);
}
0|[-1-9][0-9]* {
yylval.s_value = strdup(yytext);
return(INT_CONST);
}
"'"[^'\\]|(\\[athrn])|(\\[0-9][0-9]?[0-9]?)"'" {
yylval.s_value = strdup(yytext);
return(CHAR_CONST);
}
"/*" { level = 1; comstart = line_no; BEGIN COMMENT; }
<COMMENT>"/*" { level++; }
<COMMENT>"*/" { if (level-- == 1) BEGIN 0; }
<COMMENT>"\n" { line_no++; }
<COMMENT><<EOF>> {
yyerror ("EOF inside a comment that started at line %d",
comstart);
exit (1);
}
<COMMENT>. {/* eat character */}
"{" { level = 1; BEGIN BRACE; }
<BRACE>"{" { buff_add_ch(yytext[0]); level++; }
<BRACE>"}" { if (level-- == 1) {
BEGIN 0;
yylval.s_value = buff_copy();
return CODE;
} else
buff_add_ch (yytext[0]);
}
<BRACE>"\n" { buff_add_ch (yytext[0]); line_no++; }
<BRACE>. { buff_add_ch (yytext[0]); }
. {
if (yytext[0] < ' ')
yyerror ("illegal character: ^%c",yytext[0] + '@');
else
if (yytext[0] > '~')
yyerror ("illegal character: \\%3d", (int) yytext[0]);
else
yyerror ("illegal character: %s",yytext);
/* To quiet the compiler */
if (0) unput(0);
}
%%
#ifdef SCAN
YYSTYPE yylval;
main()
{
int val;
line_no = 1;
while ( (val = yylex()) != 0 )
printf ("val = %d\n yytext = %s\n", val, yytext);
}
#endif

View file

@ -0,0 +1,27 @@
# $NetBSD: Makefile,v 1.17 2012/04/21 12:27:29 roy Exp $
NOMAN= # defined
.include <bsd.own.mk>
MENUCDIR!= cd $(.CURDIR)/..; ${PRINTOBJDIR}
MENUC= ${MENUCDIR}/menuc
${MENUC}:
cd ${.CURDIR}/..; ${MAKE}
PROG= testm
SRCS= msg_defs.c menu_defs.c main.c
CFLAGS+=-g
CPPFLAGS+=-I.
LDADD+= -lcurses -lterminfo
DPADD+= ${LIBCURSES}
CLEANFILES+= menu_defs.c menu_defs.h msg_defs.c msg_defs.h
menu_defs.c menu_defs.h: menus.mc ${MENUC} ${.CURDIR}/../menu_sys.def
MENUDEF=${.CURDIR}/.. ${MENUC} ${.CURDIR}/menus.mc
msg_defs.c msg_defs.h: menus.msg
msgc ${.CURDIR}/menus.msg
.include <bsd.prog.mk>

126
usr.bin/menuc/testm/main.c Normal file
View file

@ -0,0 +1,126 @@
/* $NetBSD: main.c,v 1.6 2004/09/17 18:16:44 wrstuden Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software develooped for the NetBSD Project by
* Piermont Information Systems Inc.
* 4. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* main sysinst program. */
#include "menu_defs.h"
#include "msg_defs.h"
int main(void);
int main(void)
{
/* Menu processing */
process_menu (MENU_root, NULL);
return 0;
}
/* Dynamic menu suff! */
char ent_text[5][50] = {"name: ", "strt: ", "city: ", "opt 4", "NUM: "};
/* opt processing routines .. */
int opt_1 (struct menudesc *m, void *p);
int opt_1 (struct menudesc *m, void *p)
{
msg_clear();
msg_prompt (MSG_name, "", &ent_text[0][6], 40);
msg_clear();
return 0;
}
int opt_2 (struct menudesc *m, void *p);
int opt_2 (struct menudesc *m, void *p)
{
msg_clear();
msg_prompt (MSG_street, "", &ent_text[1][6], 40);
msg_clear();
return 0;
}
int opt_3 (struct menudesc *m, void *p);
int opt_3 (struct menudesc *m, void *p)
{
msg_clear();
msg_prompt (MSG_city, "", &ent_text[2][6], 40);
msg_clear();
return 0;
}
menu_ent mymenu [5] = {
{ ent_text[0], OPT_NOMENU, 0, opt_1},
{ ent_text[1], OPT_NOMENU, 0, opt_2},
{ ent_text[2], OPT_NOMENU, 0, opt_3},
{ ent_text[3], OPT_NOMENU, 0, NULL},
{ ent_text[4], OPT_NOMENU, 0, NULL} };
int num = 0;
void do_dynamic(void);
void dyn_disp (struct menudesc *, void *);
void dyn_disp (struct menudesc *m, void *p)
{
sprintf (&ent_text[4][5], "%d", num++);
}
void do_dynamic(void)
{
int menu_no;
num = 0;
menu_no = new_menu (" A test dynamic menu! ", mymenu, 5, 10, 10,
0, 55, MC_SCROLL, dyn_disp, NULL, NULL,
"Make sure you try at least one option before exiting.\n"
"Then look at what changes.\n", "Done now!");
if (menu_no < 0) {
endwin();
(void) fprintf (stderr, "Dynamic memu creation failure. \n");
exit (1);
}
process_menu (menu_no, NULL);
free_menu (menu_no);
}

View file

@ -0,0 +1,277 @@
/* $NetBSD: menus.mc,v 1.11 2004/09/17 18:16:31 wrstuden Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software develooped for the NetBSD Project by
* Piermont Information Systems Inc.
* 4. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
{
#include "msg_defs.h"
/* Initial code for definitions and includes and prototypes. */
void do_dynamic (void);
static int msg_init = 0;
}
default x=20, y=10;
allow dynamic menus;
error action { fprintf (stderr, "Testm: Could not initialize curses.\n");
exit(1); };
menu root, title " Main Menu of Test System", x=10;
display action {
/* Message initialization */
if (!msg_init) {
msg_window (stdscr);
msg_init = 1;
}
msg_display (MSG_welcome);
wrefresh(stdscr); };
option "Do nothing option",
action { }
;
option "Try a sub menu",
sub menu submenu
;
option "A scrollable menu",
sub menu scrollit
;
option "Another scrollable menu",
sub menu scrollit2
;
option "Big non-scrollable menu, bombs on small screens",
sub menu bigscroll
;
option "A menu with no shortcuts",
sub menu noshort
;
option "A dynamic menu ...",
action { do_dynamic (); }
;
option "Run a shell...",
action (endwin) { system ("/bin/sh"); }
;
exit action (endwin) { printf ("Thanks for playing\n"); };
help {
Main Menu Help Screen
This is help text for the main menu of the menu test system. This
text should appear verbatim when asked for by use of the ? key by
the user. This should allow scrolling, if needed. If the first
character in the help is the newline (as the case for this help),
then that newline is not included in the help text.
Now this tests lines for scrolling:
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
};
menu submenu, title " submenu test";
option "upper right", sub menu upperright;
option "lower left", sub menu lowerleft;
option "middle, no title", sub menu middle;
option "next menu", next menu nextmenu;
menu upperright, title "upper right", y=2, x=60, no exit;
option "Just Exit!", exit;
menu lowerleft, title "lower left", y=19, x=2, no exit;
option "Just Exit!", exit;
menu middle, no box;
option "Just Exit!", exit;
menu nextmenu, title " A next window! ? for comments", no exit;
option "Just Exit!:", exit;
menu noshort, title " No shortcut characters!", no shortcut;
option "first", action {};
option "second", action {};
option "third", action {};
menu scrollit, scrollable, h=4, title " Scrollable Menu";
option "option 1", action {};
option "option 2", action {};
option "option 3", action {};
option "option 4", action {};
option "option 5", action {};
option "option 6", action {};
menu bigscroll, no scrollable, title " Non-scrollable Menu";
option "option 1", action {};
option "option 2", action {};
option "option 3", action {};
option "option 4", action {};
option "option 5", action {};
option "option 6", action {};
option "option 7", action {};
option "option 8", action {};
option "option 9", action {};
option "option 10", action {};
option "option 11", action {};
option "option 12", action {};
option "option 13", action {};
option "option 14", action {};
option "option 15", action {};
option "option 16", action {};
option "option 17", action {};
option "option 18", action {};
option "option 19", action {};
option "option 20", action {};
menu scrollit2, scrollable, title " Big scrollable Menu";
option "option 1", action {};
option "option 2", action {};
option "option 3", action {};
option "option 4", action {};
option "option 5", action {};
option "option 6", action {};
option "option 7", action {};
option "option 8", action {};
option "option 9", action {};
option "option 10", action {};
option "option 11", action {};
option "option 12", action {};
option "option 13", action {};
option "option 14", action {};
option "option 15", action {};
option "option 16", action {};
option "option 17", action {};
option "option 18", action {};
option "option 19", action {};
option "option 20", action {};
option "option 21", action {};
option "option 22", action {};
option "option 23", action {};
option "option 24", action {};
option "option 25", action {};
option "option 26", action {};
option "option 27", action {};
option "option 28", action {};
option "option 29", action {};
option "option 30", action {};
option "option 31", action {};
option "option 32", action {};
option "option 33", action {};
option "option 34", action {};
option "option 35", action {};
option "option 36", action {};
option "option 37", action {};
option "option 38", action {};
option "option 39", action {};
option "option 40", action {};
option "option 41", action {};
option "option 42", action {};
option "option 43", action {};
option "option 44", action {};
option "option 45", action {};
option "option 46", action {};
option "option 47", action {};
option "option 48", action {};
option "option 49", action {};
option "option 50", action {};
option "option 51", action {};

View file

@ -0,0 +1,12 @@
/* $NetBSD: menus.msg,v 1.1 1998/07/16 07:08:26 phil Exp $ */
message welcome {
Welcome to the menuc (and msg) test program!
}
message name {name}
message street {street address}
message city {city, state zip}

107
usr.bin/menuc/util.c Normal file
View file

@ -0,0 +1,107 @@
/* $NetBSD: util.c,v 1.5 2012/03/06 16:55:18 mbalmer Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* util.c - utility routines. */
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: util.c,v 1.5 2012/03/06 16:55:18 mbalmer Exp $");
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "defs.h"
/* Error routine */
void
yyerror(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
printf("%s:%d: ", src_name, line_no);
vfprintf(stdout, fmt, args);
printf("\n");
va_end(args);
had_errors = TRUE;
}
/* Buffer routines */
static char *mc_buff = NULL;
static int mc_size = 0;
static int mc_loc = 0;
void
buff_add_ch(char ch)
{
char *t;
if (mc_loc >= mc_size-1) {
if (mc_size == 0)
mc_size = 80;
else
mc_size *= 2;
t = (char *)malloc(mc_size);
if (t == NULL) {
(void)fprintf(stderr, "%s:%d: Malloc error\n",
src_name, line_no);
exit(1);
}
if (mc_buff != NULL) {
strcpy(t, mc_buff);
free(mc_buff);
}
mc_buff = t;
}
mc_buff[mc_loc++] = ch;
mc_buff[mc_loc] = '\0';
}
/* get a copy of the string ! */
char *
buff_copy(void)
{
char *res = strdup(mc_buff);
mc_loc = 0;
mc_buff[0] = '\0';
return res;
}