]> Zhao Yanbai Git Server - minix.git/commitdiff
Importing usr.bin/msgc 22/1122/1
authorThomas Cort <tcort@minix3.org>
Wed, 6 Nov 2013 15:52:33 +0000 (10:52 -0500)
committerThomas Cort <tcort@minix3.org>
Wed, 6 Nov 2013 16:46:22 +0000 (11:46 -0500)
Minix-specific changes were needed in msg_sys.def:

 * use minix_mmap()/minix_munmap() since mmap()/munmap() aren't
   defined on Minix.

 * use MAP_PRIVATE flag since MAP_SHARED isn't defined on Minix.

Tested with usr.bin/menuc/testm.

Change-Id: I1c463e7b0623036050adb6a9079c6747e1c1e084

13 files changed:
distrib/sets/lists/minix/mi
releasetools/nbsd_ports
usr.bin/Makefile
usr.bin/msgc/Makefile [new file with mode: 0644]
usr.bin/msgc/defs.h [new file with mode: 0644]
usr.bin/msgc/msg_sys.def [new file with mode: 0644]
usr.bin/msgc/msgc.1 [new file with mode: 0644]
usr.bin/msgc/msgdb.c [new file with mode: 0644]
usr.bin/msgc/msgdb.h [new file with mode: 0644]
usr.bin/msgc/msgmain.c [new file with mode: 0644]
usr.bin/msgc/msgparse.y [new file with mode: 0644]
usr.bin/msgc/msgscan.l [new file with mode: 0644]
usr.bin/msgc/pathnames.h [new file with mode: 0644]

index 17cbcb62fe90cefd1928515979653ee2934fd24f..5e197e485b75299cb174269bc059105f381eb345 100644 (file)
 ./usr/bin/mkstr                                minix-sys
 ./usr/bin/mktemp                       minix-sys
 ./usr/bin/more                         minix-sys
+./usr/bin/msgc                         minix-sys
 ./usr/bin/mt                           minix-sys
 ./usr/bin/nbperf                       minix-sys
 ./usr/bin/newgrp                       minix-sys
 ./usr/man/man1/mktemp.1                        minix-sys
 ./usr/man/man1/more.1                  minix-sys
 ./usr/man/man1/mount.1                 minix-sys
+./usr/man/man1/msgc.1                  minix-sys
 ./usr/man/man1/mt.1                    minix-sys
 ./usr/man/man1/mv.1                    minix-sys
 ./usr/man/man1/nbperf.1                        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/msg_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
index fbe0e53493b68dbf619a86228da759f184417cfb..b2099498b947ff823cd702182087121bb09da825 100644 (file)
 2010/10/15 05:46:48,usr.bin/mkdep
 2012/10/17 12:00:00,usr.bin/mkstr
 2009/08/15 20:44:56,usr.bin/mktemp
+2012/10/17 12:00:00,usr.bin/msgc
 2012/10/17 12:00:00,usr.bin/nbperf
 2013/10/10 12:00:00,usr.bin/nice
 2013/10/13 12:00:00,usr.bin/nl
index 983e398e86a6016690fae5e9d07686432c3914cb..e468a1797bbda70ae70b77116e461e0f5715edde 100644 (file)
@@ -17,7 +17,7 @@ SUBDIR= asa \
        lock login logname lorder m4 \
        machine make man menuc mesg \
        mkdep mkstr mktemp \
-       \
+       msgc \
        nbperf newgrp nice nl nohup nvi \
        passwd paste pathchk pr \
        printenv printf pwhash \
diff --git a/usr.bin/msgc/Makefile b/usr.bin/msgc/Makefile
new file mode 100644 (file)
index 0000000..770e94b
--- /dev/null
@@ -0,0 +1,23 @@
+#      $NetBSD: Makefile,v 1.18 2009/10/29 14:37:56 christos Exp $
+
+WARNS?= 1      # XXX -Wshadow -Wcast-qual issues
+
+.include <bsd.own.mk>
+
+PROG=          msgc
+SRCS=          msgmain.c msgparse.y msgscan.l msgdb.c util.c avl.c
+.PATH:         ${NETBSDSRCDIR}/usr.bin/menuc
+CPPFLAGS+=     -I. -I${.CURDIR}
+YHEADER=
+
+.if ${MKSHARE} != "no"
+FILES=         msg_sys.def
+FILESDIR=      /usr/share/misc
+.endif
+
+.ifndef HOSTPROG
+LDADD+=                -ll
+DPADD+=                ${LIBL}
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/msgc/defs.h b/usr.bin/msgc/defs.h
new file mode 100644 (file)
index 0000000..dbbf57f
--- /dev/null
@@ -0,0 +1,91 @@
+/*     $NetBSD: defs.h,v 1.5 2012/03/06 16:26:01 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 message system. */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <stdio.h>
+#include "msgdb.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("msg_defs");
+EXTERN char *sys_name INIT("msg_sys.def");
+
+EXTERN int line_no INIT(1);
+EXTERN int had_errors INIT(FALSE);
+EXTERN int max_strlen INIT(1);
+
+EXTERN id_rec *root INIT(NULL);
+
+/* Prototypes. */
+
+/* From util.c */
+void yyerror(const char *, ...);
+void buff_add_ch(char);
+char *buff_copy(void); 
+
+/* From avl.c */
+id_rec *find_id(id_rec *, char *);
+int insert_id(id_rec **, id_rec *);
+
+/* from scan.l */
+int yylex(void);
+
+/* from parse.y */
+int yyparse(void);
+
+/* Vars not defined in main.c */
+extern FILE *yyin;
+
+/* from mdb.c */
+void define_msg(char *, char *);
+void write_msg_file(void);
diff --git a/usr.bin/msgc/msg_sys.def b/usr.bin/msgc/msg_sys.def
new file mode 100644 (file)
index 0000000..f6bb952
--- /dev/null
@@ -0,0 +1,612 @@
+/*     $NetBSD: msg_sys.def,v 1.41 2012/03/06 16:26:01 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.
+ *
+ */
+
+static WINDOW *msg_win = NULL;
+static char *cbuffer;
+static size_t cbuffersize;
+
+static int last_i_was_nl, last_i_was_space;
+static int last_o_was_punct, last_o_was_space;
+
+static void    _msg_beep(void);
+static int     _msg_vprintf(int, const char *, va_list);
+#define MSG_PROMPT_ECHO                1
+#define MSG_PROMPT_HIDE_DFLT   2
+static void    _msg_vprompt(const char *, int, const char *, char *,
+                       size_t, va_list);
+
+static char *msgmap = MAP_FAILED;
+static size_t msgmapsz;
+static unsigned int msgmapcount;
+
+/* Routines */
+
+static void
+_msg_beep(void)
+{
+
+       fprintf(stderr, "\a");
+}
+
+WINDOW *
+msg_window(WINDOW *window)
+{
+       size_t ncbuffersize;
+       char *ncbuffer;
+       WINDOW *old;
+
+       old = msg_win;
+       if (!window)
+               return old;
+       msg_win = window;
+
+       ncbuffersize = getmaxx(window) * getmaxy(window) + 1;
+       while (ncbuffersize > cbuffersize) {
+               ncbuffer = malloc(ncbuffersize);
+               if (ncbuffer == NULL) {
+                       /* we might get truncated messages... */
+                       ncbuffersize <<= 1;
+                       continue;
+               }
+               if (cbuffer != NULL)
+                       free(cbuffer);
+               cbuffer = ncbuffer;
+               cbuffersize = ncbuffersize;
+               break;
+       }
+       last_o_was_punct = 0;
+       last_o_was_space = 1;
+       return old;
+}
+
+int
+msg_file(const char *file)
+{
+       int fd;
+
+       if (msgmap != MAP_FAILED)
+#ifdef __minix
+               minix_munmap(msgmap, msgmapsz);
+#else /* ! __minix */
+               munmap(msgmap, msgmapsz);
+#endif /* ! __minix */
+       msgmap = MAP_FAILED;
+       if (!file)
+               return 0;
+       fd = open(file, O_RDONLY, 0);
+       if (fd == -1)
+               return -1;
+       msgmapsz = lseek(fd, 0, SEEK_END);
+#ifdef __minix
+       msgmap = minix_mmap(0, msgmapsz, PROT_READ, MAP_PRIVATE, fd, 0);
+#else /* ! __minix */
+       msgmap = mmap(0, msgmapsz, PROT_READ, MAP_SHARED, fd, 0);
+#endif /* ! __minix */
+       close(fd);
+       if (msgmap == MAP_FAILED)
+               return -1;
+       /* check_magic */
+       if (strcmp(msgmap, "MSGTXTS") != 0) {
+               msg_file(NULL);
+               return -1;
+       }
+       msgmapcount = atoi(msgmap + 8);
+       return 0;
+}
+
+const char *
+msg_string(msg msg_no)
+{
+       uintptr_t m = (uintptr_t)msg_no;
+
+       if (m > sizeof msg_list / sizeof msg_list[0])
+               /* guess that we were passed a text string */
+               return msg_no;
+
+       if (msgmap != MAP_FAILED && m != 0 && m <= msgmapcount) {
+               unsigned int offset = atoi(msgmap + 8 + 8 * m);
+               if (offset != 0 && offset < msgmapsz)
+                       return msgmap + offset;
+       }
+
+       return msg_list[m];
+}
+
+void
+msg_clear(void)
+{
+
+       wclear(msg_win);
+       last_o_was_punct = 0;
+       last_o_was_space = 1;
+}
+
+void
+msg_standout(void)
+{
+
+       wstandout(msg_win);
+}
+
+void
+msg_standend(void)
+{
+
+       wstandend(msg_win);
+}
+
+static int
+_msg_vprintf(int auto_fill, const char *fmt, va_list ap)
+{
+       const char *wstart, *afterw;
+       int wordlen, nspaces;
+       int ret;
+
+       ret = vsnprintf(cbuffer, cbuffersize, fmt, ap);
+
+       if (!auto_fill) {
+               waddstr(msg_win, cbuffer);
+
+               /*
+                * nothing is perfect if they flow text after a table,
+                * but this may be decent.
+                */
+               last_i_was_nl = last_i_was_space = 1;
+               last_o_was_punct = 0;
+               last_o_was_space = 1;
+               goto out;
+       }
+
+       for (wstart = afterw = cbuffer; *wstart; wstart = afterw) {
+
+               /* eat one space, or a whole word of non-spaces */
+               if (isspace((unsigned char)*afterw))
+                       afterw++;
+               else
+                       while (*afterw && !isspace((unsigned char)*afterw))
+                               afterw++;
+
+               /* this is an nl: special formatting necessary */
+               if (*wstart == '\n') {
+                       if (last_i_was_nl || last_i_was_space) {
+
+                               if (getcurx(msg_win) != 0)
+                                       waddch(msg_win, '\n');
+                               if (last_i_was_nl) {
+                                       /* last was an nl: paragraph break */
+                                       waddch(msg_win, '\n');
+                               } else {
+                                       /* last was space: line break */
+                               }
+                               last_o_was_punct = 0;
+                               last_o_was_space = 1;
+                       } else {
+                               /* last_o_was_punct unchanged */
+                               /* last_o_was_space unchanged */
+                       }
+                       last_i_was_space = 1;
+                       last_i_was_nl = 1;
+                       continue;
+               }
+
+               /* this is a tab: special formatting necessary. */
+               if (*wstart == '\t') {
+                       if (last_i_was_nl) {
+                               /* last was an nl: list indent */
+                               if (getcurx(msg_win) != 0)
+                                       waddch(msg_win, '\n');
+                       } else {
+                               /* last was not an nl: columns */
+                       }
+                       waddch(msg_win, '\t');
+                       last_i_was_nl = 0;
+                       last_i_was_space = 1;
+                       last_o_was_punct = 0;
+                       last_o_was_space = 1;
+                       continue;
+               }
+
+               /* this is a space: ignore it but set flags */
+               last_i_was_nl = 0;      /* all newlines handled above */
+               last_i_was_space = isspace((unsigned char)*wstart);
+               if (last_i_was_space)
+                       continue;
+
+               /*
+                * we have a real "word," i.e. a sequence of non-space
+                * characters.  wstart is now the start of the word,
+                * afterw is the next character after the end.
+                */
+               wordlen = afterw - wstart;
+               nspaces = last_o_was_space ? 0 : (last_o_was_punct ? 2 : 1);
+               if ((getcurx(msg_win) + nspaces + wordlen) >=
+                     getmaxx(msg_win) &&
+                   wordlen < (getmaxx(msg_win) / 3)) {
+                       /* wrap the line */
+                       waddch(msg_win, '\n');
+                       nspaces = 0;
+               }
+
+               /* output the word, preceded by spaces if necessary */
+               while (nspaces-- > 0)
+                       waddch(msg_win, ' ');
+               waddbytes(msg_win, wstart, wordlen);
+
+               /* set up the 'last' state for the next time around */
+               switch (afterw[-1]) {
+               case '.':
+               case '?':
+               case '!':
+                       last_o_was_punct = 1;
+                       break;
+               default:
+                       last_o_was_punct = 0;
+                       break;
+               }
+               last_o_was_space = 0;
+
+               /* ... and do it all again! */
+       }
+
+       /* String ended with a newline.  They really want a line break. */
+       if (last_i_was_nl) {
+               if (getcurx(msg_win) != 0)
+                       waddch(msg_win, '\n');
+               last_o_was_punct = 0;
+               last_o_was_space = 1;
+       }
+
+out:
+       wrefresh(msg_win);
+       return ret;
+}
+
+void
+msg_display(msg msg_no, ...)
+{
+       va_list ap;
+
+       msg_clear();
+
+       va_start(ap, msg_no);
+       (void)_msg_vprintf(1, msg_string(msg_no), ap);
+       va_end(ap);
+}
+
+void
+msg_display_add(msg msg_no, ...)
+{
+       va_list ap;
+
+       va_start(ap, msg_no);
+       (void)_msg_vprintf(1, msg_string(msg_no), ap);
+       va_end(ap);
+}
+
+void
+msg_printf(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       (void)_msg_vprintf(1, fmt, ap);
+       va_end(ap);
+}
+
+static void
+_msg_vprompt(const char *fmt, int flags, const char *def, char *val,
+    size_t val_buf_len, va_list ap)
+{
+       int ch;
+       int len, pos, npos, off;
+       int first;
+       int txt_y, txt_x;
+       char *ibuf;
+       int maxx;
+
+       if (val == NULL || val_buf_len == 0) {
+               /* No answer wanted */
+               val = NULL;
+               val_buf_len = 1;
+       }
+
+       ibuf = malloc(val_buf_len);
+
+       keypad(msg_win, TRUE);
+       _msg_vprintf(0, fmt, ap);
+       ibuf[0] = 0;
+       if (def != NULL && *def) {
+               if (flags & MSG_PROMPT_HIDE_DFLT)
+                       strlcpy(ibuf, def, val_buf_len);
+               else {
+                       waddstr(msg_win, " [");
+                       waddstr(msg_win, def);
+                       waddstr(msg_win, "]");
+               }
+       }
+       waddstr(msg_win, ": ");
+       len = strlen(ibuf);
+       pos = len;
+       getyx(msg_win, txt_y, txt_x);
+       maxx = getmaxx(msg_win) - txt_x - 1;
+       off = 0;
+
+       for (first = 1; ; first = 0) {
+
+               if (flags & MSG_PROMPT_ECHO) {
+                       /* shift text right as we near the buffer start */
+                       if (pos - off < 4)
+                               off = pos - 4;
+                       /* keep offset to a minimum if we are at the end */
+                       if (pos == len)
+                               off = pos - maxx;
+                       if (off < 0 || len <= maxx)
+                               off = 0;
+                       /* shift text left as we near the buffer end */
+                       npos = pos + 4;
+                       if (npos > len)
+                               npos = len;
+                       if (npos - off > maxx)
+                               off = npos - maxx;
+                       /* calc. length to display */
+                       npos = len - off;
+                       if (npos > maxx)
+                               npos = maxx;
+                       mvwaddnstr(msg_win, txt_y, txt_x, ibuf + off, npos);
+                       wclrtoeol(msg_win);
+                       if (off != 0)
+                               mvwaddstr(msg_win, txt_y, txt_x, "+");
+                       wmove(msg_win, txt_y, txt_x + pos - off);
+                       wrefresh(msg_win);
+               }
+
+               ch = wgetch(msg_win);
+               if (ch == '\n')
+                       break;
+
+               switch (ch) {
+               case KEY_BACKSPACE:
+               case 'h' & 0x1f: case 0x7f:  /* bs or del - delete left */
+                       if (first) {
+                               /* delete all of default string */
+                               len = pos = 0;
+                               break;
+                       }
+                       if (pos > 0) {
+                               memmove(ibuf + pos - 1, ibuf + pos, len - pos);
+                               len--;
+                               pos--;
+                       } else
+                               _msg_beep();
+                       break;
+               case 'u' & 0x1f:        /* ^U; line kill */
+                       /* kill line */
+                       len = pos = 0;
+                       break;
+               case 'w' & 0x1f:        /* ^W; word kill */
+                       /*
+                        * word kill kills the spaces and the 'word'
+                        * (non-spaces) last typed.  the spaces before
+                        * the 'word' aren't killed.
+                        */
+                       npos = pos;
+                       while (npos > 0 && isspace((unsigned char)ibuf[npos - 1]))
+                               npos--;
+                       while (npos > 0 && !isspace((unsigned char)ibuf[npos - 1]))
+                               npos--;
+                       memmove(ibuf + npos, ibuf + pos, len - pos);
+                       len -= pos - npos;
+                       pos = npos;
+                       break;
+               case KEY_LEFT:
+                       if (pos > 0)
+                               pos--;
+                       break;
+               case KEY_RIGHT:
+                       if (len == 0 && pos == 0 && def != NULL) {
+                               /* restore default! */
+                               strlcpy(ibuf, def, val_buf_len);
+                               len = pos = strlen(ibuf);
+                               break;
+                       }
+                       if (pos < len)
+                               pos++;
+                       break;
+               default:
+                       if (len < (int)(val_buf_len - 1) && isprint(ch)) {
+                               memmove(ibuf + pos + 1, ibuf + pos, len - pos);
+                               ibuf[pos++] = ch;
+                               len++;
+                       } else
+                               _msg_beep();
+                       break;
+               }
+       }
+
+       if (flags & MSG_PROMPT_ECHO) {
+               mvwaddch(msg_win, txt_y, txt_x + len - off, '\n');
+               last_o_was_punct = 0;
+               last_o_was_space = 1;
+       }
+
+       if (val != NULL) {
+               /* copy the appropriate string to the output */
+               if (len != 0 || flags & MSG_PROMPT_HIDE_DFLT) {
+                       ibuf[len] = '\0';
+                       strlcpy(val, ibuf, val_buf_len);
+               } else if (def != NULL && val != def) {
+                       strlcpy(val, def, val_buf_len);
+               }
+       }
+       free(ibuf);
+}
+
+void
+msg_prompt(msg msg_no, const char *def, char *val, size_t val_buf_len, ...)
+{
+       va_list ap;
+
+       msg_clear();
+
+       va_start(ap, val_buf_len);
+       _msg_vprompt(msg_string(msg_no), MSG_PROMPT_ECHO,
+               def, val, val_buf_len, ap);
+       va_end(ap);
+}
+
+void
+msg_prompt_win(msg msg_no, int x, int y, int w, int h,
+       const char *def, char *val, size_t val_buf_len, ...)
+{
+       va_list ap;
+       WINDOW *win;
+       WINDOW *svmsg = NULL, *sv_win = NULL; /* XXX -Wuninitialized [many] */
+       int maxx, maxy;
+       int msg_flags = MSG_PROMPT_ECHO | MSG_PROMPT_HIDE_DFLT;
+
+       maxx = getmaxx(msg_win);
+       maxy = getmaxy(msg_win);
+       if (w == 0) {
+               va_start(ap, val_buf_len);
+               w = vsnprintf(NULL, 0, msg_string(msg_no), ap);
+               va_end(ap);
+               if (def != NULL && *def != 0 && w + (int)val_buf_len * 2 < maxx) {
+                       w += 2 + strlen(def) + 1;
+                       msg_flags &= ~MSG_PROMPT_HIDE_DFLT;
+               }
+               w += 1 + 2 + val_buf_len + 1;
+               if (w > maxx) {
+                       if (!(msg_flags & MSG_PROMPT_HIDE_DFLT)) {
+                               w -= 2 + strlen(def) + 1;
+                               msg_flags |= MSG_PROMPT_HIDE_DFLT;
+                       }
+                       w = maxx;
+               }
+       }
+
+       if (x == -1)
+               x = (maxx - w) / 2 + 1;
+       if (h < 3)
+               h = 3;
+       if (y < 3)
+               y = (maxy - h) / 2;
+       if (y + h > maxy)
+               y = maxy - h;
+
+       win = subwin(msg_win, h, w, y, x);
+       if (win == NULL)
+               wprintw(msg_win, "msg_prompt_win: "
+                       "newwin(%d, %d, %d, %d) failed\n",
+                       h, w, y, x);
+       else {
+               /*
+                * Save screen contents from under our window
+                * Due to a mis-feature of NetBSD curses, curscr contains
+                * the data processed by doupdate() not that by wnoutrefresh().
+                * We must call doupdate() here to ensure we save the correct
+                * data.  See PR 26660
+                */
+               doupdate();
+               sv_win = dupwin(win);
+               if (sv_win)
+                       overwrite(curscr, sv_win);
+               wbkgd(win, getbkgd(msg_win));
+               wattrset(win, getattrs(msg_win));
+               box(win, 0, 0);
+               wrefresh(win);
+
+               /* Change message window to be our little box */
+               svmsg = msg_window(subwin(msg_win, h - 2, w - 2, y + 1, x + 1));
+               wbkgd(msg_win, getbkgd(win));
+               wattrset(msg_win, getattrs(win));
+
+               msg_clear();
+       }
+
+       va_start(ap, val_buf_len);
+       _msg_vprompt(msg_string(msg_no), msg_flags, def, val, val_buf_len, ap);
+       va_end(ap);
+
+       if (win != NULL) {
+               wclear(win);
+               if (sv_win) {
+                       /* Restore original screen contents */
+                       overwrite(sv_win, win);
+                       delwin(sv_win);
+               }
+               wnoutrefresh(win);
+               /* Restore normal message window */
+               delwin(msg_window(svmsg));
+               delwin(win);
+       }
+}
+
+void
+msg_prompt_add(msg msg_no, const char *def, char *val, size_t val_buf_len, ...)
+{
+       va_list ap;
+
+       va_start(ap, val_buf_len);
+       _msg_vprompt(msg_string(msg_no), MSG_PROMPT_ECHO, def, val, val_buf_len, ap);
+       va_end(ap);
+}
+
+void
+msg_prompt_noecho(msg msg_no, const char *def, char *val, size_t val_buf_len, ...)
+{
+       va_list ap;
+
+       msg_clear();
+
+       va_start(ap, val_buf_len);
+       _msg_vprompt(msg_string(msg_no), 0, def, val, val_buf_len, ap);
+       va_end(ap);
+}
+
+void
+msg_table_add(msg msg_no, ...)
+{
+       va_list ap;
+
+       va_start(ap, msg_no);
+       (void)_msg_vprintf(0, msg_string(msg_no), ap);
+       va_end(ap);
+}
+
+int
+msg_row(void)
+{
+
+       return getcury(msg_win) + getbegy(msg_win);
+}
diff --git a/usr.bin/msgc/msgc.1 b/usr.bin/msgc/msgc.1
new file mode 100644 (file)
index 0000000..9e47cdb
--- /dev/null
@@ -0,0 +1,211 @@
+.\"    $NetBSD: msgc.1,v 1.26 2012/03/06 16:26:01 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 March 3, 2012
+.Dt MSGC 1
+.Os
+.Sh NAME
+.Nm msgc ,
+.Nm msg_window ,
+.Nm msg_string ,
+.Nm msg_clear ,
+.Nm msg_standout ,
+.Nm msg_standend ,
+.Nm msg_display ,
+.Nm msg_display_add ,
+.Nm msg_printf ,
+.Nm msg_prompt ,
+.Nm msg_prompt_add ,
+.Nm msg_prompt_win ,
+.Nm msg_prompt_noecho ,
+.Nm msg_row ,
+.Nm msg_table_add
+.Nd simple message list compiler
+.Sh SYNOPSIS
+msgc
+.Op Fl o Ar name
+.Ar file
+.Pp
+.Fd #include \&"msg_defs.h"
+.Ft void
+.Fn msg_window "WINDOW *window"
+.Ft const char *
+.Fn msg_string "msg msg_no"
+.Ft void
+.Fn msg_clear "void"
+.Ft void
+.Fn msg_standout "void"
+.Ft void
+.Fn msg_standend "void"
+.Ft void
+.Fn msg_display "msg msg_no" ...
+.Ft void
+.Fn msg_display_add "msg msg_no" ...
+.Ft void
+.Fn msg_printf "fmt" ...
+.Ft void
+.Fn msg_prompt  "msg msg_no" "const char *def" "char *val" "int max_chars" ...
+.Ft void
+.Fn msg_prompt_add  "msg msg_no" "const char *def" "char *val" "int max_chars" ...
+.Ft void
+.Fn msg_prompt_win  "msg msg_no" "WINDOW *win" "const char *def" "char *val" "int max_chars" ...
+.Ft void
+.Fn msg_prompt_noecho  "msg msg_no" "const char *def" "char *val" "int max_chars" ...
+.Ft int
+.Fn msg_row "void"
+.Ft void
+.Fn msg_table_add "msg msg_no" ...
+.Sh DESCRIPTION
+This implements a curses based message display system.
+A source file that lists messages with associated names is given to
+.Nm
+and produces both a .c and a .h file that implement the menu system.
+The standard root name of the files is
+.Pa msg_defs .
+The
+.Fl o Ar name
+can be used to specify a different root name.
+.Sh ENVIRONMENT
+.Bl -tag -width MSGDEF
+.It Ev MSGDEF
+Can be set to point to a different set of
+definition files for
+.Nm msgc .
+The current location defaults to
+.Pa /usr/share/misc .
+.El
+.Sh FILES
+.Bl -item
+.It
+.Pa /usr/share/misc/msg_sys.def
+.El
+.Sh SOURCE DESCRIPTION
+The format is very simple.
+Each message is started with the word
+.Sq message
+followed by the name of the message.
+The body of the message is next and is started by a { and closed by a }.
+The braces are not part of the message.
+Everything, including newlines between the braces are part of the message.
+.Sh MESSAGE FUNCTIONS
+The defined messages are used through calls routines that manipulate
+the messages.
+You first need to set the
+.Xr curses 3
+environment up and then tell the message system which window to use
+for displaying message by calling the function
+.Fn msg_window .
+.Pp
+All variable argument lists in the functions are used as
+are arguments to
+.Xr sprintf 3 .
+The messages may have
+.Xr sprintf 3
+conversions in them and the corresponding parameters should match.
+Messages are identified by name using the notation
+.Sq MSG_name
+where
+.Dq name
+is the name in the message source file.
+(The definitions are accessed by including the generated .h file into a
+source file wanting to use the message routines.)
+.Pp
+The function
+.Fn msg_string
+just returns a pointer to the actual message string.
+The functions
+.Fn msg_clear ,
+.Fn msg_standout
+and
+.Fn msg_standend
+respectively clear the message window, set standout mode and clear standout
+mode.
+.Pp
+The functions
+.Fn msg_display
+and
+.Fn msg_display_add
+cause a defined message to be displayed in the message window and does
+the requested conversions before printing.
+The difference is that
+.Fn msg_display
+clears the window before displaying the message.
+These functions fill paragraphs for readability.
+The
+.Fn msg_table_add
+function behaves like
+.Fn msg_display_add
+but does not fill text.
+.Pp
+The function
+.Fn msg_printf
+allows to display a raw message without going through the message catalog.
+.Pp
+The remaining functions deal with a prompt facility.
+A prompt message is either taken from the message directory or from a
+given string.
+The message is processed with
+.Xr sprintf 3
+and then displayed.
+If the parameter
+.Ar def
+is
+.No non- Ns Dv NULL
+and not a string of zero length, a default value is printed
+in brackets.
+The user is allowed to type in a response.
+If the user types just the newline character, the default is returned
+in the value.
+The parameter
+.Ar max_chars
+is the length of the parameter
+.Ar val ,
+where the results are stored.
+The parameters
+.Ar def
+and
+.Ar val
+may point to the same character array.
+If the default is chosen, the character array is not changed.
+The functions
+.Fn msg_echo
+and
+.Fn msg_noecho
+control whether the prompt routine echo or don't echo the input that
+is typed by the user.
+.Pp
+.Fn msg_prompt_win
+uses the specified curses window instead of the default one.
+.Pp
+.Fn msg_row
+return the current row - i.e.: getcury(msg_win) + getbegy(msg_win).
+.Sh AUTHORS
+Philip A. Nelson for Piermont Information Systems Inc.
diff --git a/usr.bin/msgc/msgdb.c b/usr.bin/msgc/msgdb.c
new file mode 100644 (file)
index 0000000..024145e
--- /dev/null
@@ -0,0 +1,213 @@
+/*     $NetBSD: msgdb.c,v 1.23 2012/03/06 16:26:01 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 - message database manipulation */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: msgdb.c,v 1.23 2012/03/06 16:26:01 mbalmer Exp $");
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "defs.h"
+#include "pathnames.h"
+
+static struct id_rec *head = NULL, *tail = NULL;
+static int msg_no = 1;
+
+void define_msg (char *name, char *value)
+{
+       struct id_rec *tmp = (struct id_rec *)malloc(sizeof(struct id_rec));
+
+       if (find_id (root, name))
+               yyerror ("%s is defined twice", name);
+
+       tmp->id     = name;
+       tmp->msg    = value;
+       tmp->msg_no = msg_no++;
+       tmp->next   = NULL;
+       if (tail == NULL)
+               head = tail = tmp;
+       else {
+               tail->next = tmp;
+               tail = tmp;
+       }
+
+       insert_id (&root, tmp);
+}
+
+static void write_str (FILE *f, char *str)
+{
+       (void)fprintf (f, "\"");
+       while (*str) {
+               if (*str == '\n')
+                       (void) fprintf (f, "\\n\"\n\""), str++;
+               else if (*str == '"')
+                       (void) fprintf (f, "\\\""), str++;
+               else
+                       (void) fprintf (f, "%c", *str++);
+       }
+       (void)fprintf (f, "\",");
+}
+
+/* Write out the msg files. */
+void
+write_msg_file ()
+{
+       FILE *out_file;
+       FILE *sys_file;
+       char hname[1024];
+       char cname[1024];
+       char sname[1024];
+       char *sys_prefix;
+
+       int nlen;
+       int ch;
+
+       struct id_rec *t;
+
+       /* 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 msg_sys file first. */
+       sys_prefix = getenv ("MSGDEF");
+       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",
+               "/* msg system definitions. */\n"
+               "\n"
+               "#ifndef MSG_DEFS_H\n"
+               "#define MSG_DEFS_H\n"
+               "#include <stdio.h>\n"
+               "#include <stdlib.h>\n"
+               "#include <unistd.h>\n"
+               "#include <fcntl.h>\n"
+               "#include <string.h>\n"
+               "#include <ctype.h>\n"
+               "#include <stdarg.h>\n"
+               "#include <stdint.h>\n"
+               "#include <curses.h>\n"
+               "#include <sys/mman.h>\n"
+               "\n"
+               "typedef const char *msg;\n"
+               "\n"
+               "/* Prototypes */\n"
+               "WINDOW *msg_window(WINDOW *window);\n"
+               "const char *msg_string(msg msg_no);\n"
+               "int msg_file(const char *);\n"
+               "void msg_clear(void);\n"
+               "void msg_standout(void);\n"
+               "void msg_standend(void);\n"
+               "void msg_display(msg msg_no,...);\n"
+               "void msg_display_add(msg msg_no,...);\n"
+               "void msg_printf(const char *fmt, ...) __printflike(1, 2);\n"
+               "void msg_prompt (msg msg_no, const char *def,"
+                       " char *val, size_t max_chars, ...);\n"
+               "void msg_prompt_add (msg msg_no, const char *def,"
+                       " char *val, size_t max_chars, ...);\n"
+               "void msg_prompt_noecho (msg msg_no, const char *def,"
+                       " char *val, size_t max_chars, ...);\n"
+               "void msg_prompt_win (msg, int, int, int, int,"
+                       " const char *, char *, size_t, ...);\n"
+               "void msg_table_add(msg msg_no,...);\n"
+               "int msg_row(void);\n"
+               "\n"
+               "/* Message names */\n"
+             );
+       (void) fprintf (out_file, "#define MSG_NONE\tNULL\n");
+       for (t=head; t != NULL; t = t->next) {
+               (void) fprintf (out_file, "#define MSG_%s\t((msg)(long)%d)\n",
+                               t->id, t->msg_no);
+       }
+       (void) fprintf (out_file, "\n#endif\n");
+
+       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);
+       }
+
+       /* hfile include ... */
+       (void)fprintf (out_file, "#include \"%s\"\n", hname);
+
+       /* msg_list */
+       (void)fprintf (out_file, "const char *msg_list[] = {\nNULL,\n");
+       for (t=head ; t != NULL; t = t->next)
+               write_str (out_file, t->msg);
+       (void)fprintf (out_file, "NULL};\n");
+
+       /* sys file out! */
+       while ((ch = fgetc(sys_file)) != EOF)
+               fputc(ch, out_file);
+
+       fclose (out_file);
+       fclose (sys_file);
+}
diff --git a/usr.bin/msgc/msgdb.h b/usr.bin/msgc/msgdb.h
new file mode 100644 (file)
index 0000000..f983ad2
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $NetBSD: msgdb.h,v 1.3 2012/03/06 16:26:01 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 msg database. */
+
+#ifndef MSGDB_H
+#define MSGDB_H
+
+/* Definition for a list of messages. */
+
+typedef struct id_rec {
+       char  *id;
+
+       /* For the balanced tree. */
+       short balance;
+       struct id_rec *left, *right;
+
+       /* For the list of messages. */
+       struct id_rec *next;
+       char *msg;
+       int msg_no;
+} id_rec;
+
+#endif
diff --git a/usr.bin/msgc/msgmain.c b/usr.bin/msgc/msgmain.c
new file mode 100644 (file)
index 0000000..83daf87
--- /dev/null
@@ -0,0 +1,105 @@
+/*     $NetBSD: msgmain.c,v 1.9 2012/03/06 16:26:01 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 */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: msgmain.c,v 1.9 2012/03/06 16:26:01 mbalmer Exp $");
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define MAIN
+#include "defs.h"
+
+/* Local prototypes */
+void usage (char *);
+
+int
+main (int argc, char **argv)
+{
+       int ch;
+
+       prog_name = argv[0];
+
+       /* Process the arguments. */
+       while ( (ch = getopt (argc, argv, "o:")) != -1 ) {
+               switch (ch) {
+               case 'o': /* output file name */
+                       out_name = optarg;
+                       break;
+               default:
+                       usage (prog_name);
+               }
+       }
+
+       if (optind != argc-1)
+               usage (prog_name);
+
+       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);
+       }
+
+       /* Do the parse */
+       (void) yyparse ();
+
+       if (had_errors)
+               return 1;
+
+       write_msg_file();
+
+       return 0;
+}
+
+
+void
+usage (char *prog)
+{
+       (void) fprintf (stderr, "%s [-o name] file\n", prog);
+       exit (1);
+}
diff --git a/usr.bin/msgc/msgparse.y b/usr.bin/msgc/msgparse.y
new file mode 100644 (file)
index 0000000..722fdc5
--- /dev/null
@@ -0,0 +1,66 @@
+/*     $NetBSD: msgparse.y,v 1.5 2012/03/06 16:26:01 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 <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: msgparse.y,v 1.5 2012/03/06 16:26:01 mbalmer Exp $");
+#endif
+
+
+#include "defs.h"
+
+%}
+
+%union {
+       char *s_value;
+}
+
+
+%token MESSAGE
+%token <s_value> NAME VALUE
+
+%start list
+
+%%
+
+list   : /* empty */
+       | list msg
+       ;
+
+
+msg    : MESSAGE NAME VALUE
+               { define_msg ($2, $3); }
diff --git a/usr.bin/msgc/msgscan.l b/usr.bin/msgc/msgscan.l
new file mode 100644 (file)
index 0000000..a9aa31d
--- /dev/null
@@ -0,0 +1,131 @@
+/*     $NetBSD: msgscan.l,v 1.7 2012/03/06 16:26:01 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 message compiler. */
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: msgscan.l,v 1.7 2012/03/06 16:26:01 mbalmer Exp $");
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "msgparse.h"
+
+static int level;      /* For nested comments. */
+
+%}
+
+%x COMMENT
+%x BRACE
+
+%option noinput
+
+%%
+
+[ \t]+ { /* ignore spaces and tabs */ }
+
+[\n]   { line_no++; }
+
+";"    { return (int)yytext[0]; }
+
+message { return MESSAGE; }
+
+[a-zA-Z][a-zA-Z0-9_]* {
+         yylval.s_value = strdup(yytext);
+         return(NAME);
+       }
+
+"/*"  {        level = 1; BEGIN COMMENT;  }
+
+<COMMENT>"/*" { level++; }
+
+<COMMENT>"*/" { if (level-- == 1) BEGIN 0; }
+
+<COMMENT>"\n" { line_no++; }
+
+<COMMENT><<EOF>> { yyerror ("EOF inside a comment."); exit (1); }
+
+<COMMENT>.  {/* eat character */}
+
+"{"    { level = 1; BEGIN BRACE; }
+
+<BRACE>"\\{"   { buff_add_ch('{'); }
+
+<BRACE>"\\}"   { buff_add_ch('}'); }
+
+<BRACE>"{"     { buff_add_ch(yytext[0]); level++; }
+
+<BRACE>"}"     { if (level-- == 1)  {
+                       BEGIN 0;
+                       yylval.s_value = buff_copy();
+                       return VALUE;
+                 } 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
diff --git a/usr.bin/msgc/pathnames.h b/usr.bin/msgc/pathnames.h
new file mode 100644 (file)
index 0000000..6316d78
--- /dev/null
@@ -0,0 +1,5 @@
+/*     $NetBSD: pathnames.h,v 1.1 2001/10/15 22:11:12 bjh21 Exp $      */
+
+#ifndef _PATH_DEFSYSPREFIX
+#define _PATH_DEFSYSPREFIX     "/usr/share/misc"
+#endif