/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <ctype.h>
#include <stdio.h>
#include <locale.h>
#include <euc.h>
#include <stdlib.h>
#define boolean int
#define FALSE 0
#define NIL 0
#define STANDARD 0
/*
* Vfontedpr.
*
* Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
*
*/
/* regular expression routines */
char *expmatch(); /* match a string to an expression */
char *STRNCMP(); /* a different kind of strncmp */
char *convexp(); /* convert expression to internal form */
char *tgetstr(); /* extract a string-valued capability */
char *ctime();
char *strchr();
/*
* The state variables
*/
* whether we are currently processing
* input.
*/
int margin;
may be found, -1 if none currently valid
(meaningful only if l_prclevel is true) */
/*
* The language specific globals
*/
can be found in the next lexical level --
kludge for lisp-like languages that use
something like
(defun (proc ...)
(proc ...)
)
to define procedures */
the nesting level indicated by the px
(l_prcenable) capability */
/*
* for the benefit of die-hards who aren't convinced that tabs
* occur every eight columns
*/
/*
* global variables also used by expmatch
*/
to letters and digits (default "_") */
static void putcp(int c);
static int iskw(char *s);
/*
* The code below emits troff macros and directives that consume part of the
* troff macro and register space. See tmac.vgrind for an enumeration of
* these macros and registers.
*/
int
{
char *fname;
int needbp = 0;
int i;
char *cp;
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
/*
* Dump the name by which we were invoked.
*/
/*
* Process arguments. For the sake of compatibility with older versions
* of the program, the syntax accepted below is very idiosyncratic. Some
* options require space between the option and its argument; others
* disallow it. No options may be bundled together.
*
* Actually, there is one incompatibility. Files and options formerly
* could be arbitrarily intermixed, but this is no longer allowed. (This
* possiblity was never documented.)
*/
case '\0': /* - */
/* Take input from stdin. */
/*
* This option implies the end of the flag arguments. Leave the
* "-" in place for the file processing code to see.
*/
goto flagsdone;
case '2': /* -2 */
/* Enter two column mode. */
twocol = 1;
printf("'nr =2 1\n");
break;
case 'd': /* -d <defs-file> */
/* Specify the language description file. */
break;
case 'f': /* -f */
/* Act as a filter like eqn. */
filter = 1;
/*
* Slide remaining arguments down one position and postpend "-",
* to force reading from stdin.
*/
for (i = 0; i < argc - 1; i++)
continue;
case 'h': /* -h [header] */
/* Specify header string. */
if (argc == 1) {
printf("'ds =H\n");
break;
}
break;
case 'l': /* -l<language> */
/* Specify the language. */
break;
case 'n': /* -n */
/* Indicate no keywords. */
nokeyw = 1;
break;
case 's': /* -s<size> */
/* Specify the font size. */
i = 0;
cp++;
while (*cp)
printf("'nr vP %d\n", i);
break;
case 't': /* -t */
/* Specify a nondefault tab size. */
tabsize = 4;
break;
case 'x': /* -x */
/* Build an index. */
doindex = 1;
/* This option implies "-n" as well; turn it on. */
argv[0] = "-n";
continue;
}
/* Advance to next argument. */
}
/*
* Get the language definition from the defs file.
*/
if (i == 0) {
exit (0);
} else if (i < 0) {
exit (0);
}
else {
char **cpp;
while (*cp) {
if (*cp)
cp++;
}
}
/* Set default, for compatibility with old version */
l_idchars = "_";
l_escape = '\\';
/*
* Emit a call to the initialization macro. If not in filter mode, emit a
* call to the vS macro, so that tmac.vgrind can uniformly assume that all
* program input is bracketed with vS-vE pairs.
*/
printf("'vI\n");
if (!filter)
printf("'vS\n");
if (doindex) {
/*
* XXX: Hard-wired spacing information. This should probably turn
* into the emission of a macro invocation, so that tmac.vgrind
* can make up its own mind about what spacing is appropriate.
*/
if (twocol)
printf("'ta 2.5i 2.75i 4.0iR\n'in .25i\n");
else
printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
}
while (argc > 0) {
/* Embed an instance of the original stdin. */
fname = "";
} else {
/* Open the file for input. */
exit(1);
}
}
/*
* Reinitialize for the current file.
*/
blklevel = 0;
prclevel = -1;
}
psptr = -1;
printf("'-F\n");
if (!filter) {
char *cp;
if (needbp) {
needbp = 0;
printf(".()\n");
printf(".bp\n");
}
printf("'wh 0 vH\n");
printf("'wh -1i vF\n");
}
needbp = 0;
printf(".()\n");
printf(".bp\n");
}
/*
* MAIN LOOP!!!
*/
if (buf[0] == '\f') {
printf(".bp\n");
}
if (buf[0] == '.') {
continue;
}
else
#ifdef DEBUG
#endif
margin = 0;
}
needbp = 1;
}
/* Close off the vS-vE pair. */
if (!filter)
printf("'vE\n");
return (0);
}
static void
{
char *s = os; /* pointer to unmatched string */
goto skip;
if (isproc(s)) {
++psptr;
}
}
/*
* if l_prclevel is set, check to see whether this lexical level
* is one immediately below which procedure definitions are allowed.
*/
}
skip:
do {
/* check for string, comment, blockstart, etc */
/* start of a comment? */
s = comptr;
if (s != os)
printf ("\\c");
printf ("\\c\n'+C\n");
continue;
}
/* start of a comment? */
s = acmptr;
if (s != os)
printf ("\\c");
printf ("\\c\n'+C\n");
continue;
}
/* start of a string? */
s = strptr;
continue;
}
/* start of a character string? */
s = chrptr;
continue;
}
/* end of a lexical block */
/* reset prclevel if necessary */
prclevel = -1;
s = blkeptr;
blklevel--;
/* end of current procedure */
if (s != os)
printf ("\\c");
printf ("\\c\n'-F\n");
/* see if we should print the last proc name */
if (--psptr >= 0)
else
psptr = -1;
}
continue;
}
}
/* start of a lexical block */
s = blksptr;
blklevel++;
continue;
}
/* check for end of comment */
} else if (incomm) {
s = comptr;
} else {
s = acmptr;
}
printf("\\c\n'-C\n");
continue;
} else {
s = s + strlen(s);
continue;
}
/* check for end of string */
} else if (instr) {
s = strptr;
continue;
} else {
s = s + strlen(s);
continue;
}
/* check for end of character string */
} else if (inchr) {
s = chrptr;
continue;
} else {
s = s + strlen(s);
continue;
}
}
/* print out the line */
s = s + strlen(s);
} while (*s);
}
static void
/* start - start of string to write */
/* end - end of string to write */
/* force - true if we should force nokeyw */
{
int i;
int xfld = 0;
if (doindex) {
if (xfld == 0)
printf("");
printf("\t");
xfld = 1;
start++;
continue;
}
}
/* take care of nice tab stops */
if (*start == '\t') {
while (*start == '\t')
start++;
printf ("\\h'|%dn'",
continue;
}
) {
if (i > 0) {
printf("\\*(+K");
do
while (--i > 0);
printf("\\*(-K");
continue;
}
}
}
}
static int
{
}
static int
{
int i = 0;
unsigned char c;
int n;
while (s < os) {
if (*s == '\t') {
s++;
continue;
}
c = *(unsigned char *)s;
if (c < ' ')
i += 2, s++;
else if (c >= 0200) {
if ((n = mblen(s, MB_CUR_MAX)) > 0) {
s += n;
} else
s++;
} else
i++, s++;
}
return (i);
}
static void
putcp(int c)
{
switch(c) {
case 0:
break;
case '\f':
break;
case '{':
printf("\\*(+K{\\*(-K");
break;
case '}':
printf("\\*(+K}\\*(-K");
break;
case '\\':
printf("\\e");
break;
case '_':
printf("\\*_");
break;
case '-':
printf("\\*-");
break;
/*
* The following two cases deal with the accent characters.
* If they're part of a comment, we assume that they're part
* of running text and hand them to troff as regular quote
* characters. Otherwise, we assume they're being used as
* special characters (e.g., string delimiters) and arrange
* for troff to render them as accents. This is an imperfect
* heuristic that produces slightly better appearance than the
* former behavior of unconditionally rendering the characters
* as accents. (See bug 1040343.)
*/
case '`':
if (incomm)
printf("`");
else
printf("\\`");
break;
case '\'':
if (incomm)
printf("'");
else
printf("\\'");
break;
case '.':
printf("\\&.");
break;
/*
* The following two cases contain special hacking
* to make C-style comments line up. The tests aren't
* really adequate; they lead to grotesqueries such
* as italicized multiplication and division operators.
* However, the obvious test (!incomm) doesn't work,
* because incomm isn't set until after we've put out
* the comment-begin characters. The real problem is
* that expmatch() doesn't give us enough information.
*/
case '*':
printf("*");
else
printf("\\f2*\\fP");
break;
case '/':
printf("/");
else
printf("\\f2\\h'\\w' 'u-\\w'/'u'/\\fP");
break;
default:
if (c < 040)
case '\t':
case '\n':
putchar(c);
}
}
/*
* look for a process beginning on this line
*/
isproc(s)
char *s;
{
return (TRUE);
}
return (FALSE);
}
/*
* iskw - check to see if the next word is a keyword
* Return its length if it is or 0 if it isn't.
*/
static int
iskw(char *s)
{
int i = 1;
char *cp = s;
/* Get token length. */
i++;
return (i);
}
return (0);
}