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>
501590Srgrimes#include <string.h>
5128691Scharnier#include <time.h>
521590Srgrimes#include "pathnames.h"
531590Srgrimes#include "extern.h"
541590Srgrimes
551590Srgrimes#define FALSE 0
561590Srgrimes#define TRUE !(FALSE)
571590Srgrimes#define NIL 0
581590Srgrimes#define STANDARD 0
591590Srgrimes#define ALTERNATE 1
601590Srgrimes
611590Srgrimes/*
621590Srgrimes * Vfontedpr.
631590Srgrimes *
641590Srgrimes * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
651590Srgrimes *
661590Srgrimes */
671590Srgrimes
681590Srgrimes#define STRLEN 10		/* length of strings introducing things */
691590Srgrimes#define PNAMELEN 40		/* length of a function/procedure name */
701590Srgrimes#define PSMAX 20		/* size of procedure name stacking */
711590Srgrimes
7292922Simpstatic int       iskw(char *);
7392922Simpstatic boolean   isproc(char *);
7492922Simpstatic void      putKcp(char *, char *, boolean);
7592922Simpstatic void      putScp(char *);
7692922Simpstatic void      putcp(int);
7792922Simpstatic int       tabs(char *, char *);
7892922Simpstatic int       width(char *, char *);
791590Srgrimes
801590Srgrimes/*
811590Srgrimes *	The state variables
821590Srgrimes */
831590Srgrimes
841590Srgrimesstatic boolean  filter = FALSE;	/* act as a filter (like eqn) */
851590Srgrimesstatic boolean	inchr;		/* in a string constant */
861590Srgrimesstatic boolean	incomm;		/* in a comment of the primary type */
871590Srgrimesstatic boolean	idx = FALSE;	/* form an index */
881590Srgrimesstatic boolean	instr;		/* in a string constant */
891590Srgrimesstatic boolean	nokeyw = FALSE;	/* no keywords being flagged */
901590Srgrimesstatic boolean  pass = FALSE;	/*
911590Srgrimes				 * when acting as a filter, pass indicates
921590Srgrimes				 * whether we are currently processing
931590Srgrimes				 * input.
941590Srgrimes				 */
951590Srgrimes
961590Srgrimesstatic int	blklevel;	/* current nesting level */
971590Srgrimesstatic int	comtype;	/* type of comment */
98121547Speterstatic char *	defsfile[2] = { _PATH_VGRINDEFS, 0 };
991590Srgrimes				/* name of language definitions file */
1001590Srgrimesstatic int	margin;
1011590Srgrimesstatic int	plstack[PSMAX];	/* the procedure nesting level stack */
1028874Srgrimesstatic char	pname[BUFSIZ+1];
1031590Srgrimesstatic boolean  prccont;	/* continue last procedure */
1041590Srgrimesstatic int	psptr;		/* the stack index of the current procedure */
1051590Srgrimesstatic char	pstack[PSMAX][PNAMELEN+1];	/* the procedure name stack */
1061590Srgrimes
1071590Srgrimes/*
1081590Srgrimes *	The language specific globals
1091590Srgrimes */
1101590Srgrimes
1111590Srgrimeschar	*l_acmbeg;		/* string introducing a comment */
1121590Srgrimeschar	*l_acmend;		/* string ending a comment */
113228992Suqschar	*l_blkbeg;		/* string beginning of a block */
1141590Srgrimeschar	*l_blkend;		/* string ending a block */
1151590Srgrimeschar    *l_chrbeg;		/* delimiter for character constant */
1161590Srgrimeschar    *l_chrend;		/* delimiter for character constant */
1171590Srgrimeschar	*l_combeg;		/* string introducing a comment */
1181590Srgrimeschar	*l_comend;		/* string ending a comment */
1191590Srgrimeschar	 l_escape;		/* character used to  escape characters */
1201590Srgrimeschar	*l_keywds[BUFSIZ/2];	/* keyword table address */
12119012Sjoergchar	*l_nocom;		/* regexp for non-comments */
1221590Srgrimeschar	*l_prcbeg;		/* regular expr for procedure begin */
1231590Srgrimeschar    *l_strbeg;		/* delimiter for string constant */
1241590Srgrimeschar    *l_strend;		/* delimiter for string constant */
1251590Srgrimesboolean	 l_toplex;		/* procedures only defined at top lex level */
12687693Smarkmconst char *language = "c";	/* the language indicator */
1271590Srgrimes
1281590Srgrimes#define	ps(x)	printf("%s", x)
1291590Srgrimes
13028789Scharnierint
1311590Srgrimesmain(argc, argv)
1321590Srgrimes    int argc;
1331590Srgrimes    char *argv[];
1341590Srgrimes{
13587693Smarkm    const char *fname = "";
1361590Srgrimes    struct stat stbuf;
1371590Srgrimes    char buf[BUFSIZ];
1381590Srgrimes    char *defs;
1391590Srgrimes    int needbp = 0;
1401590Srgrimes
1411590Srgrimes    argc--, argv++;
1421590Srgrimes    do {
1431590Srgrimes	char *cp;
1441590Srgrimes	int i;
1451590Srgrimes
1461590Srgrimes	if (argc > 0) {
1471590Srgrimes	    if (!strcmp(argv[0], "-h")) {
1481590Srgrimes		if (argc == 1) {
1491590Srgrimes		    printf("'ds =H\n");
1501590Srgrimes		    argc = 0;
1511590Srgrimes		    goto rest;
1521590Srgrimes		}
1531590Srgrimes		printf("'ds =H %s\n", argv[1]);
1541590Srgrimes		argc--, argv++;
1551590Srgrimes		argc--, argv++;
1561590Srgrimes		if (argc > 0)
1571590Srgrimes		    continue;
1581590Srgrimes		goto rest;
1591590Srgrimes	    }
1601590Srgrimes
1611590Srgrimes	    /* act as a filter like eqn */
1621590Srgrimes	    if (!strcmp(argv[0], "-f")) {
1631590Srgrimes		filter++;
1641590Srgrimes		argv[0] = argv[argc-1];
16587693Smarkm		argv[argc-1] = strdup("-");
1661590Srgrimes		continue;
1671590Srgrimes	    }
1681590Srgrimes
1691590Srgrimes	    /* take input from the standard place */
1701590Srgrimes	    if (!strcmp(argv[0], "-")) {
1711590Srgrimes		argc = 0;
1721590Srgrimes		goto rest;
1731590Srgrimes	    }
1741590Srgrimes
1751590Srgrimes	    /* build an index */
1761590Srgrimes	    if (!strcmp(argv[0], "-x")) {
1771590Srgrimes		idx++;
17887693Smarkm		argv[0] = strdup("-n");
1791590Srgrimes	    }
1801590Srgrimes
1811590Srgrimes	    /* indicate no keywords */
1821590Srgrimes	    if (!strcmp(argv[0], "-n")) {
1831590Srgrimes		nokeyw++;
1841590Srgrimes		argc--, argv++;
1851590Srgrimes		continue;
1861590Srgrimes	    }
1871590Srgrimes
1881590Srgrimes	    /* specify the font size */
1891590Srgrimes	    if (!strncmp(argv[0], "-s", 2)) {
1901590Srgrimes		i = 0;
1911590Srgrimes		cp = argv[0] + 2;
1921590Srgrimes		while (*cp)
1931590Srgrimes		    i = i * 10 + (*cp++ - '0');
1941590Srgrimes		printf("'ps %d\n'vs %d\n", i, i+1);
1951590Srgrimes		argc--, argv++;
1961590Srgrimes		continue;
1971590Srgrimes	    }
1981590Srgrimes
1991590Srgrimes	    /* specify the language */
2001590Srgrimes	    if (!strncmp(argv[0], "-l", 2)) {
2011590Srgrimes		language = argv[0]+2;
2021590Srgrimes		argc--, argv++;
2031590Srgrimes		continue;
2041590Srgrimes	    }
2051590Srgrimes
2061590Srgrimes	    /* specify the language description file */
2071590Srgrimes	    if (!strncmp(argv[0], "-d", 2)) {
2081590Srgrimes		defsfile[0] = argv[1];
2091590Srgrimes		argc--, argv++;
2101590Srgrimes		argc--, argv++;
2111590Srgrimes		continue;
2121590Srgrimes	    }
2131590Srgrimes
2141590Srgrimes	    /* open the file for input */
21528691Scharnier	    if (freopen(argv[0], "r", stdin) == NULL)
21628691Scharnier		err(1, "%s", argv[0]);
2171590Srgrimes	    if (idx)
2181590Srgrimes		printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
2191590Srgrimes	    fname = argv[0];
2201590Srgrimes	    argc--, argv++;
2211590Srgrimes	}
2221590Srgrimes    rest:
2231590Srgrimes
2241590Srgrimes	/*
2251590Srgrimes	 *  get the  language definition from the defs file
2261590Srgrimes	 */
2271590Srgrimes	i = cgetent(&defs, defsfile, language);
2281590Srgrimes	if (i == -1) {
2291590Srgrimes	    fprintf (stderr, "no entry for language %s\n", language);
2301590Srgrimes	    exit (0);
2318874Srgrimes	} else  if (i == -2) { fprintf(stderr,
2321590Srgrimes	    "cannot find vgrindefs file %s\n", defsfile[0]);
2331590Srgrimes	    exit (0);
2348874Srgrimes	} else if (i == -3) { fprintf(stderr,
2358874Srgrimes	    "potential reference loop detected in vgrindefs file %s\n",
2368874Srgrimes            defsfile[0]);
2371590Srgrimes	    exit(0);
2381590Srgrimes	}
2391590Srgrimes	if (cgetustr(defs, "kw", &cp) == -1)
2401590Srgrimes	    nokeyw = TRUE;
2411590Srgrimes	else  {
2421590Srgrimes	    char **cpp;
2431590Srgrimes
2441590Srgrimes	    cpp = l_keywds;
2451590Srgrimes	    while (*cp) {
2461590Srgrimes		while (*cp == ' ' || *cp =='\t')
24729574Sphk		    *cp++ = '\0';
2481590Srgrimes		if (*cp)
2491590Srgrimes		    *cpp++ = cp;
2501590Srgrimes		while (*cp != ' ' && *cp  != '\t' && *cp)
2511590Srgrimes		    cp++;
2521590Srgrimes	    }
2531590Srgrimes	    *cpp = NIL;
2541590Srgrimes	}
2551590Srgrimes	cgetustr(defs, "pb", &cp);
2561590Srgrimes	l_prcbeg = convexp(cp);
2571590Srgrimes	cgetustr(defs, "cb", &cp);
2581590Srgrimes	l_combeg = convexp(cp);
2591590Srgrimes	cgetustr(defs, "ce", &cp);
2601590Srgrimes	l_comend = convexp(cp);
2611590Srgrimes	cgetustr(defs, "ab", &cp);
2621590Srgrimes	l_acmbeg = convexp(cp);
2631590Srgrimes	cgetustr(defs, "ae", &cp);
2641590Srgrimes	l_acmend = convexp(cp);
2651590Srgrimes	cgetustr(defs, "sb", &cp);
2661590Srgrimes	l_strbeg = convexp(cp);
2671590Srgrimes	cgetustr(defs, "se", &cp);
2681590Srgrimes	l_strend = convexp(cp);
2691590Srgrimes	cgetustr(defs, "bb", &cp);
2701590Srgrimes	l_blkbeg = convexp(cp);
2711590Srgrimes	cgetustr(defs, "be", &cp);
2721590Srgrimes	l_blkend = convexp(cp);
2731590Srgrimes	cgetustr(defs, "lb", &cp);
2741590Srgrimes	l_chrbeg = convexp(cp);
2751590Srgrimes	cgetustr(defs, "le", &cp);
2761590Srgrimes	l_chrend = convexp(cp);
27719097Sjoerg	if (cgetustr(defs, "nc", &cp) >= 0)
27819097Sjoerg		l_nocom = convexp(cp);
2791590Srgrimes	l_escape = '\\';
2801590Srgrimes	l_onecase = (cgetcap(defs, "oc", ':') != NULL);
2811590Srgrimes	l_toplex = (cgetcap(defs, "tl", ':') != NULL);
2821590Srgrimes
2831590Srgrimes	/* initialize the program */
2841590Srgrimes
2851590Srgrimes	incomm = FALSE;
2861590Srgrimes	instr = FALSE;
2871590Srgrimes	inchr = FALSE;
2881590Srgrimes	_escaped = FALSE;
2891590Srgrimes	blklevel = 0;
2901590Srgrimes	for (psptr=0; psptr<PSMAX; psptr++) {
29129574Sphk	    pstack[psptr][0] = '\0';
2921590Srgrimes	    plstack[psptr] = 0;
2931590Srgrimes	}
2941590Srgrimes	psptr = -1;
2951590Srgrimes	ps("'-F\n");
2961590Srgrimes	if (!filter) {
2971590Srgrimes	    printf(".ds =F %s\n", fname);
2981590Srgrimes	    ps("'wh 0 vH\n");
2991590Srgrimes	    ps("'wh -1i vF\n");
3001590Srgrimes	}
3011590Srgrimes	if (needbp) {
3021590Srgrimes	    needbp = 0;
3031590Srgrimes	    printf(".()\n");
3041590Srgrimes	    printf(".bp\n");
3051590Srgrimes	}
3061590Srgrimes	if (!filter) {
3071590Srgrimes	    fstat(fileno(stdin), &stbuf);
3081590Srgrimes	    cp = ctime(&stbuf.st_mtime);
3091590Srgrimes	    cp[16] = '\0';
3101590Srgrimes	    cp[24] = '\0';
3111590Srgrimes	    printf(".ds =M %s %s\n", cp+4, cp+20);
3121590Srgrimes	}
3131590Srgrimes
3141590Srgrimes	/*
3151590Srgrimes	 *	MAIN LOOP!!!
3161590Srgrimes	 */
3171590Srgrimes	while (fgets(buf, sizeof buf, stdin) != NULL) {
3181590Srgrimes	    if (buf[0] == '\f') {
3191590Srgrimes		printf(".bp\n");
3201590Srgrimes	    }
3211590Srgrimes	    if (buf[0] == '.') {
3221590Srgrimes		printf("%s", buf);
3231590Srgrimes		if (!strncmp (buf+1, "vS", 2))
3241590Srgrimes		    pass = TRUE;
3251590Srgrimes		if (!strncmp (buf+1, "vE", 2))
3261590Srgrimes		    pass = FALSE;
3271590Srgrimes		continue;
3281590Srgrimes	    }
3291590Srgrimes	    prccont = FALSE;
3301590Srgrimes	    if (!filter || pass)
3311590Srgrimes		putScp(buf);
3321590Srgrimes	    else
3331590Srgrimes		printf("%s", buf);
3341590Srgrimes	    if (prccont && (psptr >= 0)) {
3351590Srgrimes		ps("'FC ");
3361590Srgrimes		ps(pstack[psptr]);
3371590Srgrimes		ps("\n");
3381590Srgrimes	    }
3391590Srgrimes#ifdef DEBUG
3401590Srgrimes	    printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
3411590Srgrimes#endif
3421590Srgrimes	    margin = 0;
3431590Srgrimes	}
3441590Srgrimes	needbp = 1;
3451590Srgrimes    } while (argc > 0);
3461590Srgrimes    exit(0);
3471590Srgrimes}
3481590Srgrimes
3491590Srgrimes#define isidchr(c) (isalnum(c) || (c) == '_')
3501590Srgrimes
3511590Srgrimesstatic void
3521590SrgrimesputScp(os)
3531590Srgrimes    char *os;
3541590Srgrimes{
3551590Srgrimes    register char *s = os;		/* pointer to unmatched string */
3561590Srgrimes    char dummy[BUFSIZ];			/* dummy to be used by expmatch */
3571590Srgrimes    char *comptr;			/* end of a comment delimiter */
3581590Srgrimes    char *acmptr;			/* end of a comment delimiter */
3591590Srgrimes    char *strptr;			/* end of a string delimiter */
3601590Srgrimes    char *chrptr;			/* end of a character const delimiter */
3611590Srgrimes    char *blksptr;			/* end of a lexical block start */
3621590Srgrimes    char *blkeptr;			/* end of a lexical block end */
36319012Sjoerg    char *nocomptr;			/* end of a non-comment delimiter */
3641590Srgrimes
36536053Sjb    s_start = os;			/* remember the start for expmatch */
3661590Srgrimes    _escaped = FALSE;
3671590Srgrimes    if (nokeyw || incomm || instr)
3681590Srgrimes	goto skip;
3691590Srgrimes    if (isproc(s)) {
3701590Srgrimes	ps("'FN ");
3711590Srgrimes	ps(pname);
3721590Srgrimes        ps("\n");
3731590Srgrimes	if (psptr < PSMAX) {
3741590Srgrimes	    ++psptr;
3751590Srgrimes	    strncpy (pstack[psptr], pname, PNAMELEN);
37624543Sjmg	    pstack[psptr][PNAMELEN] = '\0';
3771590Srgrimes	    plstack[psptr] = blklevel;
3781590Srgrimes	}
3798874Srgrimes    }
3801590Srgrimesskip:
3811590Srgrimes    do {
3821590Srgrimes	/* check for string, comment, blockstart, etc */
3831590Srgrimes	if (!incomm && !instr && !inchr) {
3841590Srgrimes
3851590Srgrimes	    blkeptr = expmatch (s, l_blkend, dummy);
3861590Srgrimes	    blksptr = expmatch (s, l_blkbeg, dummy);
3871590Srgrimes	    comptr = expmatch (s, l_combeg, dummy);
3881590Srgrimes	    acmptr = expmatch (s, l_acmbeg, dummy);
3891590Srgrimes	    strptr = expmatch (s, l_strbeg, dummy);
3901590Srgrimes	    chrptr = expmatch (s, l_chrbeg, dummy);
39119012Sjoerg	    nocomptr = expmatch (s, l_nocom, dummy);
3921590Srgrimes
39319012Sjoerg	    /* start of non-comment? */
39419012Sjoerg	    if (nocomptr != NIL)
39519012Sjoerg		if ((nocomptr <= comptr || comptr == NIL)
39619012Sjoerg		  && (nocomptr <= acmptr || acmptr == NIL)) {
39719012Sjoerg		    /* continue after non-comment */
39819012Sjoerg		    putKcp (s, nocomptr-1, FALSE);
39919012Sjoerg		    s = nocomptr;
40019012Sjoerg		    continue;
40119012Sjoerg		}
40219012Sjoerg
4031590Srgrimes	    /* start of a comment? */
4041590Srgrimes	    if (comptr != NIL)
4051590Srgrimes		if ((comptr < strptr || strptr == NIL)
4061590Srgrimes		  && (comptr < acmptr || acmptr == NIL)
4071590Srgrimes		  && (comptr < chrptr || chrptr == NIL)
4081590Srgrimes		  && (comptr < blksptr || blksptr == NIL)
4091590Srgrimes		  && (comptr < blkeptr || blkeptr == NIL)) {
4101590Srgrimes		    putKcp (s, comptr-1, FALSE);
4111590Srgrimes		    s = comptr;
4121590Srgrimes		    incomm = TRUE;
4131590Srgrimes		    comtype = STANDARD;
4141590Srgrimes		    if (s != os)
4151590Srgrimes			ps ("\\c");
4161590Srgrimes		    ps ("\\c\n'+C\n");
4171590Srgrimes		    continue;
4181590Srgrimes		}
4191590Srgrimes
4201590Srgrimes	    /* start of a comment? */
4211590Srgrimes	    if (acmptr != NIL)
4221590Srgrimes		if ((acmptr < strptr || strptr == NIL)
4231590Srgrimes		  && (acmptr < chrptr || chrptr == NIL)
4241590Srgrimes		  && (acmptr < blksptr || blksptr == NIL)
4251590Srgrimes		  && (acmptr < blkeptr || blkeptr == NIL)) {
4261590Srgrimes		    putKcp (s, acmptr-1, FALSE);
4271590Srgrimes		    s = acmptr;
4281590Srgrimes		    incomm = TRUE;
4291590Srgrimes		    comtype = ALTERNATE;
4301590Srgrimes		    if (s != os)
4311590Srgrimes			ps ("\\c");
4321590Srgrimes		    ps ("\\c\n'+C\n");
4331590Srgrimes		    continue;
4341590Srgrimes		}
4351590Srgrimes
4361590Srgrimes	    /* start of a string? */
4371590Srgrimes	    if (strptr != NIL)
4381590Srgrimes		if ((strptr < chrptr || chrptr == NIL)
4391590Srgrimes		  && (strptr < blksptr || blksptr == NIL)
4401590Srgrimes		  && (strptr < blkeptr || blkeptr == NIL)) {
4411590Srgrimes		    putKcp (s, strptr-1, FALSE);
4421590Srgrimes		    s = strptr;
4431590Srgrimes		    instr = TRUE;
4441590Srgrimes		    continue;
4451590Srgrimes		}
4461590Srgrimes
4471590Srgrimes	    /* start of a character string? */
4481590Srgrimes	    if (chrptr != NIL)
4491590Srgrimes		if ((chrptr < blksptr || blksptr == NIL)
4501590Srgrimes		  && (chrptr < blkeptr || blkeptr == NIL)) {
4511590Srgrimes		    putKcp (s, chrptr-1, FALSE);
4521590Srgrimes		    s = chrptr;
4531590Srgrimes		    inchr = TRUE;
4541590Srgrimes		    continue;
4551590Srgrimes		}
4561590Srgrimes
4571590Srgrimes	    /* end of a lexical block */
4581590Srgrimes	    if (blkeptr != NIL) {
4591590Srgrimes		if (blkeptr < blksptr || blksptr == NIL) {
4601590Srgrimes		    putKcp (s, blkeptr - 1, FALSE);
4611590Srgrimes		    s = blkeptr;
46219012Sjoerg		    if (blklevel > 0 /* sanity */)
46319012Sjoerg			    blklevel--;
4641590Srgrimes		    if (psptr >= 0 && plstack[psptr] >= blklevel) {
4651590Srgrimes
4661590Srgrimes			/* end of current procedure */
4671590Srgrimes			if (s != os)
4681590Srgrimes			    ps ("\\c");
4691590Srgrimes			ps ("\\c\n'-F\n");
4701590Srgrimes			blklevel = plstack[psptr];
4711590Srgrimes
4721590Srgrimes			/* see if we should print the last proc name */
4731590Srgrimes			if (--psptr >= 0)
4741590Srgrimes			    prccont = TRUE;
4751590Srgrimes			else
4761590Srgrimes			    psptr = -1;
4771590Srgrimes		    }
4781590Srgrimes		    continue;
4791590Srgrimes		}
4801590Srgrimes	    }
4811590Srgrimes
4821590Srgrimes	    /* start of a lexical block */
4831590Srgrimes	    if (blksptr != NIL) {
4841590Srgrimes		putKcp (s, blksptr - 1, FALSE);
4851590Srgrimes		s = blksptr;
4861590Srgrimes		blklevel++;
4871590Srgrimes		continue;
4881590Srgrimes	    }
4891590Srgrimes
4901590Srgrimes	/* check for end of comment */
4911590Srgrimes	} else if (incomm) {
4921590Srgrimes	    comptr = expmatch (s, l_comend, dummy);
4931590Srgrimes	    acmptr = expmatch (s, l_acmend, dummy);
4941590Srgrimes	    if (((comtype == STANDARD) && (comptr != NIL)) ||
4951590Srgrimes	        ((comtype == ALTERNATE) && (acmptr != NIL))) {
4961590Srgrimes		if (comtype == STANDARD) {
4971590Srgrimes		    putKcp (s, comptr-1, TRUE);
4981590Srgrimes		    s = comptr;
4991590Srgrimes		} else {
5001590Srgrimes		    putKcp (s, acmptr-1, TRUE);
5011590Srgrimes		    s = acmptr;
5021590Srgrimes		}
5031590Srgrimes		incomm = FALSE;
5041590Srgrimes		ps("\\c\n'-C\n");
5051590Srgrimes		continue;
5061590Srgrimes	    } else {
5071590Srgrimes		putKcp (s, s + strlen(s) -1, TRUE);
5081590Srgrimes		s = s + strlen(s);
5091590Srgrimes		continue;
5101590Srgrimes	    }
5111590Srgrimes
5121590Srgrimes	/* check for end of string */
5131590Srgrimes	} else if (instr) {
5141590Srgrimes	    if ((strptr = expmatch (s, l_strend, dummy)) != NIL) {
5151590Srgrimes		putKcp (s, strptr-1, TRUE);
5161590Srgrimes		s = strptr;
5171590Srgrimes		instr = FALSE;
5181590Srgrimes		continue;
5191590Srgrimes	    } else {
5201590Srgrimes		putKcp (s, s+strlen(s)-1, TRUE);
5211590Srgrimes		s = s + strlen(s);
5221590Srgrimes		continue;
5231590Srgrimes	    }
5241590Srgrimes
5251590Srgrimes	/* check for end of character string */
5261590Srgrimes	} else if (inchr) {
5271590Srgrimes	    if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) {
5281590Srgrimes		putKcp (s, chrptr-1, TRUE);
5291590Srgrimes		s = chrptr;
5301590Srgrimes		inchr = FALSE;
5311590Srgrimes		continue;
5321590Srgrimes	    } else {
5331590Srgrimes		putKcp (s, s+strlen(s)-1, TRUE);
5341590Srgrimes		s = s + strlen(s);
5351590Srgrimes		continue;
5361590Srgrimes	    }
5371590Srgrimes	}
5381590Srgrimes
5391590Srgrimes	/* print out the line */
5401590Srgrimes	putKcp (s, s + strlen(s) -1, FALSE);
5411590Srgrimes	s = s + strlen(s);
5421590Srgrimes    } while (*s);
5431590Srgrimes}
5441590Srgrimes
5451590Srgrimesstatic void
5461590SrgrimesputKcp (start, end, force)
5471590Srgrimes    char	*start;		/* start of string to write */
5481590Srgrimes    char	*end;		/* end of string to write */
5491590Srgrimes    boolean	force;		/* true if we should force nokeyw */
5501590Srgrimes{
5511590Srgrimes    int i;
5521590Srgrimes    int xfld = 0;
5531590Srgrimes
5541590Srgrimes    while (start <= end) {
5551590Srgrimes	if (idx) {
5561590Srgrimes	    if (*start == ' ' || *start == '\t') {
5578874Srgrimes		if (xfld == 0)
5581798Sphk		    printf("\001");
5591590Srgrimes		printf("\t");
5601590Srgrimes		xfld = 1;
5611590Srgrimes		while (*start == ' ' || *start == '\t')
5621590Srgrimes		    start++;
5631590Srgrimes		continue;
5641590Srgrimes	    }
5651590Srgrimes	}
5661590Srgrimes
5671590Srgrimes	/* take care of nice tab stops */
5681590Srgrimes	if (*start == '\t') {
5691590Srgrimes	    while (*start == '\t')
5701590Srgrimes		start++;
57136053Sjb	    i = tabs(s_start, start) - margin / 8;
5721590Srgrimes	    printf("\\h'|%dn'", i * 10 + 1 - margin % 8);
5731590Srgrimes	    continue;
5741590Srgrimes	}
5751590Srgrimes
5761590Srgrimes	if (!nokeyw && !force)
5778874Srgrimes	    if ((*start == '#' || isidchr(*start))
57836053Sjb	    && (start == s_start || !isidchr(start[-1]))) {
5791590Srgrimes		i = iskw(start);
5801590Srgrimes		if (i > 0) {
5811590Srgrimes		    ps("\\*(+K");
5828874Srgrimes		    do
58318164Sjoerg			putcp((unsigned char)*start++);
5841590Srgrimes		    while (--i > 0);
5851590Srgrimes		    ps("\\*(-K");
5861590Srgrimes		    continue;
5871590Srgrimes		}
5881590Srgrimes	    }
5891590Srgrimes
59018164Sjoerg	putcp ((unsigned char)*start++);
5911590Srgrimes    }
5921590Srgrimes}
5931590Srgrimes
5941590Srgrimes
5951590Srgrimesstatic int
5961590Srgrimestabs(s, os)
5971590Srgrimes    char *s, *os;
5981590Srgrimes{
5991590Srgrimes
6001590Srgrimes    return (width(s, os) / 8);
6011590Srgrimes}
6021590Srgrimes
6031590Srgrimesstatic int
6041590Srgrimeswidth(s, os)
6051590Srgrimes	register char *s, *os;
6061590Srgrimes{
6071590Srgrimes	register int i = 0;
6081590Srgrimes
6091590Srgrimes	while (s < os) {
6101590Srgrimes		if (*s == '\t') {
6111590Srgrimes			i = (i + 8) &~ 7;
6121590Srgrimes			s++;
6131590Srgrimes			continue;
6141590Srgrimes		}
6151590Srgrimes		if (*s < ' ')
6161590Srgrimes			i += 2;
6171590Srgrimes		else
6181590Srgrimes			i++;
6191590Srgrimes		s++;
6201590Srgrimes	}
6211590Srgrimes	return (i);
6221590Srgrimes}
6231590Srgrimes
6241590Srgrimesstatic void
6251590Srgrimesputcp(c)
6261590Srgrimes	register int c;
6271590Srgrimes{
6281590Srgrimes
6291590Srgrimes	switch(c) {
6301590Srgrimes
6311590Srgrimes	case 0:
6321590Srgrimes		break;
6331590Srgrimes
6341590Srgrimes	case '\f':
6351590Srgrimes		break;
6361590Srgrimes
63719012Sjoerg	case '\r':
63819012Sjoerg		break;
63919012Sjoerg
6401590Srgrimes	case '{':
6411590Srgrimes		ps("\\*(+K{\\*(-K");
6421590Srgrimes		break;
6431590Srgrimes
6441590Srgrimes	case '}':
6451590Srgrimes		ps("\\*(+K}\\*(-K");
6461590Srgrimes		break;
6471590Srgrimes
6481590Srgrimes	case '\\':
6491590Srgrimes		ps("\\e");
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("\\&.");
6701590Srgrimes		break;
6711590Srgrimes
6721590Srgrimes	case '*':
6731590Srgrimes		ps("\\fI*\\fP");
6741590Srgrimes		break;
6751590Srgrimes
6761590Srgrimes	case '/':
6771590Srgrimes		ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP");
6781590Srgrimes		break;
6791590Srgrimes
6801590Srgrimes	default:
6811590Srgrimes		if (c < 040)
6821590Srgrimes			putchar('^'), c |= '@';
6831590Srgrimes	case '\t':
6841590Srgrimes	case '\n':
6851590Srgrimes		putchar(c);
6861590Srgrimes	}
6871590Srgrimes}
6881590Srgrimes
6891590Srgrimes/*
6901590Srgrimes *	look for a process beginning on this line
6911590Srgrimes */
6921590Srgrimesstatic boolean
6931590Srgrimesisproc(s)
6941590Srgrimes    char *s;
6951590Srgrimes{
69629574Sphk    pname[0] = '\0';
6971590Srgrimes    if (!l_toplex || blklevel == 0)
6981590Srgrimes	if (expmatch (s, l_prcbeg, pname) != NIL) {
6991590Srgrimes	    return (TRUE);
7001590Srgrimes	}
7011590Srgrimes    return (FALSE);
7021590Srgrimes}
7031590Srgrimes
7041590Srgrimes
7051590Srgrimes/*  iskw -	check to see if the next word is a keyword
7061590Srgrimes */
7071590Srgrimes
7081590Srgrimesstatic int
7091590Srgrimesiskw(s)
7101590Srgrimes	register char *s;
7111590Srgrimes{
7121590Srgrimes	register char **ss = l_keywds;
7131590Srgrimes	register int i = 1;
7141590Srgrimes	register char *cp = s;
7151590Srgrimes
7161590Srgrimes	while (++cp, isidchr(*cp))
7171590Srgrimes		i++;
71887693Smarkm	while ((cp = *ss++))
7191590Srgrimes		if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
7201590Srgrimes			return (i);
7211590Srgrimes	return (0);
7221590Srgrimes}
7231590Srgrimes
724