xref: /titanic_53/usr/src/cmd/vgrind/vfontedpr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
3*7c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
4*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
5*7c478bd9Sstevel@tonic-gate  */
6*7c478bd9Sstevel@tonic-gate 
7*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate #include <ctype.h>
10*7c478bd9Sstevel@tonic-gate #include <stdio.h>
11*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
12*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
13*7c478bd9Sstevel@tonic-gate #include <locale.h>
14*7c478bd9Sstevel@tonic-gate #include <euc.h>
15*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #define boolean int
18*7c478bd9Sstevel@tonic-gate #define TRUE 1
19*7c478bd9Sstevel@tonic-gate #define FALSE 0
20*7c478bd9Sstevel@tonic-gate #define NIL 0
21*7c478bd9Sstevel@tonic-gate #define STANDARD 0
22*7c478bd9Sstevel@tonic-gate #define ALTERNATE 1
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate /*
25*7c478bd9Sstevel@tonic-gate  * Vfontedpr.
26*7c478bd9Sstevel@tonic-gate  *
27*7c478bd9Sstevel@tonic-gate  * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
28*7c478bd9Sstevel@tonic-gate  *
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #define STRLEN 10		/* length of strings introducing things */
32*7c478bd9Sstevel@tonic-gate #define PNAMELEN 40		/* length of a function/procedure name */
33*7c478bd9Sstevel@tonic-gate #define PSMAX 20		/* size of procedure name stacking */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /* regular expression routines */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate char	*expmatch();		/* match a string to an expression */
38*7c478bd9Sstevel@tonic-gate char	*STRNCMP();		/* a different kind of strncmp */
39*7c478bd9Sstevel@tonic-gate char	*convexp();		/* convert expression to internal form */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate char	*tgetstr();		/* extract a string-valued capability */
42*7c478bd9Sstevel@tonic-gate boolean	isproc();
43*7c478bd9Sstevel@tonic-gate char	*ctime();
44*7c478bd9Sstevel@tonic-gate char	*strchr();
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /*
47*7c478bd9Sstevel@tonic-gate  *	The state variables
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate boolean	incomm;			/* in a comment of the primary type */
51*7c478bd9Sstevel@tonic-gate boolean	instr;			/* in a string constant */
52*7c478bd9Sstevel@tonic-gate boolean	inchr;			/* in a string constant */
53*7c478bd9Sstevel@tonic-gate boolean	nokeyw = FALSE;		/* no keywords being flagged */
54*7c478bd9Sstevel@tonic-gate boolean	doindex = FALSE;	/* form an index */
55*7c478bd9Sstevel@tonic-gate boolean twocol = FALSE;		/* in two-column mode */
56*7c478bd9Sstevel@tonic-gate boolean	filter = FALSE;		/* act as a filter (like eqn) */
57*7c478bd9Sstevel@tonic-gate boolean	pass = FALSE;		/* when acting as a filter, pass indicates
58*7c478bd9Sstevel@tonic-gate 				 * whether we are currently processing
59*7c478bd9Sstevel@tonic-gate 				 * input.
60*7c478bd9Sstevel@tonic-gate 				 */
61*7c478bd9Sstevel@tonic-gate boolean	prccont;		/* continue last procedure */
62*7c478bd9Sstevel@tonic-gate int	comtype;		/* type of comment */
63*7c478bd9Sstevel@tonic-gate int	margin;
64*7c478bd9Sstevel@tonic-gate int	psptr;			/* the stack index of the current procedure */
65*7c478bd9Sstevel@tonic-gate char	pstack[PSMAX][PNAMELEN+1];	/* the procedure name stack */
66*7c478bd9Sstevel@tonic-gate int	plstack[PSMAX];		/* the procedure nesting level stack */
67*7c478bd9Sstevel@tonic-gate int	blklevel;		/* current nesting level */
68*7c478bd9Sstevel@tonic-gate int	prclevel;		/* nesting level at which procedure definitions
69*7c478bd9Sstevel@tonic-gate 				   may be found, -1 if none currently valid
70*7c478bd9Sstevel@tonic-gate 				   (meaningful only if l_prclevel is true) */
71*7c478bd9Sstevel@tonic-gate char	*defsfile = "/usr/lib/vgrindefs";	/* name of language definitions file */
72*7c478bd9Sstevel@tonic-gate char	pname[BUFSIZ+1];
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /*
75*7c478bd9Sstevel@tonic-gate  *	The language specific globals
76*7c478bd9Sstevel@tonic-gate  */
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate char	*language = "c";	/* the language indicator */
79*7c478bd9Sstevel@tonic-gate char	*l_keywds[BUFSIZ/2];	/* keyword table address */
80*7c478bd9Sstevel@tonic-gate char	*l_prcbeg;		/* regular expr for procedure begin */
81*7c478bd9Sstevel@tonic-gate char	*l_combeg;		/* string introducing a comment */
82*7c478bd9Sstevel@tonic-gate char	*l_comend;		/* string ending a comment */
83*7c478bd9Sstevel@tonic-gate char	*l_acmbeg;		/* string introducing a comment */
84*7c478bd9Sstevel@tonic-gate char	*l_acmend;		/* string ending a comment */
85*7c478bd9Sstevel@tonic-gate char	*l_blkbeg;		/* string begining of a block */
86*7c478bd9Sstevel@tonic-gate char	*l_blkend;		/* string ending a block */
87*7c478bd9Sstevel@tonic-gate char	*l_strbeg;		/* delimiter for string constant */
88*7c478bd9Sstevel@tonic-gate char	*l_strend;		/* delimiter for string constant */
89*7c478bd9Sstevel@tonic-gate char	*l_chrbeg;		/* delimiter for character constant */
90*7c478bd9Sstevel@tonic-gate char	*l_chrend;		/* delimiter for character constant */
91*7c478bd9Sstevel@tonic-gate char	*l_prcenable;		/* re indicating that procedure definitions
92*7c478bd9Sstevel@tonic-gate 				   can be found in the next lexical level --
93*7c478bd9Sstevel@tonic-gate 				   kludge for lisp-like languages that use
94*7c478bd9Sstevel@tonic-gate 				   something like
95*7c478bd9Sstevel@tonic-gate 					   (defun (proc ...)
96*7c478bd9Sstevel@tonic-gate 					  	(proc ...)
97*7c478bd9Sstevel@tonic-gate 					   )
98*7c478bd9Sstevel@tonic-gate 				   to define procedures */
99*7c478bd9Sstevel@tonic-gate char	l_escape;		/* character used to  escape characters */
100*7c478bd9Sstevel@tonic-gate boolean	l_toplex;		/* procedures only defined at top lex level */
101*7c478bd9Sstevel@tonic-gate boolean l_prclevel;		/* procedure definitions valid only within
102*7c478bd9Sstevel@tonic-gate 				   the nesting level indicated by the px
103*7c478bd9Sstevel@tonic-gate 				   (l_prcenable) capability */
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  *  for the benefit of die-hards who aren't convinced that tabs
107*7c478bd9Sstevel@tonic-gate  *  occur every eight columns
108*7c478bd9Sstevel@tonic-gate  */
109*7c478bd9Sstevel@tonic-gate short tabsize = 8;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate /*
112*7c478bd9Sstevel@tonic-gate  *  global variables also used by expmatch
113*7c478bd9Sstevel@tonic-gate  */
114*7c478bd9Sstevel@tonic-gate boolean	_escaped;		/* if last character was an escape */
115*7c478bd9Sstevel@tonic-gate char	*Start;			/* start of the current string */
116*7c478bd9Sstevel@tonic-gate boolean	l_onecase;		/* upper and lower case are equivalent */
117*7c478bd9Sstevel@tonic-gate char	*l_idchars;		/* characters legal in identifiers in addition
118*7c478bd9Sstevel@tonic-gate 				   to letters and digits (default "_") */
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate /*
121*7c478bd9Sstevel@tonic-gate  * The code below emits troff macros and directives that consume part of the
122*7c478bd9Sstevel@tonic-gate  * troff macro and register space.  See tmac.vgrind for an enumeration of
123*7c478bd9Sstevel@tonic-gate  * these macros and registers.
124*7c478bd9Sstevel@tonic-gate  */
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate main(argc, argv)
127*7c478bd9Sstevel@tonic-gate     int argc;
128*7c478bd9Sstevel@tonic-gate     char *argv[];
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate     FILE *in;
131*7c478bd9Sstevel@tonic-gate     char *fname;
132*7c478bd9Sstevel@tonic-gate     struct stat stbuf;
133*7c478bd9Sstevel@tonic-gate     char buf[BUFSIZ];
134*7c478bd9Sstevel@tonic-gate     char idbuf[256];	/* enough for all 8 bit chars */
135*7c478bd9Sstevel@tonic-gate     char strings[2 * BUFSIZ];
136*7c478bd9Sstevel@tonic-gate     char defs[2 * BUFSIZ];
137*7c478bd9Sstevel@tonic-gate     int needbp = 0;
138*7c478bd9Sstevel@tonic-gate     int i;
139*7c478bd9Sstevel@tonic-gate     char *cp;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
142*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
143*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
144*7c478bd9Sstevel@tonic-gate #endif
145*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate     /*
148*7c478bd9Sstevel@tonic-gate      * Dump the name by which we were invoked.
149*7c478bd9Sstevel@tonic-gate      */
150*7c478bd9Sstevel@tonic-gate     argc--, argv++;
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate     /*
153*7c478bd9Sstevel@tonic-gate      * Process arguments.  For the sake of compatibility with older versions
154*7c478bd9Sstevel@tonic-gate      * of the program, the syntax accepted below is very idiosyncratic.  Some
155*7c478bd9Sstevel@tonic-gate      * options require space between the option and its argument; others
156*7c478bd9Sstevel@tonic-gate      * disallow it.  No options may be bundled together.
157*7c478bd9Sstevel@tonic-gate      *
158*7c478bd9Sstevel@tonic-gate      * Actually, there is one incompatibility.  Files and options formerly
159*7c478bd9Sstevel@tonic-gate      * could be arbitrarily intermixed, but this is no longer allowed.  (This
160*7c478bd9Sstevel@tonic-gate      * possiblity was never documented.)
161*7c478bd9Sstevel@tonic-gate      */
162*7c478bd9Sstevel@tonic-gate     while (argc > 0 && *argv[0] == '-') {
163*7c478bd9Sstevel@tonic-gate 	switch (*(cp = argv[0] + 1)) {
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	case '\0':				/* - */
166*7c478bd9Sstevel@tonic-gate 	    /* Take input from stdin. */
167*7c478bd9Sstevel@tonic-gate 	    /*
168*7c478bd9Sstevel@tonic-gate 	     * This option implies the end of the flag arguments.  Leave the
169*7c478bd9Sstevel@tonic-gate 	     * "-" in place for the file processing code to see.
170*7c478bd9Sstevel@tonic-gate 	     */
171*7c478bd9Sstevel@tonic-gate 	    goto flagsdone;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	case '2':				/* -2 */
174*7c478bd9Sstevel@tonic-gate 	    /* Enter two column mode. */
175*7c478bd9Sstevel@tonic-gate 	    twocol = 1;
176*7c478bd9Sstevel@tonic-gate 	    printf("'nr =2 1\n");
177*7c478bd9Sstevel@tonic-gate 	    break;
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	case 'd':				/* -d <defs-file> */
180*7c478bd9Sstevel@tonic-gate 	    /* Specify the language description file. */
181*7c478bd9Sstevel@tonic-gate 	    defsfile = argv[1];
182*7c478bd9Sstevel@tonic-gate 	    argc--, argv++;
183*7c478bd9Sstevel@tonic-gate 	    break;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	case 'f':				/* -f */
186*7c478bd9Sstevel@tonic-gate 	    /* Act as a filter like eqn. */
187*7c478bd9Sstevel@tonic-gate 	    filter = 1;
188*7c478bd9Sstevel@tonic-gate 	    /*
189*7c478bd9Sstevel@tonic-gate 	     * Slide remaining arguments down one position and postpend "-",
190*7c478bd9Sstevel@tonic-gate 	     * to force reading from stdin.
191*7c478bd9Sstevel@tonic-gate 	     */
192*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < argc - 1; i++)
193*7c478bd9Sstevel@tonic-gate 		argv[i] = argv[i + 1];
194*7c478bd9Sstevel@tonic-gate 	    argv[argc - 1] = "-";
195*7c478bd9Sstevel@tonic-gate 	    continue;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 	case 'h':				/* -h [header] */
198*7c478bd9Sstevel@tonic-gate 	    /* Specify header string. */
199*7c478bd9Sstevel@tonic-gate 	    if (argc == 1) {
200*7c478bd9Sstevel@tonic-gate 		printf("'ds =H\n");
201*7c478bd9Sstevel@tonic-gate 		break;
202*7c478bd9Sstevel@tonic-gate 	    }
203*7c478bd9Sstevel@tonic-gate 	    printf("'ds =H %s\n", argv[1]);
204*7c478bd9Sstevel@tonic-gate 	    argc--, argv++;
205*7c478bd9Sstevel@tonic-gate 	    break;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	case 'l':				/* -l<language> */
208*7c478bd9Sstevel@tonic-gate 	    /* Specify the language. */
209*7c478bd9Sstevel@tonic-gate 	    language = cp + 1;
210*7c478bd9Sstevel@tonic-gate 	    break;
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	case 'n':				/* -n */
213*7c478bd9Sstevel@tonic-gate 	    /* Indicate no keywords. */
214*7c478bd9Sstevel@tonic-gate 	    nokeyw = 1;
215*7c478bd9Sstevel@tonic-gate 	    break;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	case 's':				/* -s<size> */
218*7c478bd9Sstevel@tonic-gate 	    /* Specify the font size. */
219*7c478bd9Sstevel@tonic-gate 	    i = 0;
220*7c478bd9Sstevel@tonic-gate 	    cp++;
221*7c478bd9Sstevel@tonic-gate 	    while (*cp)
222*7c478bd9Sstevel@tonic-gate 		i = i * 10 + (*cp++ - '0');
223*7c478bd9Sstevel@tonic-gate 	    printf("'nr vP %d\n", i);
224*7c478bd9Sstevel@tonic-gate 	    break;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	case 't':				/* -t */
227*7c478bd9Sstevel@tonic-gate 	    /* Specify a nondefault tab size. */
228*7c478bd9Sstevel@tonic-gate 	    tabsize = 4;
229*7c478bd9Sstevel@tonic-gate 	    break;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	case 'x':				/* -x */
232*7c478bd9Sstevel@tonic-gate 	    /* Build an index. */
233*7c478bd9Sstevel@tonic-gate 	    doindex = 1;
234*7c478bd9Sstevel@tonic-gate 	    /* This option implies "-n" as well; turn it on. */
235*7c478bd9Sstevel@tonic-gate 	    argv[0] = "-n";
236*7c478bd9Sstevel@tonic-gate 	    continue;
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	/* Advance to next argument. */
240*7c478bd9Sstevel@tonic-gate 	argc--, argv++;
241*7c478bd9Sstevel@tonic-gate     }
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate flagsdone:
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate     /*
246*7c478bd9Sstevel@tonic-gate      * Get the language definition from the defs file.
247*7c478bd9Sstevel@tonic-gate      */
248*7c478bd9Sstevel@tonic-gate     i = tgetent (defs, language, defsfile);
249*7c478bd9Sstevel@tonic-gate     if (i == 0) {
250*7c478bd9Sstevel@tonic-gate 	fprintf (stderr, gettext("no entry for language %s\n"), language);
251*7c478bd9Sstevel@tonic-gate 	exit (0);
252*7c478bd9Sstevel@tonic-gate     } else  if (i < 0) {
253*7c478bd9Sstevel@tonic-gate 	fprintf (stderr,  gettext("cannot find vgrindefs file %s\n"), defsfile);
254*7c478bd9Sstevel@tonic-gate 	exit (0);
255*7c478bd9Sstevel@tonic-gate     }
256*7c478bd9Sstevel@tonic-gate     cp = strings;
257*7c478bd9Sstevel@tonic-gate     if (tgetstr ("kw", &cp) == NIL)
258*7c478bd9Sstevel@tonic-gate 	nokeyw = TRUE;
259*7c478bd9Sstevel@tonic-gate     else  {
260*7c478bd9Sstevel@tonic-gate 	char **cpp;
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	cpp = l_keywds;
263*7c478bd9Sstevel@tonic-gate 	cp = strings;
264*7c478bd9Sstevel@tonic-gate 	while (*cp) {
265*7c478bd9Sstevel@tonic-gate 	    while (*cp == ' ' || *cp =='\t')
266*7c478bd9Sstevel@tonic-gate 		*cp++ = NULL;
267*7c478bd9Sstevel@tonic-gate 	    if (*cp)
268*7c478bd9Sstevel@tonic-gate 		*cpp++ = cp;
269*7c478bd9Sstevel@tonic-gate 	    while (*cp != ' ' && *cp  != '\t' && *cp)
270*7c478bd9Sstevel@tonic-gate 		cp++;
271*7c478bd9Sstevel@tonic-gate 	}
272*7c478bd9Sstevel@tonic-gate 	*cpp = NIL;
273*7c478bd9Sstevel@tonic-gate     }
274*7c478bd9Sstevel@tonic-gate     cp = buf;
275*7c478bd9Sstevel@tonic-gate     l_prcbeg = convexp (tgetstr ("pb", &cp));
276*7c478bd9Sstevel@tonic-gate     cp = buf;
277*7c478bd9Sstevel@tonic-gate     l_combeg = convexp (tgetstr ("cb", &cp));
278*7c478bd9Sstevel@tonic-gate     cp = buf;
279*7c478bd9Sstevel@tonic-gate     l_comend = convexp (tgetstr ("ce", &cp));
280*7c478bd9Sstevel@tonic-gate     cp = buf;
281*7c478bd9Sstevel@tonic-gate     l_acmbeg = convexp (tgetstr ("ab", &cp));
282*7c478bd9Sstevel@tonic-gate     cp = buf;
283*7c478bd9Sstevel@tonic-gate     l_acmend = convexp (tgetstr ("ae", &cp));
284*7c478bd9Sstevel@tonic-gate     cp = buf;
285*7c478bd9Sstevel@tonic-gate     l_strbeg = convexp (tgetstr ("sb", &cp));
286*7c478bd9Sstevel@tonic-gate     cp = buf;
287*7c478bd9Sstevel@tonic-gate     l_strend = convexp (tgetstr ("se", &cp));
288*7c478bd9Sstevel@tonic-gate     cp = buf;
289*7c478bd9Sstevel@tonic-gate     l_blkbeg = convexp (tgetstr ("bb", &cp));
290*7c478bd9Sstevel@tonic-gate     cp = buf;
291*7c478bd9Sstevel@tonic-gate     l_blkend = convexp (tgetstr ("be", &cp));
292*7c478bd9Sstevel@tonic-gate     cp = buf;
293*7c478bd9Sstevel@tonic-gate     l_chrbeg = convexp (tgetstr ("lb", &cp));
294*7c478bd9Sstevel@tonic-gate     cp = buf;
295*7c478bd9Sstevel@tonic-gate     l_chrend = convexp (tgetstr ("le", &cp));
296*7c478bd9Sstevel@tonic-gate     cp = buf;
297*7c478bd9Sstevel@tonic-gate     l_prcenable = convexp (tgetstr ("px", &cp));
298*7c478bd9Sstevel@tonic-gate     cp = idbuf;
299*7c478bd9Sstevel@tonic-gate     l_idchars = tgetstr ("id", &cp);
300*7c478bd9Sstevel@tonic-gate     /* Set default, for compatibility with old version */
301*7c478bd9Sstevel@tonic-gate     if (l_idchars == NIL)
302*7c478bd9Sstevel@tonic-gate 	l_idchars = "_";
303*7c478bd9Sstevel@tonic-gate     l_escape = '\\';
304*7c478bd9Sstevel@tonic-gate     l_onecase = tgetflag ("oc");
305*7c478bd9Sstevel@tonic-gate     l_toplex = tgetflag ("tl");
306*7c478bd9Sstevel@tonic-gate     l_prclevel = tgetflag ("pl");
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate     /*
309*7c478bd9Sstevel@tonic-gate      * Emit a call to the initialization macro.  If not in filter mode, emit a
310*7c478bd9Sstevel@tonic-gate      * call to the vS macro, so that tmac.vgrind can uniformly assume that all
311*7c478bd9Sstevel@tonic-gate      * program input is bracketed with vS-vE pairs.
312*7c478bd9Sstevel@tonic-gate      */
313*7c478bd9Sstevel@tonic-gate     printf("'vI\n");
314*7c478bd9Sstevel@tonic-gate     if (!filter)
315*7c478bd9Sstevel@tonic-gate 	printf("'vS\n");
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate     if (doindex) {
318*7c478bd9Sstevel@tonic-gate 	/*
319*7c478bd9Sstevel@tonic-gate 	 * XXX:	Hard-wired spacing information.  This should probably turn
320*7c478bd9Sstevel@tonic-gate 	 *	into the emission of a macro invocation, so that tmac.vgrind
321*7c478bd9Sstevel@tonic-gate 	 *	can make up its own mind about what spacing is appropriate.
322*7c478bd9Sstevel@tonic-gate 	 */
323*7c478bd9Sstevel@tonic-gate 	if (twocol)
324*7c478bd9Sstevel@tonic-gate 	    printf("'ta 2.5i 2.75i 4.0iR\n'in .25i\n");
325*7c478bd9Sstevel@tonic-gate 	else
326*7c478bd9Sstevel@tonic-gate 	    printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
327*7c478bd9Sstevel@tonic-gate     }
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate     while (argc > 0) {
330*7c478bd9Sstevel@tonic-gate 	if (strcmp(argv[0], "-") == 0) {
331*7c478bd9Sstevel@tonic-gate 	    /* Embed an instance of the original stdin. */
332*7c478bd9Sstevel@tonic-gate 	    in = fdopen(fileno(stdin), "r");
333*7c478bd9Sstevel@tonic-gate 	    fname = "";
334*7c478bd9Sstevel@tonic-gate 	} else {
335*7c478bd9Sstevel@tonic-gate 	    /* Open the file for input. */
336*7c478bd9Sstevel@tonic-gate 	    if ((in = fopen(argv[0], "r")) == NULL) {
337*7c478bd9Sstevel@tonic-gate 		perror(argv[0]);
338*7c478bd9Sstevel@tonic-gate 		exit(1);
339*7c478bd9Sstevel@tonic-gate 	    }
340*7c478bd9Sstevel@tonic-gate 	    fname = argv[0];
341*7c478bd9Sstevel@tonic-gate 	}
342*7c478bd9Sstevel@tonic-gate 	argc--, argv++;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	/*
345*7c478bd9Sstevel@tonic-gate 	 * Reinitialize for the current file.
346*7c478bd9Sstevel@tonic-gate 	 */
347*7c478bd9Sstevel@tonic-gate 	incomm = FALSE;
348*7c478bd9Sstevel@tonic-gate 	instr = FALSE;
349*7c478bd9Sstevel@tonic-gate 	inchr = FALSE;
350*7c478bd9Sstevel@tonic-gate 	_escaped = FALSE;
351*7c478bd9Sstevel@tonic-gate 	blklevel = 0;
352*7c478bd9Sstevel@tonic-gate 	prclevel = -1;
353*7c478bd9Sstevel@tonic-gate 	for (psptr=0; psptr<PSMAX; psptr++) {
354*7c478bd9Sstevel@tonic-gate 	    pstack[psptr][0] = NULL;
355*7c478bd9Sstevel@tonic-gate 	    plstack[psptr] = 0;
356*7c478bd9Sstevel@tonic-gate 	}
357*7c478bd9Sstevel@tonic-gate 	psptr = -1;
358*7c478bd9Sstevel@tonic-gate 	printf("'-F\n");
359*7c478bd9Sstevel@tonic-gate 	if (!filter) {
360*7c478bd9Sstevel@tonic-gate 	    char *cp;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	    printf(".ds =F %s\n", fname);
363*7c478bd9Sstevel@tonic-gate 	    if (needbp) {
364*7c478bd9Sstevel@tonic-gate 		needbp = 0;
365*7c478bd9Sstevel@tonic-gate 		printf(".()\n");
366*7c478bd9Sstevel@tonic-gate 		printf(".bp\n");
367*7c478bd9Sstevel@tonic-gate 	    }
368*7c478bd9Sstevel@tonic-gate 	    fstat(fileno(in), &stbuf);
369*7c478bd9Sstevel@tonic-gate 	    cp = ctime(&stbuf.st_mtime);
370*7c478bd9Sstevel@tonic-gate 	    cp[16] = '\0';
371*7c478bd9Sstevel@tonic-gate 	    cp[24] = '\0';
372*7c478bd9Sstevel@tonic-gate 	    printf(".ds =M %s %s\n", cp+4, cp+20);
373*7c478bd9Sstevel@tonic-gate 	    printf("'wh 0 vH\n");
374*7c478bd9Sstevel@tonic-gate 	    printf("'wh -1i vF\n");
375*7c478bd9Sstevel@tonic-gate 	}
376*7c478bd9Sstevel@tonic-gate 	if (needbp && filter) {
377*7c478bd9Sstevel@tonic-gate 	    needbp = 0;
378*7c478bd9Sstevel@tonic-gate 	    printf(".()\n");
379*7c478bd9Sstevel@tonic-gate 	    printf(".bp\n");
380*7c478bd9Sstevel@tonic-gate 	}
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	/*
383*7c478bd9Sstevel@tonic-gate 	 *	MAIN LOOP!!!
384*7c478bd9Sstevel@tonic-gate 	 */
385*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, sizeof buf, in) != NULL) {
386*7c478bd9Sstevel@tonic-gate 	    if (buf[0] == '\f') {
387*7c478bd9Sstevel@tonic-gate 		printf(".bp\n");
388*7c478bd9Sstevel@tonic-gate 	    }
389*7c478bd9Sstevel@tonic-gate 	    if (buf[0] == '.') {
390*7c478bd9Sstevel@tonic-gate 		printf("%s", buf);
391*7c478bd9Sstevel@tonic-gate 		if (!strncmp (buf+1, "vS", 2))
392*7c478bd9Sstevel@tonic-gate 		    pass = TRUE;
393*7c478bd9Sstevel@tonic-gate 		if (!strncmp (buf+1, "vE", 2))
394*7c478bd9Sstevel@tonic-gate 		    pass = FALSE;
395*7c478bd9Sstevel@tonic-gate 		continue;
396*7c478bd9Sstevel@tonic-gate 	    }
397*7c478bd9Sstevel@tonic-gate 	    prccont = FALSE;
398*7c478bd9Sstevel@tonic-gate 	    if (!filter || pass)
399*7c478bd9Sstevel@tonic-gate 		putScp(buf);
400*7c478bd9Sstevel@tonic-gate 	    else
401*7c478bd9Sstevel@tonic-gate 		printf("%s", buf);
402*7c478bd9Sstevel@tonic-gate 	    if (prccont && (psptr >= 0))
403*7c478bd9Sstevel@tonic-gate 		printf("'FC %s\n", pstack[psptr]);
404*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
405*7c478bd9Sstevel@tonic-gate 	    printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
406*7c478bd9Sstevel@tonic-gate #endif
407*7c478bd9Sstevel@tonic-gate 	    margin = 0;
408*7c478bd9Sstevel@tonic-gate 	}
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	needbp = 1;
411*7c478bd9Sstevel@tonic-gate 	(void) fclose(in);
412*7c478bd9Sstevel@tonic-gate     }
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate     /* Close off the vS-vE pair. */
415*7c478bd9Sstevel@tonic-gate     if (!filter)
416*7c478bd9Sstevel@tonic-gate 	printf("'vE\n");
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate     exit(0);
419*7c478bd9Sstevel@tonic-gate     /* NOTREACHED */
420*7c478bd9Sstevel@tonic-gate }
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate #define isidchr(c) (isalnum(c) || ((c) != NIL && strchr(l_idchars, (c)) != NIL))
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate putScp(os)
425*7c478bd9Sstevel@tonic-gate     char *os;
426*7c478bd9Sstevel@tonic-gate {
427*7c478bd9Sstevel@tonic-gate     register char *s = os;		/* pointer to unmatched string */
428*7c478bd9Sstevel@tonic-gate     char dummy[BUFSIZ];			/* dummy to be used by expmatch */
429*7c478bd9Sstevel@tonic-gate     char *comptr;			/* end of a comment delimiter */
430*7c478bd9Sstevel@tonic-gate     char *acmptr;			/* end of a comment delimiter */
431*7c478bd9Sstevel@tonic-gate     char *strptr;			/* end of a string delimiter */
432*7c478bd9Sstevel@tonic-gate     char *chrptr;			/* end of a character const delimiter */
433*7c478bd9Sstevel@tonic-gate     char *blksptr;			/* end of a lexical block start */
434*7c478bd9Sstevel@tonic-gate     char *blkeptr;			/* end of a lexical block end */
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate     Start = os;			/* remember the start for expmatch */
437*7c478bd9Sstevel@tonic-gate     _escaped = FALSE;
438*7c478bd9Sstevel@tonic-gate     if (nokeyw || incomm || instr)
439*7c478bd9Sstevel@tonic-gate 	goto skip;
440*7c478bd9Sstevel@tonic-gate     if (isproc(s)) {
441*7c478bd9Sstevel@tonic-gate 	printf("'FN %s\n", pname);
442*7c478bd9Sstevel@tonic-gate 	if (psptr < PSMAX-1) {
443*7c478bd9Sstevel@tonic-gate 	    ++psptr;
444*7c478bd9Sstevel@tonic-gate 	    strncpy (pstack[psptr], pname, PNAMELEN);
445*7c478bd9Sstevel@tonic-gate 	    pstack[psptr][PNAMELEN] = NULL;
446*7c478bd9Sstevel@tonic-gate 	    plstack[psptr] = blklevel;
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate     }
449*7c478bd9Sstevel@tonic-gate     /*
450*7c478bd9Sstevel@tonic-gate      * if l_prclevel is set, check to see whether this lexical level
451*7c478bd9Sstevel@tonic-gate      * is one immediately below which procedure definitions are allowed.
452*7c478bd9Sstevel@tonic-gate      */
453*7c478bd9Sstevel@tonic-gate     if (l_prclevel && !incomm && !instr && !inchr) {
454*7c478bd9Sstevel@tonic-gate 	if (expmatch (s, l_prcenable, dummy) != NIL)
455*7c478bd9Sstevel@tonic-gate 	    prclevel = blklevel + 1;
456*7c478bd9Sstevel@tonic-gate     }
457*7c478bd9Sstevel@tonic-gate skip:
458*7c478bd9Sstevel@tonic-gate     do {
459*7c478bd9Sstevel@tonic-gate 	/* check for string, comment, blockstart, etc */
460*7c478bd9Sstevel@tonic-gate 	if (!incomm && !instr && !inchr) {
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	    blkeptr = expmatch (s, l_blkend, dummy);
463*7c478bd9Sstevel@tonic-gate 	    blksptr = expmatch (s, l_blkbeg, dummy);
464*7c478bd9Sstevel@tonic-gate 	    comptr = expmatch (s, l_combeg, dummy);
465*7c478bd9Sstevel@tonic-gate 	    acmptr = expmatch (s, l_acmbeg, dummy);
466*7c478bd9Sstevel@tonic-gate 	    strptr = expmatch (s, l_strbeg, dummy);
467*7c478bd9Sstevel@tonic-gate 	    chrptr = expmatch (s, l_chrbeg, dummy);
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	    /* start of a comment? */
470*7c478bd9Sstevel@tonic-gate 	    if (comptr != NIL)
471*7c478bd9Sstevel@tonic-gate 		if ((comptr < strptr || strptr == NIL)
472*7c478bd9Sstevel@tonic-gate 		  && (comptr < acmptr || acmptr == NIL)
473*7c478bd9Sstevel@tonic-gate 		  && (comptr < chrptr || chrptr == NIL)
474*7c478bd9Sstevel@tonic-gate 		  && (comptr < blksptr || blksptr == NIL)
475*7c478bd9Sstevel@tonic-gate 		  && (comptr < blkeptr || blkeptr == NIL)) {
476*7c478bd9Sstevel@tonic-gate 		    putKcp (s, comptr-1, FALSE);
477*7c478bd9Sstevel@tonic-gate 		    s = comptr;
478*7c478bd9Sstevel@tonic-gate 		    incomm = TRUE;
479*7c478bd9Sstevel@tonic-gate 		    comtype = STANDARD;
480*7c478bd9Sstevel@tonic-gate 		    if (s != os)
481*7c478bd9Sstevel@tonic-gate 			printf ("\\c");
482*7c478bd9Sstevel@tonic-gate 		    printf ("\\c\n'+C\n");
483*7c478bd9Sstevel@tonic-gate 		    continue;
484*7c478bd9Sstevel@tonic-gate 		}
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 	    /* start of a comment? */
487*7c478bd9Sstevel@tonic-gate 	    if (acmptr != NIL)
488*7c478bd9Sstevel@tonic-gate 		if ((acmptr < strptr || strptr == NIL)
489*7c478bd9Sstevel@tonic-gate 		  && (acmptr < chrptr || chrptr == NIL)
490*7c478bd9Sstevel@tonic-gate 		  && (acmptr < blksptr || blksptr == NIL)
491*7c478bd9Sstevel@tonic-gate 		  && (acmptr < blkeptr || blkeptr == NIL)) {
492*7c478bd9Sstevel@tonic-gate 		    putKcp (s, acmptr-1, FALSE);
493*7c478bd9Sstevel@tonic-gate 		    s = acmptr;
494*7c478bd9Sstevel@tonic-gate 		    incomm = TRUE;
495*7c478bd9Sstevel@tonic-gate 		    comtype = ALTERNATE;
496*7c478bd9Sstevel@tonic-gate 		    if (s != os)
497*7c478bd9Sstevel@tonic-gate 			printf ("\\c");
498*7c478bd9Sstevel@tonic-gate 		    printf ("\\c\n'+C\n");
499*7c478bd9Sstevel@tonic-gate 		    continue;
500*7c478bd9Sstevel@tonic-gate 		}
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	    /* start of a string? */
503*7c478bd9Sstevel@tonic-gate 	    if (strptr != NIL)
504*7c478bd9Sstevel@tonic-gate 		if ((strptr < chrptr || chrptr == NIL)
505*7c478bd9Sstevel@tonic-gate 		  && (strptr < blksptr || blksptr == NIL)
506*7c478bd9Sstevel@tonic-gate 		  && (strptr < blkeptr || blkeptr == NIL)) {
507*7c478bd9Sstevel@tonic-gate 		    putKcp (s, strptr-1, FALSE);
508*7c478bd9Sstevel@tonic-gate 		    s = strptr;
509*7c478bd9Sstevel@tonic-gate 		    instr = TRUE;
510*7c478bd9Sstevel@tonic-gate 		    continue;
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	    /* start of a character string? */
514*7c478bd9Sstevel@tonic-gate 	    if (chrptr != NIL)
515*7c478bd9Sstevel@tonic-gate 		if ((chrptr < blksptr || blksptr == NIL)
516*7c478bd9Sstevel@tonic-gate 		  && (chrptr < blkeptr || blkeptr == NIL)) {
517*7c478bd9Sstevel@tonic-gate 		    putKcp (s, chrptr-1, FALSE);
518*7c478bd9Sstevel@tonic-gate 		    s = chrptr;
519*7c478bd9Sstevel@tonic-gate 		    inchr = TRUE;
520*7c478bd9Sstevel@tonic-gate 		    continue;
521*7c478bd9Sstevel@tonic-gate 		}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	    /* end of a lexical block */
524*7c478bd9Sstevel@tonic-gate 	    if (blkeptr != NIL) {
525*7c478bd9Sstevel@tonic-gate 		if (blkeptr < blksptr || blksptr == NIL) {
526*7c478bd9Sstevel@tonic-gate 		    /* reset prclevel if necessary */
527*7c478bd9Sstevel@tonic-gate 		    if (l_prclevel && prclevel == blklevel)
528*7c478bd9Sstevel@tonic-gate 			prclevel = -1;
529*7c478bd9Sstevel@tonic-gate 		    putKcp (s, blkeptr - 1, FALSE);
530*7c478bd9Sstevel@tonic-gate 		    s = blkeptr;
531*7c478bd9Sstevel@tonic-gate 		    blklevel--;
532*7c478bd9Sstevel@tonic-gate 		    if (psptr >= 0 && plstack[psptr] >= blklevel) {
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 			/* end of current procedure */
535*7c478bd9Sstevel@tonic-gate 			if (s != os)
536*7c478bd9Sstevel@tonic-gate 			    printf ("\\c");
537*7c478bd9Sstevel@tonic-gate 			printf ("\\c\n'-F\n");
538*7c478bd9Sstevel@tonic-gate 			blklevel = plstack[psptr];
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 			/* see if we should print the last proc name */
541*7c478bd9Sstevel@tonic-gate 			if (--psptr >= 0)
542*7c478bd9Sstevel@tonic-gate 			    prccont = TRUE;
543*7c478bd9Sstevel@tonic-gate 			else
544*7c478bd9Sstevel@tonic-gate 			    psptr = -1;
545*7c478bd9Sstevel@tonic-gate 		    }
546*7c478bd9Sstevel@tonic-gate 		    continue;
547*7c478bd9Sstevel@tonic-gate 		}
548*7c478bd9Sstevel@tonic-gate 	    }
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 	    /* start of a lexical block */
551*7c478bd9Sstevel@tonic-gate 	    if (blksptr != NIL) {
552*7c478bd9Sstevel@tonic-gate 		putKcp (s, blksptr - 1, FALSE);
553*7c478bd9Sstevel@tonic-gate 		s = blksptr;
554*7c478bd9Sstevel@tonic-gate 		blklevel++;
555*7c478bd9Sstevel@tonic-gate 		continue;
556*7c478bd9Sstevel@tonic-gate 	    }
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate 	/* check for end of comment */
559*7c478bd9Sstevel@tonic-gate 	} else if (incomm) {
560*7c478bd9Sstevel@tonic-gate 	    comptr = expmatch (s, l_comend, dummy);
561*7c478bd9Sstevel@tonic-gate 	    acmptr = expmatch (s, l_acmend, dummy);
562*7c478bd9Sstevel@tonic-gate 	    if (((comtype == STANDARD) && (comptr != NIL)) ||
563*7c478bd9Sstevel@tonic-gate 	        ((comtype == ALTERNATE) && (acmptr != NIL))) {
564*7c478bd9Sstevel@tonic-gate 		if (comtype == STANDARD) {
565*7c478bd9Sstevel@tonic-gate 		    putKcp (s, comptr-1, TRUE);
566*7c478bd9Sstevel@tonic-gate 		    s = comptr;
567*7c478bd9Sstevel@tonic-gate 		} else {
568*7c478bd9Sstevel@tonic-gate 		    putKcp (s, acmptr-1, TRUE);
569*7c478bd9Sstevel@tonic-gate 		    s = acmptr;
570*7c478bd9Sstevel@tonic-gate 		}
571*7c478bd9Sstevel@tonic-gate 		incomm = FALSE;
572*7c478bd9Sstevel@tonic-gate 		printf("\\c\n'-C\n");
573*7c478bd9Sstevel@tonic-gate 		continue;
574*7c478bd9Sstevel@tonic-gate 	    } else {
575*7c478bd9Sstevel@tonic-gate 		putKcp (s, s + strlen(s) -1, TRUE);
576*7c478bd9Sstevel@tonic-gate 		s = s + strlen(s);
577*7c478bd9Sstevel@tonic-gate 		continue;
578*7c478bd9Sstevel@tonic-gate 	    }
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	/* check for end of string */
581*7c478bd9Sstevel@tonic-gate 	} else if (instr) {
582*7c478bd9Sstevel@tonic-gate 	    if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
583*7c478bd9Sstevel@tonic-gate 		putKcp (s, strptr-1, TRUE);
584*7c478bd9Sstevel@tonic-gate 		s = strptr;
585*7c478bd9Sstevel@tonic-gate 		instr = FALSE;
586*7c478bd9Sstevel@tonic-gate 		continue;
587*7c478bd9Sstevel@tonic-gate 	    } else {
588*7c478bd9Sstevel@tonic-gate 		putKcp (s, s+strlen(s)-1, TRUE);
589*7c478bd9Sstevel@tonic-gate 		s = s + strlen(s);
590*7c478bd9Sstevel@tonic-gate 		continue;
591*7c478bd9Sstevel@tonic-gate 	    }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	/* check for end of character string */
594*7c478bd9Sstevel@tonic-gate 	} else if (inchr) {
595*7c478bd9Sstevel@tonic-gate 	    if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) {
596*7c478bd9Sstevel@tonic-gate 		putKcp (s, chrptr-1, TRUE);
597*7c478bd9Sstevel@tonic-gate 		s = chrptr;
598*7c478bd9Sstevel@tonic-gate 		inchr = FALSE;
599*7c478bd9Sstevel@tonic-gate 		continue;
600*7c478bd9Sstevel@tonic-gate 	    } else {
601*7c478bd9Sstevel@tonic-gate 		putKcp (s, s+strlen(s)-1, TRUE);
602*7c478bd9Sstevel@tonic-gate 		s = s + strlen(s);
603*7c478bd9Sstevel@tonic-gate 		continue;
604*7c478bd9Sstevel@tonic-gate 	    }
605*7c478bd9Sstevel@tonic-gate 	}
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 	/* print out the line */
608*7c478bd9Sstevel@tonic-gate 	putKcp (s, s + strlen(s) -1, FALSE);
609*7c478bd9Sstevel@tonic-gate 	s = s + strlen(s);
610*7c478bd9Sstevel@tonic-gate     } while (*s);
611*7c478bd9Sstevel@tonic-gate }
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate putKcp (start, end, force)
614*7c478bd9Sstevel@tonic-gate     char	*start;		/* start of string to write */
615*7c478bd9Sstevel@tonic-gate     char	*end;		/* end of string to write */
616*7c478bd9Sstevel@tonic-gate     boolean	force;		/* true if we should force nokeyw */
617*7c478bd9Sstevel@tonic-gate {
618*7c478bd9Sstevel@tonic-gate     int i;
619*7c478bd9Sstevel@tonic-gate     int xfld = 0;
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate     while (start <= end) {
622*7c478bd9Sstevel@tonic-gate 	if (doindex) {
623*7c478bd9Sstevel@tonic-gate 	    if (*start == ' ' || *start == '\t') {
624*7c478bd9Sstevel@tonic-gate 		if (xfld == 0)
625*7c478bd9Sstevel@tonic-gate 		    printf("");
626*7c478bd9Sstevel@tonic-gate 		printf("\t");
627*7c478bd9Sstevel@tonic-gate 		xfld = 1;
628*7c478bd9Sstevel@tonic-gate 		while (*start == ' ' || *start == '\t')
629*7c478bd9Sstevel@tonic-gate 		    start++;
630*7c478bd9Sstevel@tonic-gate 		continue;
631*7c478bd9Sstevel@tonic-gate 	    }
632*7c478bd9Sstevel@tonic-gate 	}
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	/* take care of nice tab stops */
635*7c478bd9Sstevel@tonic-gate 	if (*start == '\t') {
636*7c478bd9Sstevel@tonic-gate 	    while (*start == '\t')
637*7c478bd9Sstevel@tonic-gate 		start++;
638*7c478bd9Sstevel@tonic-gate 	    i = tabs(Start, start) - margin / tabsize;
639*7c478bd9Sstevel@tonic-gate 	    printf ("\\h'|%dn'",
640*7c478bd9Sstevel@tonic-gate 		    i * (tabsize == 4 ? 5 : 10) + 1 - margin % tabsize);
641*7c478bd9Sstevel@tonic-gate 	    continue;
642*7c478bd9Sstevel@tonic-gate 	}
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	if (!nokeyw && !force)
645*7c478bd9Sstevel@tonic-gate 	    if (  (*start == '#'   ||  isidchr(*start))
646*7c478bd9Sstevel@tonic-gate 	       && (start == Start || !isidchr(start[-1]))
647*7c478bd9Sstevel@tonic-gate 	       ) {
648*7c478bd9Sstevel@tonic-gate 		i = iskw(start);
649*7c478bd9Sstevel@tonic-gate 		if (i > 0) {
650*7c478bd9Sstevel@tonic-gate 		    printf("\\*(+K");
651*7c478bd9Sstevel@tonic-gate 		    do
652*7c478bd9Sstevel@tonic-gate 			putcp(*start++);
653*7c478bd9Sstevel@tonic-gate 		    while (--i > 0);
654*7c478bd9Sstevel@tonic-gate 		    printf("\\*(-K");
655*7c478bd9Sstevel@tonic-gate 		    continue;
656*7c478bd9Sstevel@tonic-gate 		}
657*7c478bd9Sstevel@tonic-gate 	    }
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	putcp (*start++);
660*7c478bd9Sstevel@tonic-gate     }
661*7c478bd9Sstevel@tonic-gate }
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate tabs(s, os)
665*7c478bd9Sstevel@tonic-gate     char *s, *os;
666*7c478bd9Sstevel@tonic-gate {
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate     return (width(s, os) / tabsize);
669*7c478bd9Sstevel@tonic-gate }
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate width(s, os)
672*7c478bd9Sstevel@tonic-gate 	register char *s, *os;
673*7c478bd9Sstevel@tonic-gate {
674*7c478bd9Sstevel@tonic-gate 	register int i = 0;
675*7c478bd9Sstevel@tonic-gate 	unsigned char c;
676*7c478bd9Sstevel@tonic-gate 	int n;
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 	while (s < os) {
679*7c478bd9Sstevel@tonic-gate 		if (*s == '\t') {
680*7c478bd9Sstevel@tonic-gate 			i = (i + tabsize) &~ (tabsize-1);
681*7c478bd9Sstevel@tonic-gate 			s++;
682*7c478bd9Sstevel@tonic-gate 			continue;
683*7c478bd9Sstevel@tonic-gate 		}
684*7c478bd9Sstevel@tonic-gate 		c = *(unsigned char *)s;
685*7c478bd9Sstevel@tonic-gate 		if (c < ' ')
686*7c478bd9Sstevel@tonic-gate 			i += 2, s++;
687*7c478bd9Sstevel@tonic-gate 		else if (c >= 0200) {
688*7c478bd9Sstevel@tonic-gate 			if ((n = mblen(s, MB_CUR_MAX)) > 0) {
689*7c478bd9Sstevel@tonic-gate 				i += csetcol(csetno(c));
690*7c478bd9Sstevel@tonic-gate 				s += n;
691*7c478bd9Sstevel@tonic-gate 			} else
692*7c478bd9Sstevel@tonic-gate 				s++;
693*7c478bd9Sstevel@tonic-gate 		} else
694*7c478bd9Sstevel@tonic-gate 			i++, s++;
695*7c478bd9Sstevel@tonic-gate 	}
696*7c478bd9Sstevel@tonic-gate 	return (i);
697*7c478bd9Sstevel@tonic-gate }
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate putcp(c)
700*7c478bd9Sstevel@tonic-gate 	register int c;
701*7c478bd9Sstevel@tonic-gate {
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	switch(c) {
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	case 0:
706*7c478bd9Sstevel@tonic-gate 		break;
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 	case '\f':
709*7c478bd9Sstevel@tonic-gate 		break;
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate 	case '{':
712*7c478bd9Sstevel@tonic-gate 		printf("\\*(+K{\\*(-K");
713*7c478bd9Sstevel@tonic-gate 		break;
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	case '}':
716*7c478bd9Sstevel@tonic-gate 		printf("\\*(+K}\\*(-K");
717*7c478bd9Sstevel@tonic-gate 		break;
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	case '\\':
720*7c478bd9Sstevel@tonic-gate 		printf("\\e");
721*7c478bd9Sstevel@tonic-gate 		break;
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 	case '_':
724*7c478bd9Sstevel@tonic-gate 		printf("\\*_");
725*7c478bd9Sstevel@tonic-gate 		break;
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate 	case '-':
728*7c478bd9Sstevel@tonic-gate 		printf("\\*-");
729*7c478bd9Sstevel@tonic-gate 		break;
730*7c478bd9Sstevel@tonic-gate 
731*7c478bd9Sstevel@tonic-gate 		/*
732*7c478bd9Sstevel@tonic-gate 		 * The following two cases deal with the accent characters.
733*7c478bd9Sstevel@tonic-gate 		 * If they're part of a comment, we assume that they're part
734*7c478bd9Sstevel@tonic-gate 		 * of running text and hand them to troff as regular quote
735*7c478bd9Sstevel@tonic-gate 		 * characters.  Otherwise, we assume they're being used as
736*7c478bd9Sstevel@tonic-gate 		 * special characters (e.g., string delimiters) and arrange
737*7c478bd9Sstevel@tonic-gate 		 * for troff to render them as accents.  This is an imperfect
738*7c478bd9Sstevel@tonic-gate 		 * heuristic that produces slightly better appearance than the
739*7c478bd9Sstevel@tonic-gate 		 * former behavior of unconditionally rendering the characters
740*7c478bd9Sstevel@tonic-gate 		 * as accents.  (See bug 1040343.)
741*7c478bd9Sstevel@tonic-gate 		 */
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	case '`':
744*7c478bd9Sstevel@tonic-gate 		if (incomm)
745*7c478bd9Sstevel@tonic-gate 			printf("`");
746*7c478bd9Sstevel@tonic-gate 		else
747*7c478bd9Sstevel@tonic-gate 			printf("\\`");
748*7c478bd9Sstevel@tonic-gate 		break;
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	case '\'':
751*7c478bd9Sstevel@tonic-gate 		if (incomm)
752*7c478bd9Sstevel@tonic-gate 			printf("'");
753*7c478bd9Sstevel@tonic-gate 		else
754*7c478bd9Sstevel@tonic-gate 			printf("\\'");
755*7c478bd9Sstevel@tonic-gate 		break;
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate 	case '.':
758*7c478bd9Sstevel@tonic-gate 		printf("\\&.");
759*7c478bd9Sstevel@tonic-gate 		break;
760*7c478bd9Sstevel@tonic-gate 
761*7c478bd9Sstevel@tonic-gate 		/*
762*7c478bd9Sstevel@tonic-gate 		 * The following two cases contain special hacking
763*7c478bd9Sstevel@tonic-gate 		 * to make C-style comments line up.  The tests aren't
764*7c478bd9Sstevel@tonic-gate 		 * really adequate; they lead to grotesqueries such
765*7c478bd9Sstevel@tonic-gate 		 * as italicized multiplication and division operators.
766*7c478bd9Sstevel@tonic-gate 		 * However, the obvious test (!incomm) doesn't work,
767*7c478bd9Sstevel@tonic-gate 		 * because incomm isn't set until after we've put out
768*7c478bd9Sstevel@tonic-gate 		 * the comment-begin characters.  The real problem is
769*7c478bd9Sstevel@tonic-gate 		 * that expmatch() doesn't give us enough information.
770*7c478bd9Sstevel@tonic-gate 		 */
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	case '*':
773*7c478bd9Sstevel@tonic-gate 		if (instr || inchr)
774*7c478bd9Sstevel@tonic-gate 			printf("*");
775*7c478bd9Sstevel@tonic-gate 		else
776*7c478bd9Sstevel@tonic-gate 			printf("\\f2*\\fP");
777*7c478bd9Sstevel@tonic-gate 		break;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	case '/':
780*7c478bd9Sstevel@tonic-gate 		if (instr || inchr)
781*7c478bd9Sstevel@tonic-gate 			printf("/");
782*7c478bd9Sstevel@tonic-gate 		else
783*7c478bd9Sstevel@tonic-gate 			printf("\\f2\\h'\\w' 'u-\\w'/'u'/\\fP");
784*7c478bd9Sstevel@tonic-gate 		break;
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	default:
787*7c478bd9Sstevel@tonic-gate 		if (c < 040)
788*7c478bd9Sstevel@tonic-gate 			putchar('^'), c |= '@';
789*7c478bd9Sstevel@tonic-gate 	case '\t':
790*7c478bd9Sstevel@tonic-gate 	case '\n':
791*7c478bd9Sstevel@tonic-gate 		putchar(c);
792*7c478bd9Sstevel@tonic-gate 	}
793*7c478bd9Sstevel@tonic-gate }
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate /*
796*7c478bd9Sstevel@tonic-gate  *	look for a process beginning on this line
797*7c478bd9Sstevel@tonic-gate  */
798*7c478bd9Sstevel@tonic-gate boolean
799*7c478bd9Sstevel@tonic-gate isproc(s)
800*7c478bd9Sstevel@tonic-gate     char *s;
801*7c478bd9Sstevel@tonic-gate {
802*7c478bd9Sstevel@tonic-gate     pname[0] = NULL;
803*7c478bd9Sstevel@tonic-gate     if (l_prclevel ? (prclevel == blklevel) : (!l_toplex || blklevel == 0))
804*7c478bd9Sstevel@tonic-gate 	if (expmatch (s, l_prcbeg, pname) != NIL) {
805*7c478bd9Sstevel@tonic-gate 	    return (TRUE);
806*7c478bd9Sstevel@tonic-gate 	}
807*7c478bd9Sstevel@tonic-gate     return (FALSE);
808*7c478bd9Sstevel@tonic-gate }
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate /*
812*7c478bd9Sstevel@tonic-gate  * iskw - check to see if the next word is a keyword
813*7c478bd9Sstevel@tonic-gate  *	Return its length if it is or 0 if it isn't.
814*7c478bd9Sstevel@tonic-gate  */
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate iskw(s)
817*7c478bd9Sstevel@tonic-gate 	register char *s;
818*7c478bd9Sstevel@tonic-gate {
819*7c478bd9Sstevel@tonic-gate 	register char **ss = l_keywds;
820*7c478bd9Sstevel@tonic-gate 	register int i = 1;
821*7c478bd9Sstevel@tonic-gate 	register char *cp = s;
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate 	/* Get token length. */
824*7c478bd9Sstevel@tonic-gate 	while (++cp, isidchr(*cp))
825*7c478bd9Sstevel@tonic-gate 		i++;
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	while (cp = *ss++) {
828*7c478bd9Sstevel@tonic-gate 		if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
829*7c478bd9Sstevel@tonic-gate 			return (i);
830*7c478bd9Sstevel@tonic-gate 	}
831*7c478bd9Sstevel@tonic-gate 	return (0);
832*7c478bd9Sstevel@tonic-gate }
833