summaryrefslogtreecommitdiff
path: root/vgrind
diff options
context:
space:
mode:
Diffstat (limited to 'vgrind')
-rw-r--r--vgrind/Makefile.mk34
-rw-r--r--vgrind/regexp.c569
-rw-r--r--vgrind/retest.c83
-rw-r--r--vgrind/version.c15
-rw-r--r--vgrind/vfontedpr.c901
-rw-r--r--vgrind/vgrind.1228
-rwxr-xr-xvgrind/vgrind.sh259
-rw-r--r--vgrind/vgrindefs.c314
-rw-r--r--vgrind/vgrindefs.src170
9 files changed, 2573 insertions, 0 deletions
diff --git a/vgrind/Makefile.mk b/vgrind/Makefile.mk
new file mode 100644
index 0000000000000..d167fccda151a
--- /dev/null
+++ b/vgrind/Makefile.mk
@@ -0,0 +1,34 @@
+OBJ = regexp.o vfontedpr.o vgrindefs.o version.o
+
+FLAGS = $(EUC) -DLIBDIR='"$(LIBDIR)"' $(DEFINES) -I../include
+
+.c.o:
+ $(CC) $(CFLAGS) $(WARN) $(FLAGS) $(CPPFLAGS) -c $<
+
+all: vgrind vfontedpr
+
+vfontedpr: $(OBJ)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(LIBS) -o vfontedpr
+
+vgrind: vgrind.sh
+ rm -f $@
+ echo "#!$(SHELL)" >>$@
+ echo "_TROFF=$(BINDIR)/troff" >>$@
+ echo "_VFONTEDPR=$(LIBDIR)/vfontedpr" >>$@
+ echo "_TMAC_VGRIND=$(MACDIR)/vgrind" >>$@
+ echo "_DPOST=$(BINDIR)/dpost" >>$@
+ cat vgrind.sh >>$@
+ chmod 755 $@
+
+install:
+ $(INSTALL) -c vgrind $(ROOT)$(BINDIR)/vgrind
+ test -d $(ROOT)$(LIBDIR) || mkdir -p $(ROOT)$(LIBDIR)
+ $(INSTALL) -c vfontedpr $(ROOT)$(LIBDIR)/vfontedpr
+ $(STRIP) $(ROOT)$(LIBDIR)/vfontedpr
+ $(INSTALL) -c -m 644 vgrindefs.src $(ROOT)$(LIBDIR)/vgrindefs
+ $(INSTALL) -c -m 644 vgrind.1 $(ROOT)$(MANDIR)/man1/vgrind.1
+
+clean:
+ rm -f $(OBJ) vfontedpr vgrind retest retest.o core log *~
+
+mrproper: clean
diff --git a/vgrind/regexp.c b/vgrind/regexp.c
new file mode 100644
index 0000000000000..185536b5ceba4
--- /dev/null
+++ b/vgrind/regexp.c
@@ -0,0 +1,569 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* from OpenSolaris "regexp.c 1.11 92/07/21 SMI" */
+
+/*
+ * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
+ *
+ * Sccsid @(#)regexp.c 1.3 (gritter) 10/22/05
+ */
+ /* from UCB 5.1 (Berkeley) 6/5/85 */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+typedef int boolean;
+#define TRUE 1
+#define FALSE 0
+#define NIL 0
+
+extern boolean l_onecase; /* true if upper and lower equivalent */
+extern char *l_idchars; /* set of characters legal in identifiers
+ in addition to letters and digits */
+
+static void expconv(void);
+
+#define isidchr(c) \
+ (isalnum(c) || ((c) != NIL && strchr(l_idchars, (c)) != NIL))
+#define makelower(c) (isupper((int)(c)) ? tolower((int)(c)) : (c))
+
+/* STRNCMP - like strncmp except that we convert the
+ * first string to lower case before comparing
+ * if l_onecase is set.
+ */
+
+int
+STRNCMP(register char *s1, register char *s2, register int len)
+{
+ if (l_onecase) {
+ do
+ if (*s2 - makelower(*s1))
+ return (*s2 - makelower(*s1));
+ else {
+ s2++;
+ s1++;
+ }
+ while (--len);
+ } else {
+ do
+ if (*s2 - *s1)
+ return (*s2 - *s1);
+ else {
+ s2++;
+ s1++;
+ }
+ while (--len);
+ }
+ return(0);
+}
+
+/* The following routine converts an irregular expression to
+ * internal format.
+ *
+ * Either meta symbols (\a \d or \p) or character strings or
+ * operations ( alternation or parenthesizing ) can be
+ * specified. Each starts with a descriptor byte. The descriptor
+ * byte has STR set for strings, META set for meta symbols
+ * and OPER set for operations.
+ * The descriptor byte can also have the OPT bit set if the object
+ * defined is optional. Also ALT can be set to indicate an alternation.
+ *
+ * For metasymbols the byte following the descriptor byte identities
+ * the meta symbol (containing an ascii 'a', 'd', 'p', '|', or '('). For
+ * strings the byte after the descriptor is a character count for
+ * the string:
+ *
+ * meta symbols := descriptor
+ * symbol
+ *
+ * strings := descriptor
+ * character count
+ * the string
+ *
+ * operations := descriptor
+ * symbol
+ * character count
+ */
+
+/*
+ * handy macros for accessing parts of match blocks
+ */
+#define MSYM(A) (*(A+1)) /* symbol in a meta symbol block */
+#define MNEXT(A) (A+2) /* character following a metasymbol block */
+
+#define OSYM(A) (*(A+1)) /* symbol in an operation block */
+#define OCNT(A) (*(A+2)) /* character count */
+#define ONEXT(A) (A+3) /* next character after the operation */
+#define OPTR(A) (A+*(A+2)) /* place pointed to by the operator */
+
+#define SCNT(A) (*(A+1)) /* byte count of a string */
+#define SSTR(A) (A+2) /* address of the string */
+#define SNEXT(A) (A+2+*(A+1)) /* character following the string */
+
+/*
+ * bit flags in the descriptor
+ */
+#define OPT 1
+#define STR 2
+#define META 4
+#define ALT 8
+#define OPER 16
+
+static char *ure; /* pointer current position in unconverted exp */
+static char *ccre; /* pointer to current position in converted exp*/
+
+char *
+convexp(
+ char *re /* unconverted irregular expression */
+)
+{
+ register char *cre; /* pointer to converted regular expression */
+
+ /* allocate room for the converted expression */
+ if (re == NIL)
+ return (NIL);
+ if (*re == '\0')
+ return (NIL);
+ cre = malloc (4 * strlen(re) + 3);
+ ccre = cre;
+ ure = re;
+
+ /* start the conversion with a \a */
+ *cre = META | OPT;
+ MSYM(cre) = 'a';
+ ccre = MNEXT(cre);
+
+ /* start the conversion (its recursive) */
+ expconv ();
+ *ccre = 0;
+ return (cre);
+}
+
+static void
+expconv(void)
+{
+ register char *cs; /* pointer to current symbol in converted exp */
+ register char c; /* character being processed */
+ register char *acs; /* pinter to last alternate */
+ register int temp;
+
+ /* let the conversion begin */
+ acs = NIL;
+ cs = NIL;
+ while (*ure != NIL) {
+ switch (c = *ure++) {
+
+ case '\\':
+ switch (c = *ure++) {
+
+ /* escaped characters are just characters */
+ default:
+ if (cs == NIL || (*cs & STR) == 0) {
+ cs = ccre;
+ *cs = STR;
+ SCNT(cs) = 1;
+ ccre += 2;
+ } else
+ SCNT(cs)++;
+ *ccre++ = c;
+ break;
+
+ /* normal(?) metacharacters */
+ case 'a':
+ case 'd':
+ case 'e':
+ case 'p':
+ if (acs != NIL && acs != cs) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NIL;
+ }
+ cs = ccre;
+ *cs = META;
+ MSYM(cs) = c;
+ ccre = MNEXT(cs);
+ break;
+ }
+ break;
+
+ /* just put the symbol in */
+ case '^':
+ case '$':
+ if (acs != NIL && acs != cs) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NIL;
+ }
+ cs = ccre;
+ *cs = META;
+ MSYM(cs) = c;
+ ccre = MNEXT(cs);
+ break;
+
+ /* mark the last match sequence as optional */
+ case '?':
+ if (cs)
+ *cs = *cs | OPT;
+ break;
+
+ /* recurse and define a subexpression */
+ case '(':
+ if (acs != NIL && acs != cs) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NIL;
+ }
+ cs = ccre;
+ *cs = OPER;
+ OSYM(cs) = '(';
+ ccre = ONEXT(cs);
+ expconv ();
+ OCNT(cs) = ccre - cs; /* offset to next symbol */
+ break;
+
+ /* return from a recursion */
+ case ')':
+ if (acs != NIL) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NIL;
+ }
+ cs = ccre;
+ *cs = META;
+ MSYM(cs) = c;
+ ccre = MNEXT(cs);
+ return;
+
+ /* mark the last match sequence as having an alternate */
+ /* the third byte will contain an offset to jump over the */
+ /* alternate match in case the first did not fail */
+ case '|':
+ if (acs != NIL && acs != cs)
+ OCNT(ccre) = ccre - acs; /* make a back pointer */
+ else
+ OCNT(ccre) = 0;
+ *cs |= ALT;
+ cs = ccre;
+ *cs = OPER;
+ OSYM(cs) = '|';
+ ccre = ONEXT(cs);
+ acs = cs; /* remember that the pointer is to be filles */
+ break;
+
+ /* if its not a metasymbol just build a scharacter string */
+ default:
+ if (cs == NIL || (*cs & STR) == 0) {
+ cs = ccre;
+ *cs = STR;
+ SCNT(cs) = 1;
+ ccre = SSTR(cs);
+ } else
+ SCNT(cs)++;
+ *ccre++ = c;
+ break;
+ }
+ }
+ if (acs != NIL) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NIL;
+ }
+ return;
+}
+/* end of convertre */
+
+
+/*
+ * The following routine recognises an irregular expresion
+ * with the following special characters:
+ *
+ * \? - means last match was optional
+ * \a - matches any number of characters
+ * \d - matches any number of spaces and tabs
+ * \p - matches any number of alphanumeric
+ * characters. The
+ * characters matched will be copied into
+ * the area pointed to by 'name'.
+ * \| - alternation
+ * \( \) - grouping used mostly for alternation and
+ * optionality
+ *
+ * The irregular expression must be translated to internal form
+ * prior to calling this routine
+ *
+ * The value returned is the pointer to the first non \a
+ * character matched.
+ */
+
+extern boolean escaped; /* true if we are currently escaped */
+extern char *Start; /* start of string */
+
+char *
+expmatch (
+ register char *s, /* string to check for a match in */
+ register char *re, /* a converted irregular expression */
+ register char *mstring /* where to put whatever matches a \p */
+)
+{
+ register char *cs; /* the current symbol */
+ register char *ptr,*s1; /* temporary pointer */
+ boolean matched; /* a temporary boolean */
+
+ /* initial conditions */
+ if (re == NIL)
+ return (NIL);
+ cs = re;
+ matched = FALSE;
+
+ /* loop till expression string is exhausted (or at least pretty tired) */
+ while (*cs) {
+ switch (*cs & (OPER | STR | META)) {
+
+ /* try to match a string */
+ case STR:
+ matched = !STRNCMP (s, SSTR(cs), SCNT(cs));
+ if (matched) {
+
+ /* hoorah it matches */
+ s += SCNT(cs);
+ cs = SNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* alternation, skip to next expression */
+ cs = SNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* the match is optional */
+ cs = SNEXT(cs);
+ matched = 1; /* indicate a successful match */
+ } else {
+
+ /* no match, error return */
+ return (NIL);
+ }
+ break;
+
+ /* an operator, do something fancy */
+ case OPER:
+ switch (OSYM(cs)) {
+
+ /* this is an alternation */
+ case '|':
+ if (matched)
+
+ /* last thing in the alternation was a match, skip ahead */
+ cs = OPTR(cs);
+ else
+
+ /* no match, keep trying */
+ cs = ONEXT(cs);
+ break;
+
+ /* this is a grouping, recurse */
+ case '(':
+ ptr = expmatch (s, ONEXT(cs), mstring);
+ if (ptr != NIL) {
+
+ /* the subexpression matched */
+ matched = 1;
+ s = ptr;
+ } else if (*cs & ALT) {
+
+ /* alternation, skip to next expression */
+ matched = 0;
+ } else if (*cs & OPT) {
+
+ /* the match is optional */
+ matched = 1; /* indicate a successful match */
+ } else {
+
+ /* no match, error return */
+ return (NIL);
+ }
+ cs = OPTR(cs);
+ break;
+ }
+ break;
+
+ /* try to match a metasymbol */
+ case META:
+ switch (MSYM(cs)) {
+
+ /* try to match anything and remember what was matched */
+ case 'p':
+ /*
+ * This is really the same as trying the match the
+ * remaining parts of the expression to any subset
+ * of the string.
+ */
+ s1 = s;
+ do {
+ ptr = expmatch (s1, MNEXT(cs), mstring);
+ if (ptr != NIL && s1 != s) {
+
+ /* we have a match, remember the match */
+ strncpy (mstring, s, s1 - s);
+ mstring[s1 - s] = '\0';
+ return (ptr);
+ } else if (ptr != NIL && (*cs & OPT)) {
+
+ /* it was aoptional so no match is ok */
+ return (ptr);
+ } else if (ptr != NIL) {
+
+ /* not optional and we still matched */
+ return (NIL);
+ }
+ if (!isidchr((int)*s1))
+ return (NIL);
+ if (*s1 == '\\')
+ escaped = escaped ? FALSE : TRUE;
+ else
+ escaped = FALSE;
+ } while (*s1++);
+ return (NIL);
+
+ /* try to match anything */
+ case 'a':
+ /*
+ * This is really the same as trying the match the
+ * remaining parts of the expression to any subset
+ * of the string.
+ */
+ s1 = s;
+ do {
+ ptr = expmatch (s1, MNEXT(cs), mstring);
+ if (ptr != NIL && s1 != s) {
+
+ /* we have a match */
+ return (ptr);
+ } else if (ptr != NIL && (*cs & OPT)) {
+
+ /* it was aoptional so no match is ok */
+ return (ptr);
+ } else if (ptr != NIL) {
+
+ /* not optional and we still matched */
+ return (NIL);
+ }
+ if (*s1 == '\\')
+ escaped = escaped ? FALSE : TRUE;
+ else
+ escaped = FALSE;
+ } while (*s1++);
+ return (NIL);
+
+ /* fail if we are currently escaped */
+ case 'e':
+ if (escaped)
+ return(NIL);
+ cs = MNEXT(cs);
+ break;
+
+ /* match any number of tabs and spaces */
+ case 'd':
+ ptr = s;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (s != ptr || s == Start) {
+
+ /* match, be happy */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*s == '\n' || *s == '\0') {
+
+ /* match, be happy */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* try the next part */
+ matched = 0;
+ cs = MNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* doesn't matter */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else
+
+ /* no match, error return */
+ return (NIL);
+ break;
+
+ /* check for end of line */
+ case '$':
+ if (*s == '\0' || *s == '\n') {
+
+ /* match, be happy */
+ s++;
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* try the next part */
+ matched = 0;
+ cs = MNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* doesn't matter */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else
+
+ /* no match, error return */
+ return (NIL);
+ break;
+
+ /* check for start of line */
+ case '^':
+ if (s == Start) {
+
+ /* match, be happy */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* try the next part */
+ matched = 0;
+ cs = MNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* doesn't matter */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else
+
+ /* no match, error return */
+ return (NIL);
+ break;
+
+ /* end of a subexpression, return success */
+ case ')':
+ return (s);
+ }
+ break;
+ }
+ }
+ return (s);
+}
diff --git a/vgrind/retest.c b/vgrind/retest.c
new file mode 100644
index 0000000000000..3364d9b2a846e
--- /dev/null
+++ b/vgrind/retest.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* from OpenSolaris "retest.c 1.11 92/07/21 SMI" */
+
+/*
+ * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
+ *
+ * Sccsid @(#)retest.c 1.3 (gritter) 10/22/05
+ */
+ /* from UCB 5.1 (Berkeley) 6/5/85 */
+
+#include <ctype.h>
+
+int l_onecase = 0;
+
+char *l_idchars = "_"; /* characters legal in identifiers in addition
+ to alphanumerics */
+
+char * Start;
+char * _escaped;
+char * convexp();
+char * expmatch();
+int
+main(void)
+{
+ char reg[132];
+ char *ireg;
+ char str[132];
+ char *match;
+ char matstr[132];
+ char c;
+
+ while (1) {
+ printf ("\nexpr: ");
+ scanf ("%s", reg);
+ ireg = convexp(reg);
+ match = ireg;
+ while(*match) {
+ switch (*match) {
+
+ case '\\':
+ case '(':
+ case ')':
+ case '|':
+ printf ("%c", *match);
+ break;
+
+ default:
+ if (isalnum(*match))
+ printf("%c", *match);
+ else
+ printf ("<%03o>", *match);
+ break;
+ }
+ match++;
+ }
+ printf("\n");
+ getchar();
+ while(1) {
+ printf ("string: ");
+ match = str;
+ while ((c = getchar()) != '\n')
+ *match++ = c;
+ *match = 0;
+ if (str[0] == '#')
+ break;
+ matstr[0] = 0;
+ Start = str;
+ _escaped = 0;
+ match = expmatch (str, ireg, matstr);
+ if (match == 0)
+ printf ("FAILED\n");
+ else
+ printf ("match\nmatstr = %s\n", matstr);
+ }
+
+ }
+ return 0;
+}
diff --git a/vgrind/version.c b/vgrind/version.c
new file mode 100644
index 0000000000000..5df0b7111fbee
--- /dev/null
+++ b/vgrind/version.c
@@ -0,0 +1,15 @@
+#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
+#define USED __attribute__ ((used))
+#elif defined __GNUC__
+#define USED __attribute__ ((unused))
+#else
+#define USED
+#endif
+static const char sccsid[] USED = "@(#)/usr/ucblib/vfontedpr.sl 5.1 (gritter) 10/25/05";
+/* SLIST */
+/*
+regexp.c: * Sccsid @(#)regexp.c 1.3 (gritter) 10/22/05
+retest.c: * Sccsid @(#)retest.c 1.3 (gritter) 10/22/05
+vfontedpr.c: * Sccsid @(#)vfontedpr.c 1.4 (gritter) 10/22/05
+vgrindefs.c: * Sccsid @(#)vgrindefs.c 1.3 (gritter) 10/22/05
+*/
diff --git a/vgrind/vfontedpr.c b/vgrind/vfontedpr.c
new file mode 100644
index 0000000000000..9f833730f4b83
--- /dev/null
+++ b/vgrind/vfontedpr.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* from OpenSolaris "vfontedpr.c 1.17 93/06/03 SMI" */
+
+/*
+ * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
+ *
+ * Sccsid @(#)vfontedpr.c 1.4 (gritter) 10/22/05
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#ifdef EUC
+#include <wchar.h>
+#endif
+
+#if defined (__GLIBC__) && defined (_IO_getc_unlocked)
+#undef getc
+#define getc(f) _IO_getc_unlocked(f)
+#endif
+
+#define boolean int
+#define TRUE 1
+#define FALSE 0
+#define NIL 0
+#define STANDARD 0
+#define ALTERNATE 1
+
+/*
+ * Vfontedpr.
+ *
+ * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
+ *
+ */
+
+#define STRLEN 10 /* length of strings introducing things */
+#define PNAMELEN 40 /* length of a function/procedure name */
+#define PSMAX 20 /* size of procedure name stacking */
+
+/* regular expression routines */
+
+/* regexp.c */
+/*char *expmatch(); match a string to an expression */
+char *expmatch(register char *, register char *, register char *);
+/*char *STRNCMP(); a different kind of strncmp */
+int STRNCMP(register char *, register char *, register int);
+/*char *convexp(); convert expression to internal form */
+char *convexp(char *);
+
+/*
+ * The state variables
+ */
+
+static boolean incomm; /* in a comment of the primary type */
+static boolean instr; /* in a string constant */
+static boolean inchr; /* in a string constant */
+static boolean nokeyw = FALSE; /* no keywords being flagged */
+static boolean doindex = FALSE;/* form an index */
+static boolean twocol = FALSE; /* in two-column mode */
+static boolean filter = FALSE; /* act as a filter (like eqn) */
+static boolean pass = FALSE; /* when acting as a filter, pass indicates
+ * whether we are currently processing
+ * input.
+ */
+static boolean prccont; /* continue last procedure */
+static int comtype; /* type of comment */
+static int margin;
+static int psptr; /* the stack index of the current procedure */
+static char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */
+static int plstack[PSMAX]; /* the procedure nesting level stack */
+static int blklevel; /* current nesting level */
+static int prclevel; /* nesting level at which procedure definitions
+ may be found, -1 if none currently valid
+ (meaningful only if l_prclevel is true) */
+static char *defsfile = LIBDIR "/vgrindefs"; /* name of language definitions file */
+static char pname[BUFSIZ+1];
+
+/*
+ * The language specific globals
+ */
+
+static char *language = "c";/* the language indicator */
+static char *l_keywds[BUFSIZ/2]; /* keyword table address */
+static char *l_prcbeg; /* regular expr for procedure begin */
+static char *l_combeg; /* string introducing a comment */
+static char *l_comend; /* string ending a comment */
+static char *l_acmbeg; /* string introducing a comment */
+static char *l_acmend; /* string ending a comment */
+static char *l_blkbeg; /* string begining of a block */
+static char *l_blkend; /* string ending a block */
+static char *l_strbeg; /* delimiter for string constant */
+static char *l_strend; /* delimiter for string constant */
+static char *l_chrbeg; /* delimiter for character constant */
+static char *l_chrend; /* delimiter for character constant */
+static char *l_prcenable; /* re indicating that procedure definitions
+ can be found in the next lexical level --
+ kludge for lisp-like languages that use
+ something like
+ (defun (proc ...)
+ (proc ...)
+ )
+ to define procedures */
+static char l_escape; /* character used to escape characters */
+static boolean l_toplex; /* procedures only defined at top lex level */
+static boolean l_prclevel; /* procedure definitions valid only within
+ the nesting level indicated by the px
+ (l_prcenable) capability */
+
+/*
+ * for the benefit of die-hards who aren't convinced that tabs
+ * occur every eight columns
+ */
+static short tabsize = 8;
+
+static int mb_cur_max;
+
+/*
+ * global variables also used by expmatch
+ */
+boolean escaped; /* if last character was an escape */
+char *Start; /* start of the current string */
+boolean l_onecase; /* upper and lower case are equivalent */
+char *l_idchars; /* characters legal in identifiers in addition
+ to letters and digits (default "_") */
+
+extern int STRNCMP(register char *, register char *, register int);
+extern char *convexp(char *);
+extern char *expmatch(register char *, register char *, register char *);
+extern int tgetent(char *, char *, char *);
+extern int tgetnum(char *);
+extern int tgetflag(char *);
+extern char *tgetstr(char *, char **);
+
+static void putScp(char *);
+static void putKcp(char *, char *, int);
+static int tabs(char *, char *);
+static int width(register char *, register char *);
+static void putcp(register int);
+static int isproc(char *);
+static int iskw(register char *);
+static char *fgetline(char **, size_t *, size_t *, FILE *);
+
+/*
+ * The code below emits troff macros and directives that consume part of the
+ * troff macro and register space. See tmac.vgrind for an enumeration of
+ * these macros and registers.
+ */
+
+int
+main(int argc, char **argv)
+{
+ FILE *in;
+ char *fname;
+ struct stat stbuf;
+ char *buf = NULL;
+ size_t size = 0;
+ char idbuf[256]; /* enough for all 8 bit chars */
+ char strings[2 * BUFSIZ];
+ char defs[2 * BUFSIZ];
+ int needbp = 0;
+ int i;
+ char *cp;
+
+ setlocale(LC_CTYPE, "");
+ mb_cur_max = MB_CUR_MAX;
+
+ buf = malloc(size = BUFSIZ);
+
+ /*
+ * Dump the name by which we were invoked.
+ */
+ argc--, argv++;
+
+ /*
+ * Process arguments. For the sake of compatibility with older versions
+ * of the program, the syntax accepted below is very idiosyncratic. Some
+ * options require space between the option and its argument; others
+ * disallow it. No options may be bundled together.
+ *
+ * Actually, there is one incompatibility. Files and options formerly
+ * could be arbitrarily intermixed, but this is no longer allowed. (This
+ * possiblity was never documented.)
+ */
+ while (argc > 0 && *argv[0] == '-') {
+ switch (*(cp = argv[0] + 1)) {
+
+ case '\0': /* - */
+ /* Take input from stdin. */
+ /*
+ * This option implies the end of the flag arguments. Leave the
+ * "-" in place for the file processing code to see.
+ */
+ goto flagsdone;
+
+ case '2': /* -2 */
+ /* Enter two column mode. */
+ twocol = 1;
+ printf("'nr =2 1\n");
+ break;
+
+ case 'd': /* -d <defs-file> */
+ /* Specify the language description file. */
+ defsfile = argv[1];
+ argc--, argv++;
+ break;
+
+ case 'f': /* -f */
+ /* Act as a filter like eqn. */
+ filter = 1;
+ /*
+ * Slide remaining arguments down one position and postpend "-",
+ * to force reading from stdin.
+ */
+ for (i = 0; i < argc - 1; i++)
+ argv[i] = argv[i + 1];
+ argv[argc - 1] = "-";
+ continue;
+
+ case 'h': /* -h [header] */
+ /* Specify header string. */
+ if (argc == 1) {
+ printf("'ds =H\n");
+ break;
+ }
+ printf("'ds =H %s\n", argv[1]);
+ argc--, argv++;
+ break;
+
+ case 'l': /* -l<language> */
+ /* Specify the language. */
+ language = cp + 1;
+ break;
+
+ case 'n': /* -n */
+ /* Indicate no keywords. */
+ nokeyw = 1;
+ break;
+
+ case 's': /* -s<size> */
+ /* Specify the font size. */
+ i = 0;
+ cp++;
+ while (*cp)
+ i = i * 10 + (*cp++ - '0');
+ printf("'nr vP %d\n", i);
+ break;
+
+ case 't': /* -t */
+ /* Specify a nondefault tab size. */
+ tabsize = 4;
+ break;
+
+ case 'x': /* -x */
+ /* Build an index. */
+ doindex = 1;
+ /* This option implies "-n" as well; turn it on. */
+ argv[0] = "-n";
+ continue;
+ }
+
+ /* Advance to next argument. */
+ argc--, argv++;
+ }
+
+flagsdone:
+
+ /*
+ * Get the language definition from the defs file.
+ */
+ i = tgetent (defs, language, defsfile);
+ if (i == 0) {
+ fprintf (stderr, "no entry for language %s\n", language);
+ exit (0);
+ } else if (i < 0) {
+ fprintf (stderr, "cannot find vgrindefs file %s\n", defsfile);
+ exit (0);
+ }
+ cp = strings;
+ if (tgetstr ("kw", &cp) == NIL)
+ nokeyw = TRUE;
+ else {
+ char **cpp;
+
+ cpp = l_keywds;
+ cp = strings;
+ while (*cp) {
+ while (*cp == ' ' || *cp =='\t')
+ *cp++ = '\0';
+ if (*cp)
+ *cpp++ = cp;
+ while (*cp != ' ' && *cp != '\t' && *cp)
+ cp++;
+ }
+ *cpp = NIL;
+ }
+ cp = buf;
+ l_prcbeg = convexp (tgetstr ("pb", &cp));
+ cp = buf;
+ l_combeg = convexp (tgetstr ("cb", &cp));
+ cp = buf;
+ l_comend = convexp (tgetstr ("ce", &cp));
+ cp = buf;
+ l_acmbeg = convexp (tgetstr ("ab", &cp));
+ cp = buf;
+ l_acmend = convexp (tgetstr ("ae", &cp));
+ cp = buf;
+ l_strbeg = convexp (tgetstr ("sb", &cp));
+ cp = buf;
+ l_strend = convexp (tgetstr ("se", &cp));
+ cp = buf;
+ l_blkbeg = convexp (tgetstr ("bb", &cp));
+ cp = buf;
+ l_blkend = convexp (tgetstr ("be", &cp));
+ cp = buf;
+ l_chrbeg = convexp (tgetstr ("lb", &cp));
+ cp = buf;
+ l_chrend = convexp (tgetstr ("le", &cp));
+ cp = buf;
+ l_prcenable = convexp (tgetstr ("px", &cp));
+ cp = idbuf;
+ l_idchars = tgetstr ("id", &cp);
+ /* Set default, for compatibility with old version */
+ if (l_idchars == NIL)
+ l_idchars = "_";
+ l_escape = '\\';
+ l_onecase = tgetflag ("oc");
+ l_toplex = tgetflag ("tl");
+ l_prclevel = tgetflag ("pl");
+
+ /*
+ * Emit a call to the initialization macro. If not in filter mode, emit a
+ * call to the vS macro, so that tmac.vgrind can uniformly assume that all
+ * program input is bracketed with vS-vE pairs.
+ */
+ printf("'vI\n");
+ if (!filter)
+ printf("'vS\n");
+
+ if (doindex) {
+ /*
+ * XXX: Hard-wired spacing information. This should probably turn
+ * into the emission of a macro invocation, so that tmac.vgrind
+ * can make up its own mind about what spacing is appropriate.
+ */
+ if (twocol)
+ printf("'ta 2.5i 2.75i 4.0iR\n'in .25i\n");
+ else
+ printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
+ }
+
+ while (argc > 0) {
+ if (strcmp(argv[0], "-") == 0) {
+ /* Embed an instance of the original stdin. */
+ in = fdopen(fileno(stdin), "r");
+ fname = "";
+ } else {
+ /* Open the file for input. */
+ if ((in = fopen(argv[0], "r")) == NULL) {
+ perror(argv[0]);
+ exit(1);
+ }
+ fname = argv[0];
+ }
+ argc--, argv++;
+
+ /*
+ * Reinitialize for the current file.
+ */
+ incomm = FALSE;
+ instr = FALSE;
+ inchr = FALSE;
+ escaped = FALSE;
+ blklevel = 0;
+ prclevel = -1;
+ for (psptr=0; psptr<PSMAX; psptr++) {
+ pstack[psptr][0] = '\0';
+ plstack[psptr] = 0;
+ }
+ psptr = -1;
+ printf("'-F\n");
+ if (!filter) {
+ char *cp;
+
+ printf(".ds =F %s\n", fname);
+ if (needbp) {
+ needbp = 0;
+ printf(".()\n");
+ printf(".bp\n");
+ }
+ fstat(fileno(in), &stbuf);
+ cp = ctime(&stbuf.st_mtime);
+ cp[16] = '\0';
+ cp[24] = '\0';
+ printf(".ds =M %s %s\n", cp+4, cp+20);
+ printf("'wh 0 vH\n");
+ printf("'wh -1i vF\n");
+ }
+ if (needbp && filter) {
+ needbp = 0;
+ printf(".()\n");
+ printf(".bp\n");
+ }
+
+ /*
+ * MAIN LOOP!!!
+ */
+ while (fgetline(&buf, &size, NULL, in) != NULL) {
+ if (buf[0] == '\f') {
+ printf(".bp\n");
+ }
+ if (buf[0] == '.') {
+ printf("%s", buf);
+ if (!strncmp (buf+1, "vS", 2))
+ pass = TRUE;
+ if (!strncmp (buf+1, "vE", 2))
+ pass = FALSE;
+ continue;
+ }
+ prccont = FALSE;
+ if (!filter || pass)
+ putScp(buf);
+ else
+ printf("%s", buf);
+ if (prccont && (psptr >= 0))
+ printf("'FC %s\n", pstack[psptr]);
+#ifdef DEBUG
+ printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
+#endif
+ margin = 0;
+ }
+
+ needbp = 1;
+ fclose(in);
+ }
+
+ /* Close off the vS-vE pair. */
+ if (!filter)
+ printf("'vE\n");
+
+ exit(0);
+ /* NOTREACHED */
+}
+
+#define isidchr(c) (isalnum(c) || ((c) != NIL && strchr(l_idchars, (c)) != NIL))
+
+static void
+putScp(char *os)
+{
+ register char *s = os; /* pointer to unmatched string */
+ char dummy[BUFSIZ]; /* dummy to be used by expmatch */
+ char *comptr; /* end of a comment delimiter */
+ char *acmptr; /* end of a comment delimiter */
+ char *strptr; /* end of a string delimiter */
+ char *chrptr; /* end of a character const delimiter */
+ char *blksptr; /* end of a lexical block start */
+ char *blkeptr; /* end of a lexical block end */
+
+ Start = os; /* remember the start for expmatch */
+ escaped = FALSE;
+ if (nokeyw || incomm || instr)
+ goto skip;
+ if (isproc(s)) {
+ printf("'FN %s\n", pname);
+ if (psptr < PSMAX-1) {
+ ++psptr;
+ strncpy (pstack[psptr], pname, PNAMELEN);
+ pstack[psptr][PNAMELEN] = '\0';
+ plstack[psptr] = blklevel;
+ }
+ }
+ /*
+ * if l_prclevel is set, check to see whether this lexical level
+ * is one immediately below which procedure definitions are allowed.
+ */
+ if (l_prclevel && !incomm && !instr && !inchr) {
+ if (expmatch (s, l_prcenable, dummy) != NIL)
+ prclevel = blklevel + 1;
+ }
+skip:
+ do {
+ /* check for string, comment, blockstart, etc */
+ if (!incomm && !instr && !inchr) {
+
+ blkeptr = expmatch (s, l_blkend, dummy);
+ blksptr = expmatch (s, l_blkbeg, dummy);
+ comptr = expmatch (s, l_combeg, dummy);
+ acmptr = expmatch (s, l_acmbeg, dummy);
+ strptr = expmatch (s, l_strbeg, dummy);
+ chrptr = expmatch (s, l_chrbeg, dummy);
+
+ /* start of a comment? */
+ if (comptr != NIL)
+ if ((comptr < strptr || strptr == NIL)
+ && (comptr < acmptr || acmptr == NIL)
+ && (comptr < chrptr || chrptr == NIL)
+ && (comptr < blksptr || blksptr == NIL)
+ && (comptr < blkeptr || blkeptr == NIL)) {
+ putKcp (s, comptr-1, FALSE);
+ s = comptr;
+ incomm = TRUE;
+ comtype = STANDARD;
+ if (s != os)
+ printf ("\\c");
+ printf ("\\c\n'+C\n");
+ continue;
+ }
+
+ /* start of a comment? */
+ if (acmptr != NIL)
+ if ((acmptr < strptr || strptr == NIL)
+ && (acmptr < chrptr || chrptr == NIL)
+ && (acmptr < blksptr || blksptr == NIL)
+ && (acmptr < blkeptr || blkeptr == NIL)) {
+ putKcp (s, acmptr-1, FALSE);
+ s = acmptr;
+ incomm = TRUE;
+ comtype = ALTERNATE;
+ if (s != os)
+ printf ("\\c");
+ printf ("\\c\n'+C\n");
+ continue;
+ }
+
+ /* start of a string? */
+ if (strptr != NIL)
+ if ((strptr < chrptr || chrptr == NIL)
+ && (strptr < blksptr || blksptr == NIL)
+ && (strptr < blkeptr || blkeptr == NIL)) {
+ putKcp (s, strptr-1, FALSE);
+ s = strptr;
+ instr = TRUE;
+ continue;
+ }
+
+ /* start of a character string? */
+ if (chrptr != NIL)
+ if ((chrptr < blksptr || blksptr == NIL)
+ && (chrptr < blkeptr || blkeptr == NIL)) {
+ putKcp (s, chrptr-1, FALSE);
+ s = chrptr;
+ inchr = TRUE;
+ continue;
+ }
+
+ /* end of a lexical block */
+ if (blkeptr != NIL) {
+ if (blkeptr < blksptr || blksptr == NIL) {
+ /* reset prclevel if necessary */
+ if (l_prclevel && prclevel == blklevel)
+ prclevel = -1;
+ putKcp (s, blkeptr - 1, FALSE);
+ s = blkeptr;
+ blklevel--;
+ if (psptr >= 0 && plstack[psptr] >= blklevel) {
+
+ /* end of current procedure */
+ if (s != os)
+ printf ("\\c");
+ printf ("\\c\n'-F\n");
+ blklevel = plstack[psptr];
+
+ /* see if we should print the last proc name */
+ if (--psptr >= 0)
+ prccont = TRUE;
+ else
+ psptr = -1;
+ }
+ continue;
+ }
+ }
+
+ /* start of a lexical block */
+ if (blksptr != NIL) {
+ putKcp (s, blksptr - 1, FALSE);
+ s = blksptr;
+ blklevel++;
+ continue;
+ }
+
+ /* check for end of comment */
+ } else if (incomm) {
+ comptr = expmatch (s, l_comend, dummy);
+ acmptr = expmatch (s, l_acmend, dummy);
+ if (((comtype == STANDARD) && (comptr != NIL)) ||
+ ((comtype == ALTERNATE) && (acmptr != NIL))) {
+ if (comtype == STANDARD) {
+ putKcp (s, comptr-1, TRUE);
+ s = comptr;
+ } else {
+ putKcp (s, acmptr-1, TRUE);
+ s = acmptr;
+ }
+ incomm = FALSE;
+ printf("\\c\n'-C\n");
+ continue;
+ } else {
+ putKcp (s, s + strlen(s) -1, TRUE);
+ s = s + strlen(s);
+ continue;
+ }
+
+ /* check for end of string */
+ } else if (instr) {
+ if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
+ putKcp (s, strptr-1, TRUE);
+ s = strptr;
+ instr = FALSE;
+ continue;
+ } else {
+ putKcp (s, s+strlen(s)-1, TRUE);
+ s = s + strlen(s);
+ continue;
+ }
+
+ /* check for end of character string */
+ } else if (inchr) {
+ if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) {
+ putKcp (s, chrptr-1, TRUE);
+ s = chrptr;
+ inchr = FALSE;
+ continue;
+ } else {
+ putKcp (s, s+strlen(s)-1, TRUE);
+ s = s + strlen(s);
+ continue;
+ }
+ }
+
+ /* print out the line */
+ putKcp (s, s + strlen(s) -1, FALSE);
+ s = s + strlen(s);
+ } while (*s);
+}
+
+static void
+putKcp (
+ char *start, /* start of string to write */
+ char *end, /* end of string to write */
+ boolean force /* true if we should force nokeyw */
+)
+{
+ int i;
+ int xfld = 0;
+
+ while (start <= end) {
+ if (doindex) {
+ if (*start == ' ' || *start == '\t') {
+ if (xfld == 0)
+ printf("");
+ printf("\t");
+ xfld = 1;
+ while (*start == ' ' || *start == '\t')
+ start++;
+ continue;
+ }
+ }
+
+ /* take care of nice tab stops */
+ if (*start == '\t') {
+ while (*start == '\t')
+ start++;
+ i = tabs(Start, start) - margin / tabsize;
+ printf ("\\h'|%dn'",
+ i * (tabsize == 4 ? 5 : 10) + 1 - margin % tabsize);
+ continue;
+ }
+
+ if (!nokeyw && !force)
+ if ( (*start == '#' || isidchr((int)*start))
+ && (start == Start || !isidchr((int)start[-1]))
+ ) {
+ i = iskw(start);
+ if (i > 0) {
+ printf("\\*(+K");
+ do
+ putcp(*start++);
+ while (--i > 0);
+ printf("\\*(-K");
+ continue;
+ }
+ }
+
+ putcp (*start++);
+ }
+}
+
+
+static int
+tabs(char *s, char *os)
+{
+
+ return (width(s, os) / tabsize);
+}
+
+static int
+width(register char *s, register char *os)
+{
+ register int i = 0;
+ unsigned char c;
+ int n;
+
+ while (s < os) {
+ if (*s == '\t') {
+ i = (i + tabsize) &~ (tabsize-1);
+ s++;
+ continue;
+ }
+ c = *(unsigned char *)s;
+ if (c < ' ')
+ i += 2, s++;
+#ifdef EUC
+ else if (c >= 0200) {
+ wchar_t wc;
+ if ((n = mbtowc(&wc, s, mb_cur_max)) > 0) {
+ s += n;
+ if ((n = wcwidth(wc)) > 0)
+ i += n;
+ } else
+ s++;
+ }
+#endif /* EUC */
+ else
+ i++, s++;
+ }
+ return (i);
+}
+
+static void
+putcp(register int c)
+{
+
+ switch(c) {
+
+ case 0:
+ break;
+
+ case '\f':
+ break;
+
+ case '{':
+ printf("\\*(+K{\\*(-K");
+ break;
+
+ case '}':
+ printf("\\*(+K}\\*(-K");
+ break;
+
+ case '\\':
+ printf("\\e");
+ break;
+
+ case '_':
+ printf("\\*_");
+ break;
+
+ case '-':
+ printf("\\*-");
+ break;
+
+ /*
+ * The following two cases deal with the accent characters.
+ * If they're part of a comment, we assume that they're part
+ * of running text and hand them to troff as regular quote
+ * characters. Otherwise, we assume they're being used as
+ * special characters (e.g., string delimiters) and arrange
+ * for troff to render them as accents. This is an imperfect
+ * heuristic that produces slightly better appearance than the
+ * former behavior of unconditionally rendering the characters
+ * as accents. (See bug 1040343.)
+ */
+
+ case '`':
+ if (incomm)
+ printf("`");
+ else
+ printf("\\`");
+ break;
+
+ case '\'':
+ if (incomm)
+ printf("'");
+ else
+ printf("\\'");
+ break;
+
+ case '.':
+ printf("\\&.");
+ break;
+
+ /*
+ * The following two cases contain special hacking
+ * to make C-style comments line up. The tests aren't
+ * really adequate; they lead to grotesqueries such
+ * as italicized multiplication and division operators.
+ * However, the obvious test (!incomm) doesn't work,
+ * because incomm isn't set until after we've put out
+ * the comment-begin characters. The real problem is
+ * that expmatch() doesn't give us enough information.
+ */
+
+ case '*':
+ if (instr || inchr)
+ printf("*");
+ else
+ printf("\\f2*\\fP");
+ break;
+
+ case '/':
+ if (instr || inchr)
+ printf("/");
+ else
+ printf("\\f2\\h'\\w' 'u-\\w'/'u'/\\fP");
+ break;
+
+ default:
+ if (c < 040)
+ putchar('^'), c |= '@';
+ case '\t':
+ case '\n':
+ putchar(c);
+ }
+}
+
+/*
+ * look for a process beginning on this line
+ */
+static boolean
+isproc(char *s)
+{
+ pname[0] = '\0';
+ if (l_prclevel ? (prclevel == blklevel) : (!l_toplex || blklevel == 0))
+ if (expmatch (s, l_prcbeg, pname) != NIL) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * iskw - check to see if the next word is a keyword
+ * Return its length if it is or 0 if it isn't.
+ */
+
+static int
+iskw(register char *s)
+{
+ register char **ss = l_keywds;
+ register int i = 1;
+ register char *cp = s;
+
+ /* Get token length. */
+ while (++cp, isidchr((int)*cp))
+ i++;
+
+ while ((cp = *ss++)) {
+ if (!STRNCMP(s,cp,i) && !isidchr((int)cp[i]))
+ return (i);
+ }
+ return (0);
+}
+
+#define LSIZE 128
+
+static char *
+fgetline(char **line, size_t *linesize, size_t *llen, FILE *fp)
+{
+ int c;
+ size_t n = 0;
+
+ if (*line == NULL || *linesize < LSIZE + n + 1)
+ *line = realloc(*line, *linesize = LSIZE + n + 1);
+ for (;;) {
+ if (n >= *linesize - LSIZE / 2)
+ *line = realloc(*line, *linesize += LSIZE);
+ c = getc(fp);
+ if (c != EOF) {
+ (*line)[n++] = c;
+ (*line)[n] = '\0';
+ if (c == '\n')
+ break;
+ } else {
+ if (n > 0)
+ break;
+ else
+ return NULL;
+ }
+ }
+ if (llen)
+ *llen = n;
+ return *line;
+}
diff --git a/vgrind/vgrind.1 b/vgrind/vgrind.1
new file mode 100644
index 0000000000000..ad907958e01a8
--- /dev/null
+++ b/vgrind/vgrind.1
@@ -0,0 +1,228 @@
+.\"
+.\" This code contains changes by
+.\" Gunnar Ritter, Freiburg i. Br., Germany, 2005. All rights reserved.
+.\"
+.\" Conditions 1, 2, and 4 and the no-warranty notice below apply
+.\" to these changes.
+.\"
+.\"
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" 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 acknowedgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" from 4.3BSD-Tahoe vgrind.1 6.2 (Berkeley) 5/5/86
+.\".TH VGRIND 1 "May 5, 1986"
+.\"
+.\" Sccsid @(#)vgrind.1b 1.3 (gritter) 11/6/05
+.\"
+.TH VGRIND 1 "11/6/05" "Heirloom Documentation Tools" "BSD System Compatibility"
+.UC 4
+.SH NAME
+vgrind \- grind nice listings of programs
+.SH SYNOPSIS
+.HP
+.ad l
+.nh
+\fBvgrind\fR
+[\fB\-2ftnxw\fR]
+[\fB\-s\fIn\fR]
+[\fB\-h\ \fIheader\fR]
+[\fB\-d\ \fIfile\fR]
+[\fB\-l\ \fIlanguage\fR]
+[\fB\-P\ \fIprinter\fR]
+[\fB\-T\ \fIdevice\fR]
+[\fB\-o\ \fIlist\fR]
+\fIname\fR\ ...
+.br
+.hy 1
+.ad b
+.SH DESCRIPTION
+.I Vgrind
+formats the program sources which are arguments
+in a nice style using
+.IR troff (1).
+Comments are placed in italics, keywords in bold face,
+and the name of the current function is listed down the margin of each
+page as it is encountered.
+.PP
+.I Vgrind
+runs in two basic modes, filter mode or regular mode. In filter mode
+.I vgrind
+acts as a filter in a manner similar to
+.IR tbl (1).
+The standard input is passed directly to the standard output except
+for lines bracketed by the
+.I troff-like
+macros:
+.IP .vS
+\- starts processing
+.IP .vE
+\- ends processing
+.LP
+These lines are formatted as described above. The output from this
+filter can be passed to
+.I troff
+for output. There need be no particular ordering with
+.IR eqn (1)
+or
+.IR tbl (1).
+.PP
+In regular mode
+.I vgrind
+accepts input files, processes them, and passes them to
+.IR troff (1)
+for output.
+.PP
+In both modes
+.I vgrind
+passes any lines beginning with a decimal point without conversion.
+.PP
+The options are:
+.IP \fB\-2\fP
+produce two-column output
+.IP \fB\-f\fP
+forces filter mode
+.IP \fB\-t\fP
+similar to the same option in
+.I troff
+causing formatted text to go to the standard output
+.IP \fB\-n\fP
+forces no keyword bolding
+.IP \fB\-x\fP
+outputs the index file in a ``pretty'' format.
+The index file itself is produced whenever
+.I vgrind
+is run with a file called
+.I index
+in the current directory.
+The index of function
+definitions can then be run off by giving
+.I vgrind
+the
+.B \-x
+option and the file
+.I index
+as argument.
+.IP \fB\-s\fP
+specifies a point size to use on output (exactly the same as the argument
+of a .ps)
+.IP \fB\-h\fP
+specifies a particular header to put on every output page (default is
+the file name)
+.IP \fB\-d\fP
+specifies an alternate language definitions
+file (default is /usr/lib/vgrindefs)
+.IP \fB\-l\fP
+specifies the language to use. Currently known are PASCAL
+.RB ( \-lp ),
+MODEL
+.RB ( \-lm ),
+C
+.RB ( \-lc
+or the default),
+C++
+.RB ( \-lc++ ),
+CSH
+.RB ( \-lcsh ),
+SHELL
+.RB ( \-lsh ),
+RATFOR
+.RB ( \-lr ),
+MODULA2
+.RB ( \-lmod2 ),
+YACC
+.RB ( \-lyacc ),
+ISP
+.RB ( \-lisp ),
+and ICON
+.RB ( \-lI ).
+.IP \fB\-P\fP
+specifies that output is directed to the named printer.
+.IP \fB\-T\fP
+is passed to
+.I troff
+and specifies the device to use.
+.IP \fB\-o\fP
+is passed to
+.I troff
+and specifies selected pages to print.
+.IP \fB\-w\fP
+Sets the size of tabulators to four instead of the default eight.
+.SH FILES
+.\".ta \w'/usr/ucblib/tmac/vgrind 'u
+index file where source for index is created
+.br
+/usr/ucblib/tmac/vgrind macro package
+.br
+/usr/ucblib/vfontedpr preprocessor
+.br
+/usr/ucblib/vgrindefs language descriptions
+.SH SEE ALSO
+troff(1)
+.SH NOTES
+Vfontedpr assumes that a certain programming style is followed:
+.PP
+For
+.B C
+and
+.B C++
+\- function names can be preceded on a line only by spaces, tabs, or an
+asterisk. The parenthesized arguments must also be on the same line.
+.PP
+For
+.B PASCAL
+\- function names need to appear on the same line as the keywords
+.I function
+or
+.I procedure.
+.PP
+For
+.B MODEL
+\- function names need to appear on the same line as the keywords
+.I is
+.I beginproc.
+.PP
+If these conventions are not followed, the indexing and marginal function
+name comment mechanisms will fail.
+.sp
+More generally, arbitrary formatting styles for programs mostly look bad.
+The use of spaces to align source code fails miserably; if you plan to
+.I vgrind
+your program you should use tabs. This is somewhat inevitable since the
+font used by
+.I vgrind
+is variable width.
+.PP
+The mechanism of ctags in recognizing functions should be used here.
+.PP
+Filter mode does not work in documents using the \-me or \-ms macros.
+(So what use is it anyway?)
+.PP
+Written by Dave Presotto & William Joy.
diff --git a/vgrind/vgrind.sh b/vgrind/vgrind.sh
new file mode 100755
index 0000000000000..e341fba092cd3
--- /dev/null
+++ b/vgrind/vgrind.sh
@@ -0,0 +1,259 @@
+#
+# vgrind
+# Copyright (c) 1999-2000 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# from OpenSolaris "vgrind.ksh 1.4 05/06/12 SMI"
+#
+# Copyright (c) 1980 Regents of the University of California.
+# All rights reserved. The Berkeley software License Agreement
+# specifies the terms and conditions for redistribution.
+#
+# This is a rewrite in sh of a rewrite in ksh of the command
+# originally written in csh whose last incarnation was:
+# vgrind.csh 1.16 96/10/14 SMI; from UCB 5.3 (Berkeley) 11/13/85
+#
+# Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
+#
+# Sccsid @(#)vgrind.sh 1.3 (gritter) 10/22/05
+#
+
+PATH=/usr/5bin:$PATH export PATH
+
+# Definitions the user can override
+
+troff=${TROFF:-$_TROFF}
+vfontedpr=${VFONTEDPR:-$_VFONTEDPR}
+macros=${TMAC_VGRIND:-$_TMAC_VGRIND}
+lp=${LP:-lp}
+
+# Internal processing of options
+
+dpost=$_DPOST
+
+args=""
+dpostopts=""
+files=""
+lpopts=""
+troffopts="-t"
+
+filter=0
+uselp=1
+usedpost=1
+stdoutisatty=0
+
+pspec=0
+tspec=0
+twospec=0
+
+printer=""
+
+if [ -t 1 ] ; then
+ stdoutisatty=1
+fi
+
+# Process command line options
+
+while getopts ":2d:fh:l:no:P:s:tT:wWx" opt ; do
+ case "$opt" in
+ +*)
+ printf 'vgrind: bad option %s\n' "+$opt" >&2
+ exit 1
+ ;;
+ "?")
+ printf 'vgrind: bad option %s\n' "-$OPTARG" >&2
+ exit 1
+ ;;
+ 2)
+ dpostopts="$dpostopts -p l"
+ usedpost=1
+ args="$args -2"
+ twospec=1
+ ;;
+ d)
+ args="$args -d $OPTARG"
+ if ! [ -r $OPTARG ] ; then
+ printf 'vgrind: -%s %s: file not readable\n' "$opt" "$OPTARG" >&2
+ exit 1
+ fi
+ ;;
+ f)
+ filter=1
+ args="$args -f"
+ ;;
+ h)
+ args="$args -h '$OPTARG'"
+ ;;
+ l)
+ args="$args -l$OPTARG"
+ ;;
+ n)
+ args="$args -$opt"
+ ;;
+ o)
+ troffopts="$troffopts -o$OPTARG"
+ ;;
+ P)
+ uselp=1
+ usedpost=1
+ printer=$OPTARG
+ pspec=1
+ ;;
+ s)
+ args="$args -s$OPTARG"
+ ;;
+ T)
+ troffopts="$troffopts -T$OPTARG"
+ ;;
+ t)
+ uselp=0
+ usedpost=0
+ tspec=1
+ ;;
+ W)
+ # Do nothing with this switch
+ ;;
+ w)
+ args="$args -t"
+ ;;
+ x)
+ args="$args -x"
+ ;;
+ *)
+ troffopts="$troffopts -$opt"
+ ;;
+ esac
+
+ if [ "$opt" = ":" ] ; then
+ printf 'vgrind: missing argument to option %s\n' "-$OPTARG" >&2
+ exit 1
+ fi
+done
+
+test $OPTIND -gt 1 && shift `expr $OPTIND - 1`
+
+for x in "$@" ; do
+ args="$args '$x'"
+ files="$files '$x'"
+done
+
+shift $#
+
+if [ $filter -eq 1 -a \( $twospec -eq 1 -o $pspec -eq 1 \) ] ; then
+ printf 'vgrind: option -f is incompatible with -2 and -P\n' >&2
+ exit 1
+fi
+
+if [ $filter -eq 1 -a $tspec -eq 1 ] ; then
+ printf 'vgrind: option -f is incompatible with -t\n' >&2
+ exit 1
+fi
+
+if [ $tspec -eq 1 -a \( $twospec -eq 1 -o $pspec -eq 1 \) ] ; then
+ printf 'vgrind: option -t is incompatible with -2 and -P\n' >&2
+ exit 1
+fi
+
+# Do some reasoning about whether to print
+
+if [ $uselp -eq 1 ] ; then
+ # If we want to print
+
+ if [ -z "$printer" ] ; then
+ # If "-P" was not specified
+
+ defaultprinter=`LC_ALL=C lpstat -d | sed -e "s/no system default destination//" 2>/dev/null`
+
+ if [ -n "$defaultprinter" ] ; then
+ defaultprinter=`echo $defaultprinter | \
+ sed -e "s/system default destination: //" 2>/dev/null`
+ fi
+
+ if [ $stdoutisatty -eq 1 ] ; then
+ # If stdout is not re-directed
+
+ if [ -z "$defaultprinter" ] ; then
+ uselp=0
+ else
+ printer=$defaultprinter
+ fi
+ else
+ # stdout is redirected - assume it is for further processing of
+ # postscript output.
+
+ uselp=0
+ fi
+ fi
+fi
+
+if [ $uselp -eq 1 ] ; then
+ case `basename $lp` in
+ lp)
+ lpopts="$lpopts -d$printer"
+ ;;
+ lpr)
+ lpopts="$lpopts -P$printer"
+ ;;
+ *)
+ printf 'vgrind: unknown print program %s\n' $lp >&2
+ exit 1
+ ;;
+ esac
+fi
+
+# Implementation note: In the following, we use "eval" to execute the
+# command in order to preserve spaces which may appear in the -h option
+# argument (and possibly in file names).
+
+if [ $filter -eq 1 ] ; then
+ eval "$vfontedpr $args | cat $macros -"
+else
+ cmd="$vfontedpr $args"
+
+ if [ -r index ] ; then
+ # Removes any entries from the index that come from the files we are
+ # processing.
+
+ echo > nindex
+
+ for i in "$files" ; do
+ echo "? $i ?d" | sed -e "s:/:\\\/:g" -e "s:?:/:g" >> nindex
+ done
+
+ sed -f nindex index > xindex
+
+ # Now process the input.
+ # (! [$filter -eq 1])
+
+ trap "rm -f xindex nindex; exit 1" INT QUIT
+
+ cmd="$cmd | $troff -rx1 $troffopts -i $macros - 2>> xindex"
+
+ if [ $usedpost -eq 1 ] ; then
+ cmd="$cmd | $dpost $dpostopts"
+ fi
+
+ if [ $uselp -eq 1 ] ; then
+ cmd="$cmd | $lp $lpopts"
+ fi
+
+ eval $cmd
+ trap - INT QUIT
+ sort -dfu +0 -2 xindex > index
+ rm nindex xindex
+ else
+ # (! [ -r index ])
+
+ cmd="$cmd | $troff -i $troffopts $macros -"
+
+ if [ $usedpost -eq 1 ] ; then
+ cmd="$cmd | $dpost $dpostopts"
+ fi
+
+ if [ $uselp -eq 1 ] ; then
+ cmd="$cmd | $lp $lpopts"
+ fi
+
+ eval $cmd
+ fi
+fi
diff --git a/vgrind/vgrindefs.c b/vgrind/vgrindefs.c
new file mode 100644
index 0000000000000..560b45aab43ad
--- /dev/null
+++ b/vgrind/vgrindefs.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* from OpenSolaris "vgrindefs.c 1.10 92/07/21 SMI" */
+
+/*
+ * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
+ *
+ * Sccsid @(#)vgrindefs.c 1.3 (gritter) 10/22/05
+ */
+ /* from UCB 5.1 (Berkeley) 6/5/85 */
+
+#define BUFSIZ 1024
+#define MAXHOP 32 /* max number of tc= indirections */
+
+#include <ctype.h>
+#include <locale.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "global.h"
+
+/*
+ * grindcap - routines for dealing with the language definitions data base
+ * (code stolen almost totally from termcap)
+ *
+ * BUG: Should use a "last" pointer in tbuf, so that searching
+ * for capabilities alphabetically would not be a n**2/2
+ * process when large numbers of capabilities are given.
+ * Note: If we add a last pointer now we will screw up the
+ * tc capability. We really should compile termcap.
+ *
+ * Essentially all the work here is scanning and decoding escapes
+ * in string capabilities. We don't use stdio because the editor
+ * doesn't, and because living w/o it is not hard.
+ */
+
+static char *tbuf;
+static char *filename;
+static int hopcount; /* detect infinite loops in termcap, init 0 */
+
+static char *vgrind_msg;
+
+static int tnchktc(void);
+static int tnamatch(char *);
+static char *tskip(register char *);
+static char *tdecode(register char *, char **);
+
+/*
+ * Get an entry for terminal name in buffer bp,
+ * from the termcap file. Parse is very rudimentary;
+ * we just notice escaped newlines.
+ */
+int
+tgetent(char *bp, char *name, char *file)
+{
+ register char *cp;
+ register int c;
+ register int i = 0, cnt = 0;
+ char ibuf[BUFSIZ];
+ int tf;
+
+ tbuf = bp;
+ tf = 0;
+ filename = file;
+ tf = open(filename, O_RDONLY);
+ if (tf < 0)
+ return (-1);
+ for (;;) {
+ cp = bp;
+ for (;;) {
+ if (i == cnt) {
+ cnt = read(tf, ibuf, BUFSIZ);
+ if (cnt <= 0) {
+ close(tf);
+ return (0);
+ }
+ i = 0;
+ }
+ c = ibuf[i++];
+ if (c == '\n') {
+ if (cp > bp && cp[-1] == '\\'){
+ cp--;
+ continue;
+ }
+ break;
+ }
+ if (cp >= bp+BUFSIZ) {
+ vgrind_msg = "Vgrind entry too long\n";
+ write(2, vgrind_msg, strlen(vgrind_msg));
+ break;
+ } else
+ *cp++ = c;
+ }
+ *cp = 0;
+
+ /*
+ * The real work for the match.
+ */
+ if (tnamatch(name)) {
+ close(tf);
+ return(tnchktc());
+ }
+ }
+}
+
+/*
+ * tnchktc: check the last entry, see if it's tc=xxx. If so,
+ * recursively find xxx and append that entry (minus the names)
+ * to take the place of the tc=xxx entry. This allows termcap
+ * entries to say "like an HP2621 but doesn't turn on the labels".
+ * Note that this works because of the left to right scan.
+ */
+static int
+tnchktc(void)
+{
+ register char *p, *q;
+ char tcname[16]; /* name of similar terminal */
+ char tcbuf[BUFSIZ];
+ char *holdtbuf = tbuf;
+ int l;
+
+ p = tbuf + strlen(tbuf) - 2; /* before the last colon */
+ while (*--p != ':')
+ if (p<tbuf) {
+ vgrind_msg = "Bad vgrind entry\n";
+ write(2, vgrind_msg, strlen(vgrind_msg));
+ return (0);
+ }
+ p++;
+ /* p now points to beginning of last field */
+ if (p[0] != 't' || p[1] != 'c')
+ return(1);
+ n_strcpy(tcname, p+3, 16);
+ q = tcname;
+ while (q && *q != ':')
+ q++;
+ *q = 0;
+ if (++hopcount > MAXHOP) {
+ vgrind_msg = "Infinite tc= loop\n";
+ write(2, vgrind_msg, strlen(vgrind_msg));
+ return (0);
+ }
+ if (tgetent(tcbuf, tcname, filename) != 1)
+ return(0);
+ for (q=tcbuf; *q != ':'; q++)
+ ;
+ l = p - holdtbuf + strlen(q);
+ if (l > BUFSIZ) {
+ vgrind_msg = "Vgrind entry too long\n";
+ write(2, vgrind_msg, strlen(vgrind_msg));
+ q[BUFSIZ - (p-tbuf)] = 0;
+ }
+ n_strcpy(p, q+1, BUFSIZ - (p - holdtbuf));
+ tbuf = holdtbuf;
+ return(1);
+}
+
+/*
+ * Tnamatch deals with name matching. The first field of the termcap
+ * entry is a sequence of names separated by |'s, so we compare
+ * against each such name. The normal : terminator after the last
+ * name (before the first field) stops us.
+ */
+static int
+tnamatch(char *np)
+{
+ register char *Np, *Bp;
+
+ Bp = tbuf;
+ if (*Bp == '#')
+ return(0);
+ for (;;) {
+ for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
+ continue;
+ if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
+ return (1);
+ while (*Bp && *Bp != ':' && *Bp != '|')
+ Bp++;
+ if (*Bp == 0 || *Bp == ':')
+ return (0);
+ Bp++;
+ }
+}
+
+/*
+ * Skip to the next field. Notice that this is very dumb, not
+ * knowing about \: escapes or any such. If necessary, :'s can be put
+ * into the termcap file in octal.
+ */
+static char *
+tskip(register char *bp)
+{
+
+ while (*bp && *bp != ':')
+ bp++;
+ if (*bp == ':')
+ bp++;
+ return (bp);
+}
+
+/*
+ * Return the (numeric) option id.
+ * Numeric options look like
+ * li#80
+ * i.e. the option string is separated from the numeric value by
+ * a # character. If the option is not found we return -1.
+ * Note that we handle octal numbers beginning with 0.
+ */
+int
+tgetnum(char *id)
+{
+ register int i, base;
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = tskip(bp);
+ if (*bp == 0)
+ return (-1);
+ if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+ continue;
+ if (*bp == '@')
+ return(-1);
+ if (*bp != '#')
+ continue;
+ bp++;
+ base = 10;
+ if (*bp == '0')
+ base = 8;
+ i = 0;
+ while (isdigit((int)*bp))
+ i *= base, i += *bp++ - '0';
+ return (i);
+ }
+}
+
+/*
+ * Handle a flag option.
+ * Flag options are given "naked", i.e. followed by a : or the end
+ * of the buffer. Return 1 if we find the option, or 0 if it is
+ * not given.
+ */
+int
+tgetflag(char *id)
+{
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = tskip(bp);
+ if (!*bp)
+ return (0);
+ if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+ if (!*bp || *bp == ':')
+ return (1);
+ else if (*bp == '@')
+ return(0);
+ }
+ }
+}
+
+/*
+ * Get a string valued option.
+ * These are given as
+ * cl=^Z
+ * Much decoding is done on the strings, and the strings are
+ * placed in area, which is a ref parameter which is updated.
+ * No checking on area overflow.
+ */
+char *
+tgetstr(char *id, char **area)
+{
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = tskip(bp);
+ if (!*bp)
+ return (0);
+ if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+ continue;
+ if (*bp == '@')
+ return(0);
+ if (*bp != '=')
+ continue;
+ bp++;
+ return (tdecode(bp, area));
+ }
+}
+
+/*
+ * Tdecode does the grung work to decode the
+ * string capability escapes.
+ */
+static char *
+tdecode(register char *str, char **area)
+{
+ register char *cp;
+ register int c;
+
+ cp = *area;
+ while ((c = *str++)) {
+ if (c == ':' && *(cp-1) != '\\')
+ break;
+ *cp++ = c;
+ }
+ *cp++ = 0;
+ str = *area;
+ *area = cp;
+ return (str);
+}
diff --git a/vgrind/vgrindefs.src b/vgrind/vgrindefs.src
new file mode 100644
index 0000000000000..e6581f57fc8be
--- /dev/null
+++ b/vgrind/vgrindefs.src
@@ -0,0 +1,170 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# from OpenSolaris "vgrindefs.src 1.16 05/06/08 SMI"
+#
+# Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
+#
+# Sccsid @(#)vgrindefs.src 1.3 (gritter) 10/22/05
+#
+model|mod|m:\
+ :pb=^\d(space\d\p\drep)|(\p\dis|inline|public\dbeginproc):\
+ :bb=\dbeginproc|space|case\d:be=\dendproc|end\d|;:\
+ :cb=\$:ce=\$|$:sb=":se=":lb=':le=\a|$:\
+ :kw=abs and array beginproc boolean by case cdnl char copied dispose\
+ div do dynamic else elsif end endproc entry external FALSE false\
+ fi file for formal fortran global if iff ift\
+ in integer include inline is lbnd\
+ max min mod new NIL nil noresult not notin od of or procedure public\
+ read readln readonly record recursive rem rep repeat res\
+ result return set\
+ space string subscript such then TRUE true type ubnd union until\
+ varies while width:
+pascal|pasc|p:\
+ :pb=(^\d?procedure|function|program\d\p\d|\(|;|\:)|(=\d?record\d):\
+ :bb=\dcase|begin\d:be=\dend|forward\d|;:\
+ :cb={:ce=}:\
+ :ab=\(*:ae=*\):\
+ :sb=':se=':\
+ :kw=and array assert begin case const div do downto else end file for\
+ forward function goto if in label mod nil not of or packed procedure\
+ program record repeat set then to type until var while with oct hex\
+ external:
+C|c:\
+ :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:cb=/*:ce=*/:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=asm auto break case char continue default do double else enum\
+ extern float for fortran goto if int long register return short\
+ sizeof static struct switch typedef union unsigned void while #define\
+ #else #endif #if #ifdef #ifndef #include #undef # define endif\
+ ifdef ifndef include undef defined:
+ISP|isp|i:\
+ :cb=!:ce=!|$:oc:\
+ :kw=and begin decode define end eql eqv geq gtr if leave leq lss mod\
+ neq next not or otherwise repeat restart resume sr0 sr1 srd srr sl0 sl1\
+ sld slr tst xor:
+SH|sh:\
+ :pb=(;|^)\d?\p\(\)(\d|{):\
+ :ab=\$#:ae=(\d?|\a?):\
+ :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=break case cd continue do done \
+ elif else esac eval exec exit export \
+ fi for if in then while until \
+ read readonly set shift test trap umask wait:
+CSH|csh:\
+ :cb=#:ce=$:sb=":se=\e":lb=':\
+ :ab=\$\a?#:ae=(\d?|\a?):\
+ :le=\e':tl:\
+ :kw=alias alloc break breaksw case cd chdir continue default\
+ echo else end endif endsw exec exit foreach \
+ glob goto history if logout nice nohup onintr repeat set\
+ setenv shift source switch then time \
+ while umask unalias unset wait while @ env \
+ argv child home ignoreeof noclobber noglob \
+ nomatch path prompt shell status verbose :
+ldl|LDL:\
+ :pb=^\p\::bb=\::be=;:cb=/*:ce=*/:sb=":se=\e":\
+ :kw=constant functions grammar reswords tokens add1 addste\
+ car cdr check colno cond cons copy defun divide empty enter\
+ eq equal findattr firstchild ge getattr getfield gt hash label\
+ lambda lastchild le leftsibling lookone lookup lt minus name ne\
+ newnode nextcom nil null parent plus precnl prevcom prog progn\
+ quote reglob return rightsibling self set setattr setfield setq\
+ stjoin sub1 t times tnull tokno ttype:
+Icon|icon|I:\
+ :pb=^\d?procedure\d\p\d?\(\a?\):\
+ :bb=(^\d?procedure\d\p\d?\(\a?\))|{:be=}|(^\d?end\d?$):\
+ :cb=#:ce=$:\
+ :sb=":se=\e":lb=':le=\e':tl:\
+ :kw=break by case create default do dynamic else end every external\
+ fail global if initial local next not of procedure record\
+ repeat return static suspend then to until using while\
+ &ascii &clock &cset &date &dateline &errout &fail &host &input\
+ &lcase &level &main &null &output &pos &random &source &subject\
+ &time &trace &ucase &version:
+ratfor|rat|r:\
+ :pb=(subroutine|function)\d\p\d?\(\a?\):\
+ :bb=(subroutine|function)\d\p\d?\(\a?\):be=^\d?end:\
+ :cb=#:ce=$:\
+ :sb=":se=\e":lb=':le=\e':oc:\
+ :kw=DRETURN DRIVER arith break case character default define do\
+ else elsedef enddef filedes for function goto if ifdef ifelse\
+ ifnotdef include incr integer linepointer next opeq pointer\
+ real repeat return select string subroutine substr until:
+modula2|mod2|m2:\
+ :pb=(^\d?(procedure|function|module)\d\p\d|\(|;|\:):\
+ :bb=\d(begin|case|for|if|loop|record|repeat|while|with)\d:\
+ :be=\dend|;:\
+ :cb={:ce=}:\
+ :ab=\(*:ae=*\):\
+ :sb=":se=":\
+ :oc:\
+ :kw=and array begin by case const\
+ definition div do else elsif end exit export\
+ for from if implementation import in\
+ loop mod module not of or pointer procedure qualified\
+ record repeat return set then to type\
+ until var while with:
+yacc|Yacc|y:\
+ :cb=/*:ce=*/:sb=":se=\e":lb=':le=\e':tl:\
+ :kw=%{ %} %% %union %token %type\
+ #else #endif #if #ifdef #ifndef #include #undef # define else endif\
+ if ifdef ifndef include undef:
+C++|c++:\
+ :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:cb=/*:ce=*/:ab=//:\
+ :ae=$:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=asm auto break case char continue default do double else enum\
+ extern float for fortran goto if int long register return short\
+ sizeof static struct switch typedef union unsigned while void #define\
+ #else #endif #if #ifdef #ifndef #include #undef # define endif\
+ ifdef ifndef include undef defined\
+ class const delete friend inline new operator overload private\
+ protected public virtual:
+fortran|FORTRAN|f77|fc|f:\
+ :pb=(function|subroutine|program)\d\p\d?\(\a?\):\
+ :bb=(function|subroutine|program)\d\p\d?\(\a?\):be=^\dend:\
+ :cb=^c:\
+ :ce=$:\
+ :sb=':\
+ :se=':\
+ :oc:\
+ :kw=call common complex continue dimension do double else elseif\
+ end endif equivalence format function\
+ goto if include integer \
+ parameter precision real return stop subroutine:
+#
+# This entry makes use of new capabilities added to support the description
+# of lisp-like languages (id, pl, and px). The set of keywords given is a
+# matter of taste. It would be reasonable to add all the wired functions to
+# the list.
+MLisp|ml|Emacs Mock Lisp:\
+ :cb=;:ce=$:lb=':le=\e':sb=":se=\e":bb=\(:be=\):\
+ :id=_-$#@./,%&?!^*+~`|;<>'\::\
+ :kw=defun if progn while:pl:px=\d\(defun:pb=^\d\(\p($|(\d\a$)):
+#
+# It's not obvious what constitutes a "procedure definition" in Russell.
+# This entry doesn't even try...
+russell|Russell:\
+ :cb=\(*:ce=*\):kw=cand cor do od if fi else enum record prod union\
+ extend export hide with constants let use in ni val var func type\
+ field characters readonly:sb=":se=":lb=':le=':