11590Srgrimes/*
21590Srgrimes * Copyright (c) 1980, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
3087693Smarkm#include <sys/cdefs.h>
3187693Smarkm
3287693Smarkm__FBSDID("$FreeBSD$");
3387693Smarkm
341590Srgrimes#ifndef lint
3528691Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1980, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
3887693Smarkm#endif
391590Srgrimes
401590Srgrimes#ifndef lint
4187693Smarkmstatic const char sccsid[] = "@(#)vfontedpr.c	8.1 (Berkeley) 6/6/93";
4228691Scharnier#endif
431590Srgrimes
441590Srgrimes#include <sys/types.h>
451590Srgrimes#include <sys/stat.h>
461590Srgrimes#include <ctype.h>
4728691Scharnier#include <err.h>
4828691Scharnier#include <stdio.h>
491590Srgrimes#include <stdlib.h>
50282950Sbapt#include <stdbool.h>
511590Srgrimes#include <string.h>
5228691Scharnier#include <time.h>
531590Srgrimes#include "pathnames.h"
541590Srgrimes#include "extern.h"
551590Srgrimes
561590Srgrimes#define STANDARD 0
571590Srgrimes#define ALTERNATE 1
581590Srgrimes
591590Srgrimes/*
601590Srgrimes * Vfontedpr.
611590Srgrimes *
621590Srgrimes * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
631590Srgrimes *
641590Srgrimes */
651590Srgrimes
661590Srgrimes#define STRLEN 10		/* length of strings introducing things */
671590Srgrimes#define PNAMELEN 40		/* length of a function/procedure name */
681590Srgrimes#define PSMAX 20		/* size of procedure name stacking */
691590Srgrimes
7092922Simpstatic int       iskw(char *);
71282950Sbaptstatic bool      isproc(char *);
72282950Sbaptstatic void      putKcp(char *, char *, bool);
7392922Simpstatic void      putScp(char *);
7492922Simpstatic void      putcp(int);
7592922Simpstatic int       tabs(char *, char *);
7692922Simpstatic int       width(char *, char *);
771590Srgrimes
781590Srgrimes/*
791590Srgrimes *	The state variables
801590Srgrimes */
811590Srgrimes
82282950Sbaptstatic bool	filter = false;	/* act as a filter (like eqn) */
83282950Sbaptstatic bool	inchr;		/* in a string constant */
84282950Sbaptstatic bool	incomm;		/* in a comment of the primary type */
85282950Sbaptstatic bool	idx = false;	/* form an index */
86282950Sbaptstatic bool	instr;		/* in a string constant */
87282950Sbaptstatic bool	nokeyw = false;	/* no keywords being flagged */
88282950Sbaptstatic bool	pass = false;	/*
891590Srgrimes				 * when acting as a filter, pass indicates
901590Srgrimes				 * whether we are currently processing
911590Srgrimes				 * input.
921590Srgrimes				 */
931590Srgrimes
941590Srgrimesstatic int	blklevel;	/* current nesting level */
951590Srgrimesstatic int	comtype;	/* type of comment */
96121547Speterstatic char *	defsfile[2] = { _PATH_VGRINDEFS, 0 };
971590Srgrimes				/* name of language definitions file */
981590Srgrimesstatic int	margin;
991590Srgrimesstatic int	plstack[PSMAX];	/* the procedure nesting level stack */
1008874Srgrimesstatic char	pname[BUFSIZ+1];
101282950Sbaptstatic bool  prccont;	/* continue last procedure */
1021590Srgrimesstatic int	psptr;		/* the stack index of the current procedure */
1031590Srgrimesstatic char	pstack[PSMAX][PNAMELEN+1];	/* the procedure name stack */
1041590Srgrimes
1051590Srgrimes/*
1061590Srgrimes *	The language specific globals
1071590Srgrimes */
1081590Srgrimes
1091590Srgrimeschar	*l_acmbeg;		/* string introducing a comment */
1101590Srgrimeschar	*l_acmend;		/* string ending a comment */
111228992Suqschar	*l_blkbeg;		/* string beginning of a block */
1121590Srgrimeschar	*l_blkend;		/* string ending a block */
1131590Srgrimeschar    *l_chrbeg;		/* delimiter for character constant */
1141590Srgrimeschar    *l_chrend;		/* delimiter for character constant */
1151590Srgrimeschar	*l_combeg;		/* string introducing a comment */
1161590Srgrimeschar	*l_comend;		/* string ending a comment */
1171590Srgrimeschar	 l_escape;		/* character used to  escape characters */
1181590Srgrimeschar	*l_keywds[BUFSIZ/2];	/* keyword table address */
11919012Sjoergchar	*l_nocom;		/* regexp for non-comments */
1201590Srgrimeschar	*l_prcbeg;		/* regular expr for procedure begin */
1211590Srgrimeschar    *l_strbeg;		/* delimiter for string constant */
1221590Srgrimeschar    *l_strend;		/* delimiter for string constant */
123282950Sbaptbool	 l_toplex;		/* procedures only defined at top lex level */
12487693Smarkmconst char *language = "c";	/* the language indicator */
1251590Srgrimes
1261590Srgrimes#define	ps(x)	printf("%s", x)
127282950Sbaptstatic char minus[] = "-";
128282950Sbaptstatic char minusn[] = "-n";
1291590Srgrimes
13028789Scharnierint
131282950Sbaptmain(int argc, char **argv)
1321590Srgrimes{
13387693Smarkm    const char *fname = "";
1341590Srgrimes    struct stat stbuf;
1351590Srgrimes    char buf[BUFSIZ];
1361590Srgrimes    char *defs;
1371590Srgrimes    int needbp = 0;
1381590Srgrimes
1391590Srgrimes    argc--, argv++;
1401590Srgrimes    do {
1411590Srgrimes	char *cp;
1421590Srgrimes	int i;
1431590Srgrimes
1441590Srgrimes	if (argc > 0) {
1451590Srgrimes	    if (!strcmp(argv[0], "-h")) {
1461590Srgrimes		if (argc == 1) {
1471590Srgrimes		    printf("'ds =H\n");
1481590Srgrimes		    argc = 0;
1491590Srgrimes		    goto rest;
1501590Srgrimes		}
1511590Srgrimes		printf("'ds =H %s\n", argv[1]);
1521590Srgrimes		argc--, argv++;
1531590Srgrimes		argc--, argv++;
1541590Srgrimes		if (argc > 0)
1551590Srgrimes		    continue;
1561590Srgrimes		goto rest;
1571590Srgrimes	    }
1581590Srgrimes
1591590Srgrimes	    /* act as a filter like eqn */
1601590Srgrimes	    if (!strcmp(argv[0], "-f")) {
161282950Sbapt		filter = true;
1621590Srgrimes		argv[0] = argv[argc-1];
163282950Sbapt		argv[argc-1] = minus;
1641590Srgrimes		continue;
1651590Srgrimes	    }
1661590Srgrimes
1671590Srgrimes	    /* take input from the standard place */
1681590Srgrimes	    if (!strcmp(argv[0], "-")) {
1691590Srgrimes		argc = 0;
1701590Srgrimes		goto rest;
1711590Srgrimes	    }
1721590Srgrimes
1731590Srgrimes	    /* build an index */
1741590Srgrimes	    if (!strcmp(argv[0], "-x")) {
175282950Sbapt		idx = true;
176282950Sbapt		argv[0] = minusn;
1771590Srgrimes	    }
1781590Srgrimes
1791590Srgrimes	    /* indicate no keywords */
1801590Srgrimes	    if (!strcmp(argv[0], "-n")) {
181282950Sbapt		nokeyw = true;
1821590Srgrimes		argc--, argv++;
1831590Srgrimes		continue;
1841590Srgrimes	    }
1851590Srgrimes
1861590Srgrimes	    /* specify the font size */
1871590Srgrimes	    if (!strncmp(argv[0], "-s", 2)) {
1881590Srgrimes		i = 0;
1891590Srgrimes		cp = argv[0] + 2;
1901590Srgrimes		while (*cp)
1911590Srgrimes		    i = i * 10 + (*cp++ - '0');
1921590Srgrimes		printf("'ps %d\n'vs %d\n", i, i+1);
1931590Srgrimes		argc--, argv++;
1941590Srgrimes		continue;
1951590Srgrimes	    }
1961590Srgrimes
1971590Srgrimes	    /* specify the language */
1981590Srgrimes	    if (!strncmp(argv[0], "-l", 2)) {
1991590Srgrimes		language = argv[0]+2;
2001590Srgrimes		argc--, argv++;
2011590Srgrimes		continue;
2021590Srgrimes	    }
2031590Srgrimes
2041590Srgrimes	    /* specify the language description file */
2051590Srgrimes	    if (!strncmp(argv[0], "-d", 2)) {
2061590Srgrimes		defsfile[0] = argv[1];
2071590Srgrimes		argc--, argv++;
2081590Srgrimes		argc--, argv++;
2091590Srgrimes		continue;
2101590Srgrimes	    }
2111590Srgrimes
2121590Srgrimes	    /* open the file for input */
21328691Scharnier	    if (freopen(argv[0], "r", stdin) == NULL)
21428691Scharnier		err(1, "%s", argv[0]);
2151590Srgrimes	    if (idx)
2161590Srgrimes		printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
2171590Srgrimes	    fname = argv[0];
2181590Srgrimes	    argc--, argv++;
2191590Srgrimes	}
2201590Srgrimes    rest:
2211590Srgrimes
2221590Srgrimes	/*
2231590Srgrimes	 *  get the  language definition from the defs file
2241590Srgrimes	 */
2251590Srgrimes	i = cgetent(&defs, defsfile, language);
2261590Srgrimes	if (i == -1) {
2271590Srgrimes	    fprintf (stderr, "no entry for language %s\n", language);
228282950Sbapt	    exit(0);
2298874Srgrimes	} else  if (i == -2) { fprintf(stderr,
2301590Srgrimes	    "cannot find vgrindefs file %s\n", defsfile[0]);
231282950Sbapt	    exit(0);
2328874Srgrimes	} else if (i == -3) { fprintf(stderr,
2338874Srgrimes	    "potential reference loop detected in vgrindefs file %s\n",
2348874Srgrimes            defsfile[0]);
2351590Srgrimes	    exit(0);
2361590Srgrimes	}
2371590Srgrimes	if (cgetustr(defs, "kw", &cp) == -1)
238282950Sbapt	    nokeyw = true;
2391590Srgrimes	else  {
2401590Srgrimes	    char **cpp;
2411590Srgrimes
2421590Srgrimes	    cpp = l_keywds;
2431590Srgrimes	    while (*cp) {
2441590Srgrimes		while (*cp == ' ' || *cp =='\t')
24529574Sphk		    *cp++ = '\0';
2461590Srgrimes		if (*cp)
2471590Srgrimes		    *cpp++ = cp;
2481590Srgrimes		while (*cp != ' ' && *cp  != '\t' && *cp)
2491590Srgrimes		    cp++;
2501590Srgrimes	    }
251282950Sbapt	    *cpp = NULL;
2521590Srgrimes	}
2531590Srgrimes	cgetustr(defs, "pb", &cp);
2541590Srgrimes	l_prcbeg = convexp(cp);
2551590Srgrimes	cgetustr(defs, "cb", &cp);
2561590Srgrimes	l_combeg = convexp(cp);
2571590Srgrimes	cgetustr(defs, "ce", &cp);
2581590Srgrimes	l_comend = convexp(cp);
2591590Srgrimes	cgetustr(defs, "ab", &cp);
2601590Srgrimes	l_acmbeg = convexp(cp);
2611590Srgrimes	cgetustr(defs, "ae", &cp);
2621590Srgrimes	l_acmend = convexp(cp);
2631590Srgrimes	cgetustr(defs, "sb", &cp);
2641590Srgrimes	l_strbeg = convexp(cp);
2651590Srgrimes	cgetustr(defs, "se", &cp);
2661590Srgrimes	l_strend = convexp(cp);
2671590Srgrimes	cgetustr(defs, "bb", &cp);
2681590Srgrimes	l_blkbeg = convexp(cp);
2691590Srgrimes	cgetustr(defs, "be", &cp);
2701590Srgrimes	l_blkend = convexp(cp);
2711590Srgrimes	cgetustr(defs, "lb", &cp);
2721590Srgrimes	l_chrbeg = convexp(cp);
2731590Srgrimes	cgetustr(defs, "le", &cp);
2741590Srgrimes	l_chrend = convexp(cp);
27519097Sjoerg	if (cgetustr(defs, "nc", &cp) >= 0)
27619097Sjoerg		l_nocom = convexp(cp);
2771590Srgrimes	l_escape = '\\';
2781590Srgrimes	l_onecase = (cgetcap(defs, "oc", ':') != NULL);
2791590Srgrimes	l_toplex = (cgetcap(defs, "tl", ':') != NULL);
2801590Srgrimes
2811590Srgrimes	/* initialize the program */
2821590Srgrimes
283282950Sbapt	incomm = false;
284282950Sbapt	instr = false;
285282950Sbapt	inchr = false;
286282950Sbapt	_escaped = false;
2871590Srgrimes	blklevel = 0;
2881590Srgrimes	for (psptr=0; psptr<PSMAX; psptr++) {
28929574Sphk	    pstack[psptr][0] = '\0';
2901590Srgrimes	    plstack[psptr] = 0;
2911590Srgrimes	}
2921590Srgrimes	psptr = -1;
2931590Srgrimes	ps("'-F\n");
2941590Srgrimes	if (!filter) {
2951590Srgrimes	    printf(".ds =F %s\n", fname);
2961590Srgrimes	    ps("'wh 0 vH\n");
2971590Srgrimes	    ps("'wh -1i vF\n");
2981590Srgrimes	}
2991590Srgrimes	if (needbp) {
3001590Srgrimes	    needbp = 0;
3011590Srgrimes	    printf(".()\n");
3021590Srgrimes	    printf(".bp\n");
3031590Srgrimes	}
3041590Srgrimes	if (!filter) {
3051590Srgrimes	    fstat(fileno(stdin), &stbuf);
3061590Srgrimes	    cp = ctime(&stbuf.st_mtime);
3071590Srgrimes	    cp[16] = '\0';
3081590Srgrimes	    cp[24] = '\0';
3091590Srgrimes	    printf(".ds =M %s %s\n", cp+4, cp+20);
3101590Srgrimes	}
3111590Srgrimes
3121590Srgrimes	/*
3131590Srgrimes	 *	MAIN LOOP!!!
3141590Srgrimes	 */
3151590Srgrimes	while (fgets(buf, sizeof buf, stdin) != NULL) {
3161590Srgrimes	    if (buf[0] == '\f') {
3171590Srgrimes		printf(".bp\n");
3181590Srgrimes	    }
3191590Srgrimes	    if (buf[0] == '.') {
3201590Srgrimes		printf("%s", buf);
3211590Srgrimes		if (!strncmp (buf+1, "vS", 2))
322282950Sbapt		    pass = true;
3231590Srgrimes		if (!strncmp (buf+1, "vE", 2))
324282950Sbapt		    pass = false;
3251590Srgrimes		continue;
3261590Srgrimes	    }
327282950Sbapt	    prccont = false;
3281590Srgrimes	    if (!filter || pass)
3291590Srgrimes		putScp(buf);
3301590Srgrimes	    else
3311590Srgrimes		printf("%s", buf);
3321590Srgrimes	    if (prccont && (psptr >= 0)) {
3331590Srgrimes		ps("'FC ");
3341590Srgrimes		ps(pstack[psptr]);
3351590Srgrimes		ps("\n");
3361590Srgrimes	    }
3371590Srgrimes#ifdef DEBUG
3381590Srgrimes	    printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
3391590Srgrimes#endif
3401590Srgrimes	    margin = 0;
3411590Srgrimes	}
3421590Srgrimes	needbp = 1;
3431590Srgrimes    } while (argc > 0);
3441590Srgrimes    exit(0);
3451590Srgrimes}
3461590Srgrimes
3471590Srgrimes#define isidchr(c) (isalnum(c) || (c) == '_')
3481590Srgrimes
3491590Srgrimesstatic void
350282950SbaptputScp(char *os)
3511590Srgrimes{
3521590Srgrimes    register char *s = os;		/* pointer to unmatched string */
3531590Srgrimes    char dummy[BUFSIZ];			/* dummy to be used by expmatch */
3541590Srgrimes    char *comptr;			/* end of a comment delimiter */
3551590Srgrimes    char *acmptr;			/* end of a comment delimiter */
3561590Srgrimes    char *strptr;			/* end of a string delimiter */
3571590Srgrimes    char *chrptr;			/* end of a character const delimiter */
3581590Srgrimes    char *blksptr;			/* end of a lexical block start */
3591590Srgrimes    char *blkeptr;			/* end of a lexical block end */
36019012Sjoerg    char *nocomptr;			/* end of a non-comment delimiter */
3611590Srgrimes
36236053Sjb    s_start = os;			/* remember the start for expmatch */
363282950Sbapt    _escaped = false;
3641590Srgrimes    if (nokeyw || incomm || instr)
3651590Srgrimes	goto skip;
3661590Srgrimes    if (isproc(s)) {
3671590Srgrimes	ps("'FN ");
3681590Srgrimes	ps(pname);
3691590Srgrimes        ps("\n");
3701590Srgrimes	if (psptr < PSMAX) {
3711590Srgrimes	    ++psptr;
3721590Srgrimes	    strncpy (pstack[psptr], pname, PNAMELEN);
37324543Sjmg	    pstack[psptr][PNAMELEN] = '\0';
3741590Srgrimes	    plstack[psptr] = blklevel;
3751590Srgrimes	}
3768874Srgrimes    }
3771590Srgrimesskip:
3781590Srgrimes    do {
3791590Srgrimes	/* check for string, comment, blockstart, etc */
3801590Srgrimes	if (!incomm && !instr && !inchr) {
3811590Srgrimes
382282950Sbapt	    blkeptr = expmatch(s, l_blkend, dummy);
383282950Sbapt	    blksptr = expmatch(s, l_blkbeg, dummy);
384282950Sbapt	    comptr = expmatch(s, l_combeg, dummy);
385282950Sbapt	    acmptr = expmatch(s, l_acmbeg, dummy);
386282950Sbapt	    strptr = expmatch(s, l_strbeg, dummy);
387282950Sbapt	    chrptr = expmatch(s, l_chrbeg, dummy);
38819012Sjoerg	    nocomptr = expmatch (s, l_nocom, dummy);
3891590Srgrimes
39019012Sjoerg	    /* start of non-comment? */
391282950Sbapt	    if (nocomptr != NULL)
392282950Sbapt		if ((nocomptr <= comptr || comptr == NULL)
393282950Sbapt		  && (nocomptr <= acmptr || acmptr == NULL)) {
39419012Sjoerg		    /* continue after non-comment */
395282950Sbapt		    putKcp (s, nocomptr-1, false);
39619012Sjoerg		    s = nocomptr;
39719012Sjoerg		    continue;
39819012Sjoerg		}
39919012Sjoerg
4001590Srgrimes	    /* start of a comment? */
401282950Sbapt	    if (comptr != NULL)
402282950Sbapt		if ((comptr < strptr || strptr == NULL)
403282950Sbapt		  && (comptr < acmptr || acmptr == NULL)
404282950Sbapt		  && (comptr < chrptr || chrptr == NULL)
405282950Sbapt		  && (comptr < blksptr || blksptr == NULL)
406282950Sbapt		  && (comptr < blkeptr || blkeptr == NULL)) {
407282950Sbapt		    putKcp(s, comptr-1, false);
4081590Srgrimes		    s = comptr;
409282950Sbapt		    incomm = true;
4101590Srgrimes		    comtype = STANDARD;
4111590Srgrimes		    if (s != os)
412282950Sbapt			ps("\\c");
413282950Sbapt		    ps("\\c\n'+C\n");
4141590Srgrimes		    continue;
4151590Srgrimes		}
4161590Srgrimes
4171590Srgrimes	    /* start of a comment? */
418282950Sbapt	    if (acmptr != NULL)
419282950Sbapt		if ((acmptr < strptr || strptr == NULL)
420282950Sbapt		  && (acmptr < chrptr || chrptr == NULL)
421282950Sbapt		  && (acmptr < blksptr || blksptr == NULL)
422282950Sbapt		  && (acmptr < blkeptr || blkeptr == NULL)) {
423282950Sbapt		    putKcp(s, acmptr-1, false);
4241590Srgrimes		    s = acmptr;
425282950Sbapt		    incomm = true;
4261590Srgrimes		    comtype = ALTERNATE;
4271590Srgrimes		    if (s != os)
428282950Sbapt			ps("\\c");
429282950Sbapt		    ps("\\c\n'+C\n");
4301590Srgrimes		    continue;
4311590Srgrimes		}
4321590Srgrimes
4331590Srgrimes	    /* start of a string? */
434282950Sbapt	    if (strptr != NULL)
435282950Sbapt		if ((strptr < chrptr || chrptr == NULL)
436282950Sbapt		  && (strptr < blksptr || blksptr == NULL)
437282950Sbapt		  && (strptr < blkeptr || blkeptr == NULL)) {
438282950Sbapt		    putKcp(s, strptr-1, false);
4391590Srgrimes		    s = strptr;
440282950Sbapt		    instr = true;
4411590Srgrimes		    continue;
4421590Srgrimes		}
4431590Srgrimes
4441590Srgrimes	    /* start of a character string? */
445282950Sbapt	    if (chrptr != NULL)
446282950Sbapt		if ((chrptr < blksptr || blksptr == NULL)
447282950Sbapt		  && (chrptr < blkeptr || blkeptr == NULL)) {
448282950Sbapt		    putKcp(s, chrptr-1, false);
4491590Srgrimes		    s = chrptr;
450282950Sbapt		    inchr = true;
4511590Srgrimes		    continue;
4521590Srgrimes		}
4531590Srgrimes
4541590Srgrimes	    /* end of a lexical block */
455282950Sbapt	    if (blkeptr != NULL) {
456282950Sbapt		if (blkeptr < blksptr || blksptr == NULL) {
457282950Sbapt		    putKcp(s, blkeptr - 1, false);
4581590Srgrimes		    s = blkeptr;
45919012Sjoerg		    if (blklevel > 0 /* sanity */)
46019012Sjoerg			    blklevel--;
4611590Srgrimes		    if (psptr >= 0 && plstack[psptr] >= blklevel) {
4621590Srgrimes
4631590Srgrimes			/* end of current procedure */
4641590Srgrimes			if (s != os)
465282950Sbapt			    ps("\\c");
466282950Sbapt			ps("\\c\n'-F\n");
4671590Srgrimes			blklevel = plstack[psptr];
4681590Srgrimes
4691590Srgrimes			/* see if we should print the last proc name */
4701590Srgrimes			if (--psptr >= 0)
471282950Sbapt			    prccont = true;
4721590Srgrimes			else
4731590Srgrimes			    psptr = -1;
4741590Srgrimes		    }
4751590Srgrimes		    continue;
4761590Srgrimes		}
4771590Srgrimes	    }
4781590Srgrimes
4791590Srgrimes	    /* start of a lexical block */
480282950Sbapt	    if (blksptr != NULL) {
481282950Sbapt		putKcp(s, blksptr - 1, false);
4821590Srgrimes		s = blksptr;
4831590Srgrimes		blklevel++;
4841590Srgrimes		continue;
4851590Srgrimes	    }
4861590Srgrimes
4871590Srgrimes	/* check for end of comment */
4881590Srgrimes	} else if (incomm) {
489282950Sbapt	    comptr = expmatch(s, l_comend, dummy);
490282950Sbapt	    acmptr = expmatch(s, l_acmend, dummy);
491282950Sbapt	    if (((comtype == STANDARD) && (comptr != NULL)) ||
492282950Sbapt	        ((comtype == ALTERNATE) && (acmptr != NULL))) {
4931590Srgrimes		if (comtype == STANDARD) {
494282950Sbapt		    putKcp(s, comptr-1, true);
4951590Srgrimes		    s = comptr;
4961590Srgrimes		} else {
497282950Sbapt		    putKcp(s, acmptr-1, true);
4981590Srgrimes		    s = acmptr;
4991590Srgrimes		}
500282950Sbapt		incomm = false;
5011590Srgrimes		ps("\\c\n'-C\n");
5021590Srgrimes		continue;
5031590Srgrimes	    } else {
504282950Sbapt		putKcp(s, s + strlen(s) -1, true);
5051590Srgrimes		s = s + strlen(s);
5061590Srgrimes		continue;
5071590Srgrimes	    }
5081590Srgrimes
5091590Srgrimes	/* check for end of string */
5101590Srgrimes	} else if (instr) {
511282950Sbapt	    if ((strptr = expmatch(s, l_strend, dummy)) != NULL) {
512282950Sbapt		putKcp(s, strptr-1, true);
5131590Srgrimes		s = strptr;
514282950Sbapt		instr = false;
5151590Srgrimes		continue;
5161590Srgrimes	    } else {
517282950Sbapt		putKcp(s, s+strlen(s)-1, true);
5181590Srgrimes		s = s + strlen(s);
5191590Srgrimes		continue;
5201590Srgrimes	    }
5211590Srgrimes
5221590Srgrimes	/* check for end of character string */
5231590Srgrimes	} else if (inchr) {
524282950Sbapt	    if ((chrptr = expmatch(s, l_chrend, dummy)) != NULL) {
525282950Sbapt		putKcp(s, chrptr-1, true);
5261590Srgrimes		s = chrptr;
527282950Sbapt		inchr = false;
5281590Srgrimes		continue;
5291590Srgrimes	    } else {
530282950Sbapt		putKcp(s, s+strlen(s)-1, true);
5311590Srgrimes		s = s + strlen(s);
5321590Srgrimes		continue;
5331590Srgrimes	    }
5341590Srgrimes	}
5351590Srgrimes
5361590Srgrimes	/* print out the line */
537282950Sbapt	putKcp(s, s + strlen(s) -1, false);
5381590Srgrimes	s = s + strlen(s);
5391590Srgrimes    } while (*s);
5401590Srgrimes}
5411590Srgrimes
542282950Sbapt/*
543282950Sbapt * start: start of string to write
544282950Sbapt * end: end of string to write
545282950Sbapt * force: true if we should force nokeyw
546282950Sbapt */
5471590Srgrimesstatic void
548282950SbaptputKcp(char *start, char *end, bool force)
5491590Srgrimes{
5501590Srgrimes    int i;
5511590Srgrimes    int xfld = 0;
5521590Srgrimes
5531590Srgrimes    while (start <= end) {
5541590Srgrimes	if (idx) {
5551590Srgrimes	    if (*start == ' ' || *start == '\t') {
5568874Srgrimes		if (xfld == 0)
5571798Sphk		    printf("\001");
5581590Srgrimes		printf("\t");
5591590Srgrimes		xfld = 1;
5601590Srgrimes		while (*start == ' ' || *start == '\t')
5611590Srgrimes		    start++;
5621590Srgrimes		continue;
5631590Srgrimes	    }
5641590Srgrimes	}
5651590Srgrimes
5661590Srgrimes	/* take care of nice tab stops */
5671590Srgrimes	if (*start == '\t') {
5681590Srgrimes	    while (*start == '\t')
5691590Srgrimes		start++;
57036053Sjb	    i = tabs(s_start, start) - margin / 8;
5711590Srgrimes	    printf("\\h'|%dn'", i * 10 + 1 - margin % 8);
5721590Srgrimes	    continue;
5731590Srgrimes	}
5741590Srgrimes
5751590Srgrimes	if (!nokeyw && !force)
5768874Srgrimes	    if ((*start == '#' || isidchr(*start))
57736053Sjb	    && (start == s_start || !isidchr(start[-1]))) {
5781590Srgrimes		i = iskw(start);
5791590Srgrimes		if (i > 0) {
5801590Srgrimes		    ps("\\*(+K");
5818874Srgrimes		    do
58218164Sjoerg			putcp((unsigned char)*start++);
5831590Srgrimes		    while (--i > 0);
5841590Srgrimes		    ps("\\*(-K");
5851590Srgrimes		    continue;
5861590Srgrimes		}
5871590Srgrimes	    }
5881590Srgrimes
589282950Sbapt	putcp((unsigned char)*start++);
5901590Srgrimes    }
5911590Srgrimes}
5921590Srgrimes
5931590Srgrimes
5941590Srgrimesstatic int
595282950Sbapttabs(char *s, char *os)
5961590Srgrimes{
5971590Srgrimes
5981590Srgrimes    return (width(s, os) / 8);
5991590Srgrimes}
6001590Srgrimes
6011590Srgrimesstatic int
602282950Sbaptwidth(register char *s, register char *os)
6031590Srgrimes{
6041590Srgrimes	register int i = 0;
6051590Srgrimes
6061590Srgrimes	while (s < os) {
6071590Srgrimes		if (*s == '\t') {
6081590Srgrimes			i = (i + 8) &~ 7;
6091590Srgrimes			s++;
6101590Srgrimes			continue;
6111590Srgrimes		}
6121590Srgrimes		if (*s < ' ')
6131590Srgrimes			i += 2;
6141590Srgrimes		else
6151590Srgrimes			i++;
6161590Srgrimes		s++;
6171590Srgrimes	}
6181590Srgrimes	return (i);
6191590Srgrimes}
6201590Srgrimes
6211590Srgrimesstatic void
622282950Sbaptputcp(register int c)
6231590Srgrimes{
6241590Srgrimes
6251590Srgrimes	switch(c) {
6261590Srgrimes
6271590Srgrimes	case 0:
6281590Srgrimes		break;
6291590Srgrimes
6301590Srgrimes	case '\f':
6311590Srgrimes		break;
6321590Srgrimes
63319012Sjoerg	case '\r':
63419012Sjoerg		break;
63519012Sjoerg
6361590Srgrimes	case '{':
6371590Srgrimes		ps("\\*(+K{\\*(-K");
6381590Srgrimes		break;
6391590Srgrimes
6401590Srgrimes	case '}':
6411590Srgrimes		ps("\\*(+K}\\*(-K");
6421590Srgrimes		break;
6431590Srgrimes
6441590Srgrimes	case '\\':
6451590Srgrimes		ps("\\e");
6461590Srgrimes		break;
6471590Srgrimes
6481590Srgrimes	case '_':
6491590Srgrimes		ps("\\*_");
6501590Srgrimes		break;
6511590Srgrimes
6521590Srgrimes	case '-':
6531590Srgrimes		ps("\\*-");
6541590Srgrimes		break;
6551590Srgrimes
6561590Srgrimes	case '`':
6571590Srgrimes		ps("\\`");
6581590Srgrimes		break;
6591590Srgrimes
6601590Srgrimes	case '\'':
6611590Srgrimes		ps("\\'");
6621590Srgrimes		break;
6631590Srgrimes
6641590Srgrimes	case '.':
6651590Srgrimes		ps("\\&.");
6661590Srgrimes		break;
6671590Srgrimes
6681590Srgrimes	case '*':
6691590Srgrimes		ps("\\fI*\\fP");
6701590Srgrimes		break;
6711590Srgrimes
6721590Srgrimes	case '/':
6731590Srgrimes		ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP");
6741590Srgrimes		break;
6751590Srgrimes
6761590Srgrimes	default:
6771590Srgrimes		if (c < 040)
6781590Srgrimes			putchar('^'), c |= '@';
6791590Srgrimes	case '\t':
6801590Srgrimes	case '\n':
6811590Srgrimes		putchar(c);
6821590Srgrimes	}
6831590Srgrimes}
6841590Srgrimes
6851590Srgrimes/*
6861590Srgrimes *	look for a process beginning on this line
6871590Srgrimes */
688282950Sbaptstatic bool
689282950Sbaptisproc(char *s)
6901590Srgrimes{
69129574Sphk    pname[0] = '\0';
6921590Srgrimes    if (!l_toplex || blklevel == 0)
693282950Sbapt	if (expmatch(s, l_prcbeg, pname) != NULL) {
694282950Sbapt	    return (true);
6951590Srgrimes	}
696282950Sbapt    return (false);
6971590Srgrimes}
6981590Srgrimes
6991590Srgrimes
7001590Srgrimes/*  iskw -	check to see if the next word is a keyword
7011590Srgrimes */
7021590Srgrimes
7031590Srgrimesstatic int
704282950Sbaptiskw(register char *s)
7051590Srgrimes{
7061590Srgrimes	register char **ss = l_keywds;
7071590Srgrimes	register int i = 1;
7081590Srgrimes	register char *cp = s;
7091590Srgrimes
7101590Srgrimes	while (++cp, isidchr(*cp))
7111590Srgrimes		i++;
71287693Smarkm	while ((cp = *ss++))
7131590Srgrimes		if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
7141590Srgrimes			return (i);
7151590Srgrimes	return (0);
7161590Srgrimes}
717