xref: /illumos-gate/usr/src/cmd/vgrind/vfontedpr.c (revision 55fea89d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
37c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
47c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
57c478bd9Sstevel@tonic-gate  */
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate #include <ctype.h>
87c478bd9Sstevel@tonic-gate #include <stdio.h>
97c478bd9Sstevel@tonic-gate #include <sys/types.h>
107c478bd9Sstevel@tonic-gate #include <sys/stat.h>
117c478bd9Sstevel@tonic-gate #include <locale.h>
127c478bd9Sstevel@tonic-gate #include <euc.h>
137c478bd9Sstevel@tonic-gate #include <stdlib.h>
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #define boolean int
167c478bd9Sstevel@tonic-gate #define TRUE 1
177c478bd9Sstevel@tonic-gate #define FALSE 0
187c478bd9Sstevel@tonic-gate #define NIL 0
197c478bd9Sstevel@tonic-gate #define STANDARD 0
207c478bd9Sstevel@tonic-gate #define ALTERNATE 1
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Vfontedpr.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #define STRLEN 10		/* length of strings introducing things */
307c478bd9Sstevel@tonic-gate #define PNAMELEN 40		/* length of a function/procedure name */
317c478bd9Sstevel@tonic-gate #define PSMAX 20		/* size of procedure name stacking */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /* regular expression routines */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate char	*expmatch();		/* match a string to an expression */
367c478bd9Sstevel@tonic-gate char	*STRNCMP();		/* a different kind of strncmp */
377c478bd9Sstevel@tonic-gate char	*convexp();		/* convert expression to internal form */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate char	*tgetstr();		/* extract a string-valued capability */
407c478bd9Sstevel@tonic-gate boolean	isproc();
417c478bd9Sstevel@tonic-gate char	*ctime();
427c478bd9Sstevel@tonic-gate char	*strchr();
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  *	The state variables
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate boolean	incomm;			/* in a comment of the primary type */
497c478bd9Sstevel@tonic-gate boolean	instr;			/* in a string constant */
507c478bd9Sstevel@tonic-gate boolean	inchr;			/* in a string constant */
517c478bd9Sstevel@tonic-gate boolean	nokeyw = FALSE;		/* no keywords being flagged */
527c478bd9Sstevel@tonic-gate boolean	doindex = FALSE;	/* form an index */
537c478bd9Sstevel@tonic-gate boolean twocol = FALSE;		/* in two-column mode */
547c478bd9Sstevel@tonic-gate boolean	filter = FALSE;		/* act as a filter (like eqn) */
557c478bd9Sstevel@tonic-gate boolean	pass = FALSE;		/* when acting as a filter, pass indicates
567c478bd9Sstevel@tonic-gate 				 * whether we are currently processing
577c478bd9Sstevel@tonic-gate 				 * input.
587c478bd9Sstevel@tonic-gate 				 */
597c478bd9Sstevel@tonic-gate boolean	prccont;		/* continue last procedure */
607c478bd9Sstevel@tonic-gate int	comtype;		/* type of comment */
617c478bd9Sstevel@tonic-gate int	margin;
627c478bd9Sstevel@tonic-gate int	psptr;			/* the stack index of the current procedure */
637c478bd9Sstevel@tonic-gate char	pstack[PSMAX][PNAMELEN+1];	/* the procedure name stack */
647c478bd9Sstevel@tonic-gate int	plstack[PSMAX];		/* the procedure nesting level stack */
657c478bd9Sstevel@tonic-gate int	blklevel;		/* current nesting level */
667c478bd9Sstevel@tonic-gate int	prclevel;		/* nesting level at which procedure definitions
677c478bd9Sstevel@tonic-gate 				   may be found, -1 if none currently valid
687c478bd9Sstevel@tonic-gate 				   (meaningful only if l_prclevel is true) */
697c478bd9Sstevel@tonic-gate char	*defsfile = "/usr/lib/vgrindefs";	/* name of language definitions file */
707c478bd9Sstevel@tonic-gate char	pname[BUFSIZ+1];
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /*
737c478bd9Sstevel@tonic-gate  *	The language specific globals
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate char	*language = "c";	/* the language indicator */
777c478bd9Sstevel@tonic-gate char	*l_keywds[BUFSIZ/2];	/* keyword table address */
787c478bd9Sstevel@tonic-gate char	*l_prcbeg;		/* regular expr for procedure begin */
797c478bd9Sstevel@tonic-gate char	*l_combeg;		/* string introducing a comment */
807c478bd9Sstevel@tonic-gate char	*l_comend;		/* string ending a comment */
817c478bd9Sstevel@tonic-gate char	*l_acmbeg;		/* string introducing a comment */
827c478bd9Sstevel@tonic-gate char	*l_acmend;		/* string ending a comment */
837c478bd9Sstevel@tonic-gate char	*l_blkbeg;		/* string begining of a block */
847c478bd9Sstevel@tonic-gate char	*l_blkend;		/* string ending a block */
857c478bd9Sstevel@tonic-gate char	*l_strbeg;		/* delimiter for string constant */
867c478bd9Sstevel@tonic-gate char	*l_strend;		/* delimiter for string constant */
877c478bd9Sstevel@tonic-gate char	*l_chrbeg;		/* delimiter for character constant */
887c478bd9Sstevel@tonic-gate char	*l_chrend;		/* delimiter for character constant */
897c478bd9Sstevel@tonic-gate char	*l_prcenable;		/* re indicating that procedure definitions
907c478bd9Sstevel@tonic-gate 				   can be found in the next lexical level --
917c478bd9Sstevel@tonic-gate 				   kludge for lisp-like languages that use
927c478bd9Sstevel@tonic-gate 				   something like
937c478bd9Sstevel@tonic-gate 					   (defun (proc ...)
947c478bd9Sstevel@tonic-gate 					  	(proc ...)
957c478bd9Sstevel@tonic-gate 					   )
967c478bd9Sstevel@tonic-gate 				   to define procedures */
977c478bd9Sstevel@tonic-gate char	l_escape;		/* character used to  escape characters */
987c478bd9Sstevel@tonic-gate boolean	l_toplex;		/* procedures only defined at top lex level */
997c478bd9Sstevel@tonic-gate boolean l_prclevel;		/* procedure definitions valid only within
1007c478bd9Sstevel@tonic-gate 				   the nesting level indicated by the px
1017c478bd9Sstevel@tonic-gate 				   (l_prcenable) capability */
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  *  for the benefit of die-hards who aren't convinced that tabs
1057c478bd9Sstevel@tonic-gate  *  occur every eight columns
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate short tabsize = 8;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  *  global variables also used by expmatch
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate boolean	_escaped;		/* if last character was an escape */
1137c478bd9Sstevel@tonic-gate char	*Start;			/* start of the current string */
1147c478bd9Sstevel@tonic-gate boolean	l_onecase;		/* upper and lower case are equivalent */
1157c478bd9Sstevel@tonic-gate char	*l_idchars;		/* characters legal in identifiers in addition
1167c478bd9Sstevel@tonic-gate 				   to letters and digits (default "_") */
1177c478bd9Sstevel@tonic-gate 
118e5af7cceScraigm static void putcp(int c);
119e5af7cceScraigm static int width(char *s, char *os);
120e5af7cceScraigm static int tabs(char *s, char *os);
121e5af7cceScraigm static void putKcp(char *start, char *end, boolean force);
122e5af7cceScraigm static void putScp(char *os);
123e5af7cceScraigm static int iskw(char *s);
124e5af7cceScraigm 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * The code below emits troff macros and directives that consume part of the
1277c478bd9Sstevel@tonic-gate  * troff macro and register space.  See tmac.vgrind for an enumeration of
1287c478bd9Sstevel@tonic-gate  * these macros and registers.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate 
131e5af7cceScraigm int
main(int argc,char * argv[])132e5af7cceScraigm main(int argc, char *argv[])
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate     FILE *in;
1357c478bd9Sstevel@tonic-gate     char *fname;
1367c478bd9Sstevel@tonic-gate     struct stat stbuf;
1377c478bd9Sstevel@tonic-gate     char buf[BUFSIZ];
1387c478bd9Sstevel@tonic-gate     char idbuf[256];	/* enough for all 8 bit chars */
1397c478bd9Sstevel@tonic-gate     char strings[2 * BUFSIZ];
1407c478bd9Sstevel@tonic-gate     char defs[2 * BUFSIZ];
1417c478bd9Sstevel@tonic-gate     int needbp = 0;
1427c478bd9Sstevel@tonic-gate     int i;
1437c478bd9Sstevel@tonic-gate     char *cp;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1467c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1477c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
1487c478bd9Sstevel@tonic-gate #endif
1497c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate     /*
1527c478bd9Sstevel@tonic-gate      * Dump the name by which we were invoked.
1537c478bd9Sstevel@tonic-gate      */
1547c478bd9Sstevel@tonic-gate     argc--, argv++;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate     /*
1577c478bd9Sstevel@tonic-gate      * Process arguments.  For the sake of compatibility with older versions
1587c478bd9Sstevel@tonic-gate      * of the program, the syntax accepted below is very idiosyncratic.  Some
1597c478bd9Sstevel@tonic-gate      * options require space between the option and its argument; others
1607c478bd9Sstevel@tonic-gate      * disallow it.  No options may be bundled together.
1617c478bd9Sstevel@tonic-gate      *
1627c478bd9Sstevel@tonic-gate      * Actually, there is one incompatibility.  Files and options formerly
1637c478bd9Sstevel@tonic-gate      * could be arbitrarily intermixed, but this is no longer allowed.  (This
1647c478bd9Sstevel@tonic-gate      * possiblity was never documented.)
1657c478bd9Sstevel@tonic-gate      */
1667c478bd9Sstevel@tonic-gate     while (argc > 0 && *argv[0] == '-') {
1677c478bd9Sstevel@tonic-gate 	switch (*(cp = argv[0] + 1)) {
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	case '\0':				/* - */
1707c478bd9Sstevel@tonic-gate 	    /* Take input from stdin. */
171*55fea89dSDan Cross 	    /*
1727c478bd9Sstevel@tonic-gate 	     * This option implies the end of the flag arguments.  Leave the
1737c478bd9Sstevel@tonic-gate 	     * "-" in place for the file processing code to see.
1747c478bd9Sstevel@tonic-gate 	     */
1757c478bd9Sstevel@tonic-gate 	    goto flagsdone;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	case '2':				/* -2 */
1787c478bd9Sstevel@tonic-gate 	    /* Enter two column mode. */
1797c478bd9Sstevel@tonic-gate 	    twocol = 1;
1807c478bd9Sstevel@tonic-gate 	    printf("'nr =2 1\n");
1817c478bd9Sstevel@tonic-gate 	    break;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	case 'd':				/* -d <defs-file> */
1847c478bd9Sstevel@tonic-gate 	    /* Specify the language description file. */
1857c478bd9Sstevel@tonic-gate 	    defsfile = argv[1];
1867c478bd9Sstevel@tonic-gate 	    argc--, argv++;
1877c478bd9Sstevel@tonic-gate 	    break;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	case 'f':				/* -f */
1907c478bd9Sstevel@tonic-gate 	    /* Act as a filter like eqn. */
1917c478bd9Sstevel@tonic-gate 	    filter = 1;
192*55fea89dSDan Cross 	    /*
1937c478bd9Sstevel@tonic-gate 	     * Slide remaining arguments down one position and postpend "-",
1947c478bd9Sstevel@tonic-gate 	     * to force reading from stdin.
1957c478bd9Sstevel@tonic-gate 	     */
1967c478bd9Sstevel@tonic-gate 	    for (i = 0; i < argc - 1; i++)
197*55fea89dSDan Cross 		argv[i] = argv[i + 1];
1987c478bd9Sstevel@tonic-gate 	    argv[argc - 1] = "-";
1997c478bd9Sstevel@tonic-gate 	    continue;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	case 'h':				/* -h [header] */
2027c478bd9Sstevel@tonic-gate 	    /* Specify header string. */
2037c478bd9Sstevel@tonic-gate 	    if (argc == 1) {
2047c478bd9Sstevel@tonic-gate 		printf("'ds =H\n");
2057c478bd9Sstevel@tonic-gate 		break;
2067c478bd9Sstevel@tonic-gate 	    }
2077c478bd9Sstevel@tonic-gate 	    printf("'ds =H %s\n", argv[1]);
2087c478bd9Sstevel@tonic-gate 	    argc--, argv++;
2097c478bd9Sstevel@tonic-gate 	    break;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	case 'l':				/* -l<language> */
2127c478bd9Sstevel@tonic-gate 	    /* Specify the language. */
2137c478bd9Sstevel@tonic-gate 	    language = cp + 1;
2147c478bd9Sstevel@tonic-gate 	    break;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	case 'n':				/* -n */
2177c478bd9Sstevel@tonic-gate 	    /* Indicate no keywords. */
2187c478bd9Sstevel@tonic-gate 	    nokeyw = 1;
2197c478bd9Sstevel@tonic-gate 	    break;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	case 's':				/* -s<size> */
2227c478bd9Sstevel@tonic-gate 	    /* Specify the font size. */
2237c478bd9Sstevel@tonic-gate 	    i = 0;
2247c478bd9Sstevel@tonic-gate 	    cp++;
2257c478bd9Sstevel@tonic-gate 	    while (*cp)
2267c478bd9Sstevel@tonic-gate 		i = i * 10 + (*cp++ - '0');
2277c478bd9Sstevel@tonic-gate 	    printf("'nr vP %d\n", i);
2287c478bd9Sstevel@tonic-gate 	    break;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	case 't':				/* -t */
2317c478bd9Sstevel@tonic-gate 	    /* Specify a nondefault tab size. */
2327c478bd9Sstevel@tonic-gate 	    tabsize = 4;
2337c478bd9Sstevel@tonic-gate 	    break;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	case 'x':				/* -x */
2367c478bd9Sstevel@tonic-gate 	    /* Build an index. */
2377c478bd9Sstevel@tonic-gate 	    doindex = 1;
2387c478bd9Sstevel@tonic-gate 	    /* This option implies "-n" as well; turn it on. */
2397c478bd9Sstevel@tonic-gate 	    argv[0] = "-n";
2407c478bd9Sstevel@tonic-gate 	    continue;
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	/* Advance to next argument. */
2447c478bd9Sstevel@tonic-gate 	argc--, argv++;
2457c478bd9Sstevel@tonic-gate     }
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate flagsdone:
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate     /*
2507c478bd9Sstevel@tonic-gate      * Get the language definition from the defs file.
2517c478bd9Sstevel@tonic-gate      */
2527c478bd9Sstevel@tonic-gate     i = tgetent (defs, language, defsfile);
2537c478bd9Sstevel@tonic-gate     if (i == 0) {
2547c478bd9Sstevel@tonic-gate 	fprintf (stderr, gettext("no entry for language %s\n"), language);
2557c478bd9Sstevel@tonic-gate 	exit (0);
2567c478bd9Sstevel@tonic-gate     } else  if (i < 0) {
2577c478bd9Sstevel@tonic-gate 	fprintf (stderr,  gettext("cannot find vgrindefs file %s\n"), defsfile);
2587c478bd9Sstevel@tonic-gate 	exit (0);
2597c478bd9Sstevel@tonic-gate     }
2607c478bd9Sstevel@tonic-gate     cp = strings;
2617c478bd9Sstevel@tonic-gate     if (tgetstr ("kw", &cp) == NIL)
2627c478bd9Sstevel@tonic-gate 	nokeyw = TRUE;
2637c478bd9Sstevel@tonic-gate     else  {
2647c478bd9Sstevel@tonic-gate 	char **cpp;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	cpp = l_keywds;
2677c478bd9Sstevel@tonic-gate 	cp = strings;
2687c478bd9Sstevel@tonic-gate 	while (*cp) {
2697c478bd9Sstevel@tonic-gate 	    while (*cp == ' ' || *cp =='\t')
270e8bca4eaSToomas Soome 		*cp++ = '\0';
2717c478bd9Sstevel@tonic-gate 	    if (*cp)
2727c478bd9Sstevel@tonic-gate 		*cpp++ = cp;
2737c478bd9Sstevel@tonic-gate 	    while (*cp != ' ' && *cp  != '\t' && *cp)
2747c478bd9Sstevel@tonic-gate 		cp++;
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 	*cpp = NIL;
2777c478bd9Sstevel@tonic-gate     }
2787c478bd9Sstevel@tonic-gate     cp = buf;
2797c478bd9Sstevel@tonic-gate     l_prcbeg = convexp (tgetstr ("pb", &cp));
2807c478bd9Sstevel@tonic-gate     cp = buf;
2817c478bd9Sstevel@tonic-gate     l_combeg = convexp (tgetstr ("cb", &cp));
2827c478bd9Sstevel@tonic-gate     cp = buf;
2837c478bd9Sstevel@tonic-gate     l_comend = convexp (tgetstr ("ce", &cp));
2847c478bd9Sstevel@tonic-gate     cp = buf;
2857c478bd9Sstevel@tonic-gate     l_acmbeg = convexp (tgetstr ("ab", &cp));
2867c478bd9Sstevel@tonic-gate     cp = buf;
2877c478bd9Sstevel@tonic-gate     l_acmend = convexp (tgetstr ("ae", &cp));
2887c478bd9Sstevel@tonic-gate     cp = buf;
2897c478bd9Sstevel@tonic-gate     l_strbeg = convexp (tgetstr ("sb", &cp));
2907c478bd9Sstevel@tonic-gate     cp = buf;
2917c478bd9Sstevel@tonic-gate     l_strend = convexp (tgetstr ("se", &cp));
2927c478bd9Sstevel@tonic-gate     cp = buf;
2937c478bd9Sstevel@tonic-gate     l_blkbeg = convexp (tgetstr ("bb", &cp));
2947c478bd9Sstevel@tonic-gate     cp = buf;
2957c478bd9Sstevel@tonic-gate     l_blkend = convexp (tgetstr ("be", &cp));
2967c478bd9Sstevel@tonic-gate     cp = buf;
2977c478bd9Sstevel@tonic-gate     l_chrbeg = convexp (tgetstr ("lb", &cp));
2987c478bd9Sstevel@tonic-gate     cp = buf;
2997c478bd9Sstevel@tonic-gate     l_chrend = convexp (tgetstr ("le", &cp));
3007c478bd9Sstevel@tonic-gate     cp = buf;
3017c478bd9Sstevel@tonic-gate     l_prcenable = convexp (tgetstr ("px", &cp));
3027c478bd9Sstevel@tonic-gate     cp = idbuf;
3037c478bd9Sstevel@tonic-gate     l_idchars = tgetstr ("id", &cp);
3047c478bd9Sstevel@tonic-gate     /* Set default, for compatibility with old version */
3057c478bd9Sstevel@tonic-gate     if (l_idchars == NIL)
3067c478bd9Sstevel@tonic-gate 	l_idchars = "_";
3077c478bd9Sstevel@tonic-gate     l_escape = '\\';
3087c478bd9Sstevel@tonic-gate     l_onecase = tgetflag ("oc");
3097c478bd9Sstevel@tonic-gate     l_toplex = tgetflag ("tl");
3107c478bd9Sstevel@tonic-gate     l_prclevel = tgetflag ("pl");
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate     /*
3137c478bd9Sstevel@tonic-gate      * Emit a call to the initialization macro.  If not in filter mode, emit a
3147c478bd9Sstevel@tonic-gate      * call to the vS macro, so that tmac.vgrind can uniformly assume that all
3157c478bd9Sstevel@tonic-gate      * program input is bracketed with vS-vE pairs.
3167c478bd9Sstevel@tonic-gate      */
3177c478bd9Sstevel@tonic-gate     printf("'vI\n");
3187c478bd9Sstevel@tonic-gate     if (!filter)
3197c478bd9Sstevel@tonic-gate 	printf("'vS\n");
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate     if (doindex) {
3227c478bd9Sstevel@tonic-gate 	/*
3237c478bd9Sstevel@tonic-gate 	 * XXX:	Hard-wired spacing information.  This should probably turn
3247c478bd9Sstevel@tonic-gate 	 *	into the emission of a macro invocation, so that tmac.vgrind
3257c478bd9Sstevel@tonic-gate 	 *	can make up its own mind about what spacing is appropriate.
3267c478bd9Sstevel@tonic-gate 	 */
3277c478bd9Sstevel@tonic-gate 	if (twocol)
3287c478bd9Sstevel@tonic-gate 	    printf("'ta 2.5i 2.75i 4.0iR\n'in .25i\n");
3297c478bd9Sstevel@tonic-gate 	else
3307c478bd9Sstevel@tonic-gate 	    printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
3317c478bd9Sstevel@tonic-gate     }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate     while (argc > 0) {
3347c478bd9Sstevel@tonic-gate 	if (strcmp(argv[0], "-") == 0) {
3357c478bd9Sstevel@tonic-gate 	    /* Embed an instance of the original stdin. */
3367c478bd9Sstevel@tonic-gate 	    in = fdopen(fileno(stdin), "r");
3377c478bd9Sstevel@tonic-gate 	    fname = "";
3387c478bd9Sstevel@tonic-gate 	} else {
3397c478bd9Sstevel@tonic-gate 	    /* Open the file for input. */
3407c478bd9Sstevel@tonic-gate 	    if ((in = fopen(argv[0], "r")) == NULL) {
3417c478bd9Sstevel@tonic-gate 		perror(argv[0]);
3427c478bd9Sstevel@tonic-gate 		exit(1);
3437c478bd9Sstevel@tonic-gate 	    }
3447c478bd9Sstevel@tonic-gate 	    fname = argv[0];
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate 	argc--, argv++;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/*
3497c478bd9Sstevel@tonic-gate 	 * Reinitialize for the current file.
3507c478bd9Sstevel@tonic-gate 	 */
3517c478bd9Sstevel@tonic-gate 	incomm = FALSE;
3527c478bd9Sstevel@tonic-gate 	instr = FALSE;
3537c478bd9Sstevel@tonic-gate 	inchr = FALSE;
3547c478bd9Sstevel@tonic-gate 	_escaped = FALSE;
3557c478bd9Sstevel@tonic-gate 	blklevel = 0;
3567c478bd9Sstevel@tonic-gate 	prclevel = -1;
3577c478bd9Sstevel@tonic-gate 	for (psptr=0; psptr<PSMAX; psptr++) {
358e8bca4eaSToomas Soome 	    pstack[psptr][0] = '\0';
3597c478bd9Sstevel@tonic-gate 	    plstack[psptr] = 0;
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 	psptr = -1;
3627c478bd9Sstevel@tonic-gate 	printf("'-F\n");
3637c478bd9Sstevel@tonic-gate 	if (!filter) {
3647c478bd9Sstevel@tonic-gate 	    char *cp;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	    printf(".ds =F %s\n", fname);
3677c478bd9Sstevel@tonic-gate 	    if (needbp) {
3687c478bd9Sstevel@tonic-gate 		needbp = 0;
3697c478bd9Sstevel@tonic-gate 		printf(".()\n");
3707c478bd9Sstevel@tonic-gate 		printf(".bp\n");
3717c478bd9Sstevel@tonic-gate 	    }
3727c478bd9Sstevel@tonic-gate 	    fstat(fileno(in), &stbuf);
3737c478bd9Sstevel@tonic-gate 	    cp = ctime(&stbuf.st_mtime);
3747c478bd9Sstevel@tonic-gate 	    cp[16] = '\0';
3757c478bd9Sstevel@tonic-gate 	    cp[24] = '\0';
3767c478bd9Sstevel@tonic-gate 	    printf(".ds =M %s %s\n", cp+4, cp+20);
3777c478bd9Sstevel@tonic-gate 	    printf("'wh 0 vH\n");
3787c478bd9Sstevel@tonic-gate 	    printf("'wh -1i vF\n");
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 	if (needbp && filter) {
3817c478bd9Sstevel@tonic-gate 	    needbp = 0;
3827c478bd9Sstevel@tonic-gate 	    printf(".()\n");
3837c478bd9Sstevel@tonic-gate 	    printf(".bp\n");
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	/*
3877c478bd9Sstevel@tonic-gate 	 *	MAIN LOOP!!!
3887c478bd9Sstevel@tonic-gate 	 */
3897c478bd9Sstevel@tonic-gate 	while (fgets(buf, sizeof buf, in) != NULL) {
3907c478bd9Sstevel@tonic-gate 	    if (buf[0] == '\f') {
3917c478bd9Sstevel@tonic-gate 		printf(".bp\n");
3927c478bd9Sstevel@tonic-gate 	    }
3937c478bd9Sstevel@tonic-gate 	    if (buf[0] == '.') {
3947c478bd9Sstevel@tonic-gate 		printf("%s", buf);
3957c478bd9Sstevel@tonic-gate 		if (!strncmp (buf+1, "vS", 2))
3967c478bd9Sstevel@tonic-gate 		    pass = TRUE;
3977c478bd9Sstevel@tonic-gate 		if (!strncmp (buf+1, "vE", 2))
3987c478bd9Sstevel@tonic-gate 		    pass = FALSE;
3997c478bd9Sstevel@tonic-gate 		continue;
4007c478bd9Sstevel@tonic-gate 	    }
4017c478bd9Sstevel@tonic-gate 	    prccont = FALSE;
4027c478bd9Sstevel@tonic-gate 	    if (!filter || pass)
4037c478bd9Sstevel@tonic-gate 		putScp(buf);
4047c478bd9Sstevel@tonic-gate 	    else
4057c478bd9Sstevel@tonic-gate 		printf("%s", buf);
4067c478bd9Sstevel@tonic-gate 	    if (prccont && (psptr >= 0))
4077c478bd9Sstevel@tonic-gate 		printf("'FC %s\n", pstack[psptr]);
4087c478bd9Sstevel@tonic-gate #ifdef DEBUG
4097c478bd9Sstevel@tonic-gate 	    printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
4107c478bd9Sstevel@tonic-gate #endif
4117c478bd9Sstevel@tonic-gate 	    margin = 0;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	needbp = 1;
4157c478bd9Sstevel@tonic-gate 	(void) fclose(in);
4167c478bd9Sstevel@tonic-gate     }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate     /* Close off the vS-vE pair. */
4197c478bd9Sstevel@tonic-gate     if (!filter)
4207c478bd9Sstevel@tonic-gate 	printf("'vE\n");
4217c478bd9Sstevel@tonic-gate 
422e5af7cceScraigm     return (0);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate #define isidchr(c) (isalnum(c) || ((c) != NIL && strchr(l_idchars, (c)) != NIL))
4267c478bd9Sstevel@tonic-gate 
427e5af7cceScraigm static void
putScp(char * os)428e5af7cceScraigm putScp(char *os)
4297c478bd9Sstevel@tonic-gate {
430e5af7cceScraigm     char *s = os;			/* pointer to unmatched string */
4317c478bd9Sstevel@tonic-gate     char dummy[BUFSIZ];			/* dummy to be used by expmatch */
4327c478bd9Sstevel@tonic-gate     char *comptr;			/* end of a comment delimiter */
4337c478bd9Sstevel@tonic-gate     char *acmptr;			/* end of a comment delimiter */
4347c478bd9Sstevel@tonic-gate     char *strptr;			/* end of a string delimiter */
4357c478bd9Sstevel@tonic-gate     char *chrptr;			/* end of a character const delimiter */
4367c478bd9Sstevel@tonic-gate     char *blksptr;			/* end of a lexical block start */
4377c478bd9Sstevel@tonic-gate     char *blkeptr;			/* end of a lexical block end */
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate     Start = os;			/* remember the start for expmatch */
4407c478bd9Sstevel@tonic-gate     _escaped = FALSE;
4417c478bd9Sstevel@tonic-gate     if (nokeyw || incomm || instr)
4427c478bd9Sstevel@tonic-gate 	goto skip;
4437c478bd9Sstevel@tonic-gate     if (isproc(s)) {
4447c478bd9Sstevel@tonic-gate 	printf("'FN %s\n", pname);
4457c478bd9Sstevel@tonic-gate 	if (psptr < PSMAX-1) {
4467c478bd9Sstevel@tonic-gate 	    ++psptr;
4477c478bd9Sstevel@tonic-gate 	    strncpy (pstack[psptr], pname, PNAMELEN);
448e8bca4eaSToomas Soome 	    pstack[psptr][PNAMELEN] = '\0';
4497c478bd9Sstevel@tonic-gate 	    plstack[psptr] = blklevel;
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate     }
4527c478bd9Sstevel@tonic-gate     /*
4537c478bd9Sstevel@tonic-gate      * if l_prclevel is set, check to see whether this lexical level
4547c478bd9Sstevel@tonic-gate      * is one immediately below which procedure definitions are allowed.
4557c478bd9Sstevel@tonic-gate      */
4567c478bd9Sstevel@tonic-gate     if (l_prclevel && !incomm && !instr && !inchr) {
4577c478bd9Sstevel@tonic-gate 	if (expmatch (s, l_prcenable, dummy) != NIL)
4587c478bd9Sstevel@tonic-gate 	    prclevel = blklevel + 1;
4597c478bd9Sstevel@tonic-gate     }
4607c478bd9Sstevel@tonic-gate skip:
4617c478bd9Sstevel@tonic-gate     do {
4627c478bd9Sstevel@tonic-gate 	/* check for string, comment, blockstart, etc */
4637c478bd9Sstevel@tonic-gate 	if (!incomm && !instr && !inchr) {
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	    blkeptr = expmatch (s, l_blkend, dummy);
4667c478bd9Sstevel@tonic-gate 	    blksptr = expmatch (s, l_blkbeg, dummy);
4677c478bd9Sstevel@tonic-gate 	    comptr = expmatch (s, l_combeg, dummy);
4687c478bd9Sstevel@tonic-gate 	    acmptr = expmatch (s, l_acmbeg, dummy);
4697c478bd9Sstevel@tonic-gate 	    strptr = expmatch (s, l_strbeg, dummy);
4707c478bd9Sstevel@tonic-gate 	    chrptr = expmatch (s, l_chrbeg, dummy);
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	    /* start of a comment? */
4737c478bd9Sstevel@tonic-gate 	    if (comptr != NIL)
4747c478bd9Sstevel@tonic-gate 		if ((comptr < strptr || strptr == NIL)
4757c478bd9Sstevel@tonic-gate 		  && (comptr < acmptr || acmptr == NIL)
4767c478bd9Sstevel@tonic-gate 		  && (comptr < chrptr || chrptr == NIL)
4777c478bd9Sstevel@tonic-gate 		  && (comptr < blksptr || blksptr == NIL)
4787c478bd9Sstevel@tonic-gate 		  && (comptr < blkeptr || blkeptr == NIL)) {
4797c478bd9Sstevel@tonic-gate 		    putKcp (s, comptr-1, FALSE);
4807c478bd9Sstevel@tonic-gate 		    s = comptr;
4817c478bd9Sstevel@tonic-gate 		    incomm = TRUE;
4827c478bd9Sstevel@tonic-gate 		    comtype = STANDARD;
4837c478bd9Sstevel@tonic-gate 		    if (s != os)
4847c478bd9Sstevel@tonic-gate 			printf ("\\c");
4857c478bd9Sstevel@tonic-gate 		    printf ("\\c\n'+C\n");
4867c478bd9Sstevel@tonic-gate 		    continue;
4877c478bd9Sstevel@tonic-gate 		}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	    /* start of a comment? */
4907c478bd9Sstevel@tonic-gate 	    if (acmptr != NIL)
4917c478bd9Sstevel@tonic-gate 		if ((acmptr < strptr || strptr == NIL)
4927c478bd9Sstevel@tonic-gate 		  && (acmptr < chrptr || chrptr == NIL)
4937c478bd9Sstevel@tonic-gate 		  && (acmptr < blksptr || blksptr == NIL)
4947c478bd9Sstevel@tonic-gate 		  && (acmptr < blkeptr || blkeptr == NIL)) {
4957c478bd9Sstevel@tonic-gate 		    putKcp (s, acmptr-1, FALSE);
4967c478bd9Sstevel@tonic-gate 		    s = acmptr;
4977c478bd9Sstevel@tonic-gate 		    incomm = TRUE;
4987c478bd9Sstevel@tonic-gate 		    comtype = ALTERNATE;
4997c478bd9Sstevel@tonic-gate 		    if (s != os)
5007c478bd9Sstevel@tonic-gate 			printf ("\\c");
5017c478bd9Sstevel@tonic-gate 		    printf ("\\c\n'+C\n");
5027c478bd9Sstevel@tonic-gate 		    continue;
5037c478bd9Sstevel@tonic-gate 		}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	    /* start of a string? */
5067c478bd9Sstevel@tonic-gate 	    if (strptr != NIL)
5077c478bd9Sstevel@tonic-gate 		if ((strptr < chrptr || chrptr == NIL)
5087c478bd9Sstevel@tonic-gate 		  && (strptr < blksptr || blksptr == NIL)
5097c478bd9Sstevel@tonic-gate 		  && (strptr < blkeptr || blkeptr == NIL)) {
5107c478bd9Sstevel@tonic-gate 		    putKcp (s, strptr-1, FALSE);
5117c478bd9Sstevel@tonic-gate 		    s = strptr;
5127c478bd9Sstevel@tonic-gate 		    instr = TRUE;
5137c478bd9Sstevel@tonic-gate 		    continue;
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	    /* start of a character string? */
5177c478bd9Sstevel@tonic-gate 	    if (chrptr != NIL)
5187c478bd9Sstevel@tonic-gate 		if ((chrptr < blksptr || blksptr == NIL)
5197c478bd9Sstevel@tonic-gate 		  && (chrptr < blkeptr || blkeptr == NIL)) {
5207c478bd9Sstevel@tonic-gate 		    putKcp (s, chrptr-1, FALSE);
5217c478bd9Sstevel@tonic-gate 		    s = chrptr;
5227c478bd9Sstevel@tonic-gate 		    inchr = TRUE;
5237c478bd9Sstevel@tonic-gate 		    continue;
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	    /* end of a lexical block */
5277c478bd9Sstevel@tonic-gate 	    if (blkeptr != NIL) {
5287c478bd9Sstevel@tonic-gate 		if (blkeptr < blksptr || blksptr == NIL) {
5297c478bd9Sstevel@tonic-gate 		    /* reset prclevel if necessary */
5307c478bd9Sstevel@tonic-gate 		    if (l_prclevel && prclevel == blklevel)
5317c478bd9Sstevel@tonic-gate 			prclevel = -1;
5327c478bd9Sstevel@tonic-gate 		    putKcp (s, blkeptr - 1, FALSE);
5337c478bd9Sstevel@tonic-gate 		    s = blkeptr;
5347c478bd9Sstevel@tonic-gate 		    blklevel--;
5357c478bd9Sstevel@tonic-gate 		    if (psptr >= 0 && plstack[psptr] >= blklevel) {
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 			/* end of current procedure */
5387c478bd9Sstevel@tonic-gate 			if (s != os)
5397c478bd9Sstevel@tonic-gate 			    printf ("\\c");
5407c478bd9Sstevel@tonic-gate 			printf ("\\c\n'-F\n");
5417c478bd9Sstevel@tonic-gate 			blklevel = plstack[psptr];
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 			/* see if we should print the last proc name */
5447c478bd9Sstevel@tonic-gate 			if (--psptr >= 0)
5457c478bd9Sstevel@tonic-gate 			    prccont = TRUE;
5467c478bd9Sstevel@tonic-gate 			else
5477c478bd9Sstevel@tonic-gate 			    psptr = -1;
5487c478bd9Sstevel@tonic-gate 		    }
5497c478bd9Sstevel@tonic-gate 		    continue;
5507c478bd9Sstevel@tonic-gate 		}
5517c478bd9Sstevel@tonic-gate 	    }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	    /* start of a lexical block */
5547c478bd9Sstevel@tonic-gate 	    if (blksptr != NIL) {
5557c478bd9Sstevel@tonic-gate 		putKcp (s, blksptr - 1, FALSE);
5567c478bd9Sstevel@tonic-gate 		s = blksptr;
5577c478bd9Sstevel@tonic-gate 		blklevel++;
5587c478bd9Sstevel@tonic-gate 		continue;
5597c478bd9Sstevel@tonic-gate 	    }
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	/* check for end of comment */
5627c478bd9Sstevel@tonic-gate 	} else if (incomm) {
5637c478bd9Sstevel@tonic-gate 	    comptr = expmatch (s, l_comend, dummy);
5647c478bd9Sstevel@tonic-gate 	    acmptr = expmatch (s, l_acmend, dummy);
5657c478bd9Sstevel@tonic-gate 	    if (((comtype == STANDARD) && (comptr != NIL)) ||
5667c478bd9Sstevel@tonic-gate 	        ((comtype == ALTERNATE) && (acmptr != NIL))) {
5677c478bd9Sstevel@tonic-gate 		if (comtype == STANDARD) {
5687c478bd9Sstevel@tonic-gate 		    putKcp (s, comptr-1, TRUE);
5697c478bd9Sstevel@tonic-gate 		    s = comptr;
5707c478bd9Sstevel@tonic-gate 		} else {
5717c478bd9Sstevel@tonic-gate 		    putKcp (s, acmptr-1, TRUE);
5727c478bd9Sstevel@tonic-gate 		    s = acmptr;
5737c478bd9Sstevel@tonic-gate 		}
5747c478bd9Sstevel@tonic-gate 		incomm = FALSE;
5757c478bd9Sstevel@tonic-gate 		printf("\\c\n'-C\n");
5767c478bd9Sstevel@tonic-gate 		continue;
5777c478bd9Sstevel@tonic-gate 	    } else {
5787c478bd9Sstevel@tonic-gate 		putKcp (s, s + strlen(s) -1, TRUE);
5797c478bd9Sstevel@tonic-gate 		s = s + strlen(s);
5807c478bd9Sstevel@tonic-gate 		continue;
5817c478bd9Sstevel@tonic-gate 	    }
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	/* check for end of string */
5847c478bd9Sstevel@tonic-gate 	} else if (instr) {
5857c478bd9Sstevel@tonic-gate 	    if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
5867c478bd9Sstevel@tonic-gate 		putKcp (s, strptr-1, TRUE);
5877c478bd9Sstevel@tonic-gate 		s = strptr;
5887c478bd9Sstevel@tonic-gate 		instr = FALSE;
5897c478bd9Sstevel@tonic-gate 		continue;
5907c478bd9Sstevel@tonic-gate 	    } else {
5917c478bd9Sstevel@tonic-gate 		putKcp (s, s+strlen(s)-1, TRUE);
5927c478bd9Sstevel@tonic-gate 		s = s + strlen(s);
5937c478bd9Sstevel@tonic-gate 		continue;
5947c478bd9Sstevel@tonic-gate 	    }
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/* check for end of character string */
5977c478bd9Sstevel@tonic-gate 	} else if (inchr) {
5987c478bd9Sstevel@tonic-gate 	    if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) {
5997c478bd9Sstevel@tonic-gate 		putKcp (s, chrptr-1, TRUE);
6007c478bd9Sstevel@tonic-gate 		s = chrptr;
6017c478bd9Sstevel@tonic-gate 		inchr = FALSE;
6027c478bd9Sstevel@tonic-gate 		continue;
6037c478bd9Sstevel@tonic-gate 	    } else {
6047c478bd9Sstevel@tonic-gate 		putKcp (s, s+strlen(s)-1, TRUE);
6057c478bd9Sstevel@tonic-gate 		s = s + strlen(s);
6067c478bd9Sstevel@tonic-gate 		continue;
6077c478bd9Sstevel@tonic-gate 	    }
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/* print out the line */
6117c478bd9Sstevel@tonic-gate 	putKcp (s, s + strlen(s) -1, FALSE);
6127c478bd9Sstevel@tonic-gate 	s = s + strlen(s);
6137c478bd9Sstevel@tonic-gate     } while (*s);
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate 
616e5af7cceScraigm static void
putKcp(char * start,char * end,boolean force)617e5af7cceScraigm putKcp(char *start, char *end, boolean force)
618e5af7cceScraigm 	/* start - start of string to write */
619e5af7cceScraigm 	/* end - end of string to write */
620e5af7cceScraigm 	/* force - true if we should force nokeyw */
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate     int i;
6237c478bd9Sstevel@tonic-gate     int xfld = 0;
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate     while (start <= end) {
6267c478bd9Sstevel@tonic-gate 	if (doindex) {
6277c478bd9Sstevel@tonic-gate 	    if (*start == ' ' || *start == '\t') {
628*55fea89dSDan Cross 		if (xfld == 0)
6297c478bd9Sstevel@tonic-gate 		    printf("");
6307c478bd9Sstevel@tonic-gate 		printf("\t");
6317c478bd9Sstevel@tonic-gate 		xfld = 1;
6327c478bd9Sstevel@tonic-gate 		while (*start == ' ' || *start == '\t')
6337c478bd9Sstevel@tonic-gate 		    start++;
6347c478bd9Sstevel@tonic-gate 		continue;
6357c478bd9Sstevel@tonic-gate 	    }
6367c478bd9Sstevel@tonic-gate 	}
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	/* take care of nice tab stops */
6397c478bd9Sstevel@tonic-gate 	if (*start == '\t') {
6407c478bd9Sstevel@tonic-gate 	    while (*start == '\t')
6417c478bd9Sstevel@tonic-gate 		start++;
6427c478bd9Sstevel@tonic-gate 	    i = tabs(Start, start) - margin / tabsize;
6437c478bd9Sstevel@tonic-gate 	    printf ("\\h'|%dn'",
6447c478bd9Sstevel@tonic-gate 		    i * (tabsize == 4 ? 5 : 10) + 1 - margin % tabsize);
6457c478bd9Sstevel@tonic-gate 	    continue;
6467c478bd9Sstevel@tonic-gate 	}
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	if (!nokeyw && !force)
649*55fea89dSDan Cross 	    if (  (*start == '#'   ||  isidchr(*start))
6507c478bd9Sstevel@tonic-gate 	       && (start == Start || !isidchr(start[-1]))
6517c478bd9Sstevel@tonic-gate 	       ) {
6527c478bd9Sstevel@tonic-gate 		i = iskw(start);
6537c478bd9Sstevel@tonic-gate 		if (i > 0) {
6547c478bd9Sstevel@tonic-gate 		    printf("\\*(+K");
655*55fea89dSDan Cross 		    do
6567c478bd9Sstevel@tonic-gate 			putcp(*start++);
6577c478bd9Sstevel@tonic-gate 		    while (--i > 0);
6587c478bd9Sstevel@tonic-gate 		    printf("\\*(-K");
6597c478bd9Sstevel@tonic-gate 		    continue;
6607c478bd9Sstevel@tonic-gate 		}
6617c478bd9Sstevel@tonic-gate 	    }
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	putcp (*start++);
6647c478bd9Sstevel@tonic-gate     }
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 
668e5af7cceScraigm static int
tabs(char * s,char * os)669e5af7cceScraigm tabs(char *s, char *os)
6707c478bd9Sstevel@tonic-gate {
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate     return (width(s, os) / tabsize);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
675e5af7cceScraigm static int
width(char * s,char * os)676e5af7cceScraigm width(char *s, char *os)
6777c478bd9Sstevel@tonic-gate {
678e5af7cceScraigm 	int i = 0;
6797c478bd9Sstevel@tonic-gate 	unsigned char c;
6807c478bd9Sstevel@tonic-gate 	int n;
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	while (s < os) {
6837c478bd9Sstevel@tonic-gate 		if (*s == '\t') {
6847c478bd9Sstevel@tonic-gate 			i = (i + tabsize) &~ (tabsize-1);
6857c478bd9Sstevel@tonic-gate 			s++;
6867c478bd9Sstevel@tonic-gate 			continue;
6877c478bd9Sstevel@tonic-gate 		}
6887c478bd9Sstevel@tonic-gate 		c = *(unsigned char *)s;
6897c478bd9Sstevel@tonic-gate 		if (c < ' ')
6907c478bd9Sstevel@tonic-gate 			i += 2, s++;
6917c478bd9Sstevel@tonic-gate 		else if (c >= 0200) {
6927c478bd9Sstevel@tonic-gate 			if ((n = mblen(s, MB_CUR_MAX)) > 0) {
6937c478bd9Sstevel@tonic-gate 				i += csetcol(csetno(c));
6947c478bd9Sstevel@tonic-gate 				s += n;
6957c478bd9Sstevel@tonic-gate 			} else
6967c478bd9Sstevel@tonic-gate 				s++;
6977c478bd9Sstevel@tonic-gate 		} else
6987c478bd9Sstevel@tonic-gate 			i++, s++;
6997c478bd9Sstevel@tonic-gate 	}
7007c478bd9Sstevel@tonic-gate 	return (i);
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate 
703e5af7cceScraigm static void
putcp(int c)704e5af7cceScraigm putcp(int c)
7057c478bd9Sstevel@tonic-gate {
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	switch(c) {
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	case 0:
7107c478bd9Sstevel@tonic-gate 		break;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	case '\f':
7137c478bd9Sstevel@tonic-gate 		break;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	case '{':
7167c478bd9Sstevel@tonic-gate 		printf("\\*(+K{\\*(-K");
7177c478bd9Sstevel@tonic-gate 		break;
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	case '}':
7207c478bd9Sstevel@tonic-gate 		printf("\\*(+K}\\*(-K");
7217c478bd9Sstevel@tonic-gate 		break;
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	case '\\':
7247c478bd9Sstevel@tonic-gate 		printf("\\e");
7257c478bd9Sstevel@tonic-gate 		break;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	case '_':
7287c478bd9Sstevel@tonic-gate 		printf("\\*_");
7297c478bd9Sstevel@tonic-gate 		break;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	case '-':
7327c478bd9Sstevel@tonic-gate 		printf("\\*-");
7337c478bd9Sstevel@tonic-gate 		break;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 		/*
7367c478bd9Sstevel@tonic-gate 		 * The following two cases deal with the accent characters.
7377c478bd9Sstevel@tonic-gate 		 * If they're part of a comment, we assume that they're part
7387c478bd9Sstevel@tonic-gate 		 * of running text and hand them to troff as regular quote
7397c478bd9Sstevel@tonic-gate 		 * characters.  Otherwise, we assume they're being used as
7407c478bd9Sstevel@tonic-gate 		 * special characters (e.g., string delimiters) and arrange
7417c478bd9Sstevel@tonic-gate 		 * for troff to render them as accents.  This is an imperfect
7427c478bd9Sstevel@tonic-gate 		 * heuristic that produces slightly better appearance than the
7437c478bd9Sstevel@tonic-gate 		 * former behavior of unconditionally rendering the characters
7447c478bd9Sstevel@tonic-gate 		 * as accents.  (See bug 1040343.)
7457c478bd9Sstevel@tonic-gate 		 */
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	case '`':
7487c478bd9Sstevel@tonic-gate 		if (incomm)
7497c478bd9Sstevel@tonic-gate 			printf("`");
7507c478bd9Sstevel@tonic-gate 		else
7517c478bd9Sstevel@tonic-gate 			printf("\\`");
7527c478bd9Sstevel@tonic-gate 		break;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	case '\'':
7557c478bd9Sstevel@tonic-gate 		if (incomm)
7567c478bd9Sstevel@tonic-gate 			printf("'");
7577c478bd9Sstevel@tonic-gate 		else
7587c478bd9Sstevel@tonic-gate 			printf("\\'");
7597c478bd9Sstevel@tonic-gate 		break;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	case '.':
7627c478bd9Sstevel@tonic-gate 		printf("\\&.");
7637c478bd9Sstevel@tonic-gate 		break;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 		/*
7667c478bd9Sstevel@tonic-gate 		 * The following two cases contain special hacking
7677c478bd9Sstevel@tonic-gate 		 * to make C-style comments line up.  The tests aren't
7687c478bd9Sstevel@tonic-gate 		 * really adequate; they lead to grotesqueries such
7697c478bd9Sstevel@tonic-gate 		 * as italicized multiplication and division operators.
7707c478bd9Sstevel@tonic-gate 		 * However, the obvious test (!incomm) doesn't work,
7717c478bd9Sstevel@tonic-gate 		 * because incomm isn't set until after we've put out
7727c478bd9Sstevel@tonic-gate 		 * the comment-begin characters.  The real problem is
7737c478bd9Sstevel@tonic-gate 		 * that expmatch() doesn't give us enough information.
7747c478bd9Sstevel@tonic-gate 		 */
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	case '*':
7777c478bd9Sstevel@tonic-gate 		if (instr || inchr)
7787c478bd9Sstevel@tonic-gate 			printf("*");
7797c478bd9Sstevel@tonic-gate 		else
7807c478bd9Sstevel@tonic-gate 			printf("\\f2*\\fP");
7817c478bd9Sstevel@tonic-gate 		break;
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	case '/':
7847c478bd9Sstevel@tonic-gate 		if (instr || inchr)
7857c478bd9Sstevel@tonic-gate 			printf("/");
7867c478bd9Sstevel@tonic-gate 		else
7877c478bd9Sstevel@tonic-gate 			printf("\\f2\\h'\\w' 'u-\\w'/'u'/\\fP");
7887c478bd9Sstevel@tonic-gate 		break;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	default:
7917c478bd9Sstevel@tonic-gate 		if (c < 040)
7927c478bd9Sstevel@tonic-gate 			putchar('^'), c |= '@';
79393b546c0SToomas Soome 		/* FALLTHROUGH */
7947c478bd9Sstevel@tonic-gate 	case '\t':
7957c478bd9Sstevel@tonic-gate 	case '\n':
7967c478bd9Sstevel@tonic-gate 		putchar(c);
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate  *	look for a process beginning on this line
8027c478bd9Sstevel@tonic-gate  */
8037c478bd9Sstevel@tonic-gate boolean
isproc(char * s)804e8bca4eaSToomas Soome isproc(char *s)
8057c478bd9Sstevel@tonic-gate {
806e8bca4eaSToomas Soome     pname[0] = '\0';
8077c478bd9Sstevel@tonic-gate     if (l_prclevel ? (prclevel == blklevel) : (!l_toplex || blklevel == 0))
8087c478bd9Sstevel@tonic-gate 	if (expmatch (s, l_prcbeg, pname) != NIL) {
8097c478bd9Sstevel@tonic-gate 	    return (TRUE);
8107c478bd9Sstevel@tonic-gate 	}
8117c478bd9Sstevel@tonic-gate     return (FALSE);
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate /*
8167c478bd9Sstevel@tonic-gate  * iskw - check to see if the next word is a keyword
8177c478bd9Sstevel@tonic-gate  *	Return its length if it is or 0 if it isn't.
8187c478bd9Sstevel@tonic-gate  */
8197c478bd9Sstevel@tonic-gate 
820e5af7cceScraigm static int
iskw(char * s)821e5af7cceScraigm iskw(char *s)
8227c478bd9Sstevel@tonic-gate {
823e5af7cceScraigm 	char **ss = l_keywds;
824e5af7cceScraigm 	int i = 1;
825e5af7cceScraigm 	char *cp = s;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	/* Get token length. */
8287c478bd9Sstevel@tonic-gate 	while (++cp, isidchr(*cp))
8297c478bd9Sstevel@tonic-gate 		i++;
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	while (cp = *ss++) {
8327c478bd9Sstevel@tonic-gate 		if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
8337c478bd9Sstevel@tonic-gate 			return (i);
8347c478bd9Sstevel@tonic-gate 	}
8357c478bd9Sstevel@tonic-gate 	return (0);
8367c478bd9Sstevel@tonic-gate }
837