[comp.sources.unix] v16i071: A simple formatter

rsalz@uunet.uu.net (Rich Salz) (11/12/88)

Submitted-by: lee@uhccux.uhcc.hawaii.edu (Greg Lee)
Posting-number: Volume 16, Issue 71
Archive-name: xfmt

[  This will be the last one of these, unless anyone has an nroff
   emulator, as we're moving past the "simple" stage now.
   Note that it uses FLEX, which appeared here several months
   ago.  --r$  ]

Xfmt fills out lines by paragraphs, like the BSD fmt program.
The first version of xfmt, 'extended fmt', was written by Bill Gray
(bgray@marque.mu.edu) and appeared in comp.sources.misc as "fmt".

This version interprets a few nroff -man commands or a (very) few
TeX commands, or both, if you ask it to (by using the -m or -x flags).
It does a more complete job of interpreting fonts in terms of screen
attributes than can be done nroff(1) and ul(1).  There is also a -c flag
for displaying C code with comments highlighted and keywords shown with
various screen attributes.

Many man pages are not correctly processed, since many have nroff
commands not interpreted by xfmt.  The addition of -man interpretation
and other features to xfmt will not be to everyone's taste, especially
since they are incompletely implemented.

The BSD termcap facility is used in this version of xfmt.  Also, you
need flex, by Vern Paxson et al. to make xfmt.  Unless a second version
of flex has been distributed by now, you will need to modify flex's
skeleton files by making the changes described in the REAMDE file.

			--	Greg Lee
U.S.mail: 562 Moore Hall, Dept. of Linguistics, Univ. of Hawaii, HONO, HI 96822
INTERNET: lee@uhccux.uhcc.hawaii.edu
UUCP:     {ihnp4,dcdwest,ucbvax}!sdcsvax!nosc!uhccux!lee
BITNET:   lee@uhccux

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  MANIFEST Makefile README cmds.tex flex.skel.diff xfmt.1 xfmt.l
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(402 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	
X Makefile                   1	
X README                     1	
X cmds.tex                   1	list of formatting commands
X flex.skel.diff             1	patch for flex distribution file
X xfmt.1                     1	man page
X xfmt.l                     1	(f)lex source for xfmt
END_OF_FILE
if test 402 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(791 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# file: xfmt/Makefile
X# 04/88  bgray, rev. 05/88 by Greg Lee
X
X
BINDIR = /usr/lbin
MANDIR = /usr/man/u_man/man1
CATMAN = /usr/catman/u_man/man1
X
LIBS = -ltermcap
CFLAGS = -O
LDFLAGS = -s
CC = /bin/cc
RM = /bin/rm -f
CP = /bin/cp
X
OBJS =
X
X
all: xfmt
X
xfmt:	xfmt.c
X	$(CC) $(CFLAGS) $(LDFLAGS) -o xfmt xfmt.c $(LIBS)
X
xfmt.c:	xfmt.l
X	@rm -f xfmt.c
X	flex -t xfmt.l >xfmt.c
X
xfmt.doc: xfmt.1 xfmt
X	xfmt -jmo xfmt.1 >xfmt.doc
X
shar:	xfmt.l xfmt.1 README Makefile MANIFEST cmds.tex flex.skel.diff
X	@rm -f xfmt.shar
X	makekit -m -nxfmt.shar.
X
install: all xfmt.doc
X	$(CP) xfmt $(BINDIR)
X	chown bin $(BINDIR)/xfmt
X	chgrp bin $(BINDIR)/xfmt
X	chmod 755 $(BINDIR)/xfmt
X	$(CP) xfmt.doc $(CATMAN)/xfmt.1
X	chown bin $(CATMAN)/xfmt.1
X	chgrp bin $(CATMAN)/xfmt.1
X	chmod 644 $(CATMAN)/xfmt.1
X
clean:
X	rm xfmt.c
END_OF_FILE
if test 791 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2168 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
The first version of xfmt, 'extended fmt', was written by Bill Gray
X(bgray@marque.mu.edu) and appeared in comp.sources.misc as "fmt".
Since it is nearly downward compatible with the BSD fmt program
X(treatment of ending sentence punctuation is a little different), you
might choose to name your version "xfmt" -- or not.
X
This version interprets a few nroff -man commands or a (very) few
TeX commands, or both, if you ask it to (by using the -m or -x flags).
It does a more complete job of interpreting fonts in terms of screen
attributes than can be done nroff(1) and ul(1).  There is also a -c flag
for displaying C code with comments highlighted and keywords shown with
various screen attributes.
X
Many man pages are not correctly processed, since many have nroff
commands not interpreted by xfmt.  The addition of -man interpretation
and other features to xfmt will not be to everyone's taste, especially
since they are incompletely implemented.
X
The BSD termcap facility is used in this version of xfmt.  Also, you
need flex, by Vern Paxson et al. to make xfmt.  Unless a second version
of flex has been distributed by now, you will need to modify flex's
skeleton files by making the following changes:
X
CHANGE
static int yy_start;		/* start state number */
TO
static int yy_start = 0;	/* start state number */
X
CHANGE
X	yy_start = 1;		/* first start state */
TO
X	if (!yy_start) yy_start = 1;	/* first start state */
X
Or you can try "patch < flex.skel.diff" to make the changes
automatically in the distributed version of the file flex.skel.  (This
patch file includes another patch concerning the reject action.) The
change to flex is required so xfmt can choose a start condition in its
main() procedure depending on what flags it sees on the command line.
X
Once you have made xfmt, the accompanying documents can be displayed
with:
X	xfmt -mu xfmt.1
X	xfmt -xu cmds.tex
X	xfmt -c xfmt.l
X
X
The amount of pattern matching done in this version of xfmt exceeds the
capacity of lex by quite a bit.  This kind of program is now easy to do
thanks to the implementors of flex:  Vern Paxson, Kevin Gong, Jef
Poskanzer, Van Jacobson.
X
X		Greg Lee, lee@uhccux.uhcc.hawaii.edu
END_OF_FILE
if test 2168 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'cmds.tex' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cmds.tex'\"
else
echo shar: Extracting \"'cmds.tex'\" \(5328 characters\)
sed "s/^X//" >'cmds.tex' <<'END_OF_FILE'
X
X{\it xfmt} formatting commands.}
X\bigskip
X
X\centerline{\it Nroff/man~commands with \tt xfmt~-mu}
X\medskip
X
X\item{\tt .sp~(n)}	Skip 1 (or n) lines.
X\item{\tt \\fI}		Start {\it underlining} of text (termcap "ul").
X\item{\tt \\fB}		Start {\bf bold} text (termcap "md").
X\item{\tt \\fS}		Start {\tt reversed} text (termcap "mr").
X\item{\tt \\fG}		Start {\sl blinking} text (termcap "mb").
X\item{\tt \\fR}		End {\it underlining} or other special text
X			(termcap "me"/"ue").
X\item{\tt \\fP}		Same as {\tt \\fR} (bug).
X\item{\tt .nf}		Stop filling lines to maximum width.
X\item{\tt .fi}		Resume filling lines to maximum width.
X\item{\tt .I~<line>}	Display <line> {\it underlined}.
X\item{\tt .B~<line>}	Display <line> in {\bf bold}.
X\item{\tt .S~<line>}	Display <line> {\tt reversed}.
X\item{\tt .G~<line>}	Display <line> {\sl blinking}.
X\item{\tt .SM~<line>}	Display <line> {\tt reversed}.
X\item{\tt .R~<line>}	Display <line> plain.
X\item{\tt .CT~<char>}	Display <char> reversed or "<CTRL/<char>>"
X			in case neither -u or -o was given.
X\item{\tt \\*(lq}	Display "`".
X\item{\tt \\*(rq}	Display "'".
X\item{\tt \\(*<char>}	Display <char> reversed.
X\item{\tt \\(<char><char>}
X			Display <char><char> reversed.
X\item{\tt \\s(-)<digit>}
X			Ignored.
X\item{\tt \\| \\\^ \\\& \\! \\\{ \\\} \\a \\c \\d \\e \\p \\r \\t \\u \\z}
X			Ignored.
X\item{\tt \\}		Display following character (except as above).
X\item{\tt .br}		Terminate preceding paragraph.
X\item{\tt .PP}		Terminate preceding paragraph.
X\item{\tt .P}		Terminate preceding paragraph.
X\item{\tt .LP}		Terminate preceding paragraph.
X\item{\tt .TP~(n)}	Begin hanging paragraph with 5 (or n) extra
X			spaces of indentation at left, with first
X			following line in left margin.
X\item{\tt .IP~<word>~(0.3i)~...}
X			Begin hanging paragraph with 5 extra
X			spaces of indentation at left, with <word> ...
X			in left margin.
X\item{\tt .HP~(n)}	Begin hanging paragraph with 5 extra
X			spaces of indentation at left.
X\item{\tt .RS}		Indent 5 extra spaces until {\tt .RE}.
X\item{\tt .RE}		Resume normal indent after {\tt .RS}.
X\item{\tt .DS}		Skip a line; preserve lines and spacing;
X			indent 5 extra spaces until {\tt .DE}.
X\item{\tt .DE}		Resume filling and normal indent after {\tt .DS}.
X\item{\tt .EX}		Skip a line; preserve lines and spacing;
X			indent 5 extra spaces until {\tt .EE}.
X\item{\tt .EE}		Skip a line; resume filling and normal indent
X			after {\tt .EX}.
X\item{\tt .VS~<line>}	Ignored.
X\item{\tt .VE~<line>}	Ignored.
X\item{\tt .NT~(<line>)}	Skip a line, indent 5 extra spaces, shorten
X			line length by 5, display {\bf NOTE} bold and
X			centered (or <line>), continue until {\tt .NE}.
X\item{\tt .NE}		Resume normal indent and line length after
X			{\tt .NT}.
X\item{\tt .IR~<words>}	Join words alternating {\it underlined} and plain.
X\item{\tt .BR~<words>}	Join words alternating {\bf bold} and plain.
X\item{\tt .RI~<words>}	Join words alternating plain and {\it underlined}.
X\item{\tt .BI~<words>}	Join words alternating {\bf bold} and {\it underlined}.
X\item{\tt .RB~<words>}	Join words alternating plain and {\bf bold}.
X\item{\tt .IB~<words>}	Join words alternating {\it underlined} and {\bf bold}.
X\item{\tt .SH~<line>}	Skip a line, and display <line> left adjusted
X			and {\bf bold}.
X\item{\tt .SS~<line>}	Skip a line, and display <line> {\bf bold}.
X\item{\tt .TH~<name>~<n>~(<text>)}
X			Right adjust {\bf <name>(<n>)} (followed by <text>).
X\item{\tt .UC~(<digit>)}
X			Ignored.
X\item{\tt .\\"~<line>}	Ignore <line>.
X\item{\tt .PN~<line>}	Underline <line>.
X\item{\tt .ta~<line>}	Ignore <line>.
X\item{\tt .PD~<line>}	Ignore <line>.
X\item{\tt .NX<cap>~<line>}
X			Ignore <line>.
X\item{\tt .DT}		Ignored.
X\item{\tt .ti~+n~<line>}
X			n extra spaces of indentation at left of <line>.
X\item{\tt .MS~<word>~<n>}
X			Display {\it <word>(<n>)}.
X
X
X\bigskip
X\centerline{\it \TeX ~commands with \tt xfmt~-xu}
X\medskip
X
X\item{\tt \\vskip}	Skip a line.
X\item{\tt \\bigskip}	Skip a line.
X\item{\tt \\medskip}	Skip a line.
X\item{\tt \\smallskip}	Skip a line.
X\item{\tt \\\$ \\\# \\\{ \\\} \\\& \\\% \\^ \\_ \\\~ \\' \\" \\\\}
X			Display character following \\.
X\item{\tt\\backslash}	Display \backslash.
X\item{\tt \\it}		Begin {\it underlining} (termcap "ul").
X\item{\tt \\sl}		Begin {\sl blinking} (termcap "mb").
X\item{\tt \\bf}		Begin {\bf bold} (termcap "md").
X\item{\tt \\rm}		Begin plain.
X\item{\tt \\tt}		Begin {\tt reverse} (termcap "mr").
X\item{\tt \\TeX}	Display \TeX.
X\item{\tt \\centerline~<line>}
X			Display <line> centered.
X\item{\tt\\beginsection~<line>}
X			Skip a line, display <line> in bold.
X\item{\tt \\rightline~<line>}
X			Display <line> right adjusted.
X\item{\tt \\raggedright}
X			Stop justifying (for current \{...\} group).
X\item{\tt \\obeylines}	Stop filling lines and preserve spacing
X			(for current \{...\} group).
X\item{\tt \\obeyspaces} Stop filling lines and preserve spacing
X			(for current \{...\} group).
X\item{\tt \\item\{...\}}
X			Start hanging paragraph with 10 extra
X			spaces of left indentation and ... displayed in
X			left margin and indented 5.
X\item{\tt \\itemitem\{...\}}
X			Same as {\tt \\item}.
X\item{\tt \\<space-character>}
X			Break between words.
X\item{\tt \~}		Space that does not break between words and
X			is displayed with current display attribute.
X\item{\tt \$}		Ignored.
X\item{\tt \#}		Ignored.
X
X\bigskip
X\rightline{Greg Lee, May, 1988}
X\bye
END_OF_FILE
if test 5328 -ne `wc -c <'cmds.tex'`; then
    echo shar: \"'cmds.tex'\" unpacked with wrong size!
fi
# end of 'cmds.tex'
fi
if test -f 'flex.skel.diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flex.skel.diff'\"
else
echo shar: Extracting \"'flex.skel.diff'\" \(1605 characters\)
sed "s/^X//" >'flex.skel.diff' <<'END_OF_FILE'
X*** flex.skel.orig	Tue May 31 16:32:11 1988
X--- flex.skel		Tue May 31 16:35:25 1988
X***************
X*** 12,18
X  /* these variables are all declared out here so that section 3 code can
X   * manipulate them
X   */
X! static int yy_start, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p;
X  static int yy_saw_eof, yy_init = 1;
X  
X  /* yy_ch_buf has to be 1 character longer than YY_BUF_SIZE, since when
X
X--- 12,18 -----
X  /* these variables are all declared out here so that section 3 code can
X   * manipulate them
X   */
X! static int yy_start = 0, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p;
X  static int yy_saw_eof, yy_init = 1;
X  
X  /* yy_ch_buf has to be 1 character longer than YY_BUF_SIZE, since when
X***************
X*** 28,33
X  YY_DECL
X      {
X      int yy_n_chars, yy_lp, yy_iii, yy_buf_pos, yy_act;
X  
X  %% user's declarations go here
X  
X
X--- 28,36 -----
X  YY_DECL
X      {
X      int yy_n_chars, yy_lp, yy_iii, yy_buf_pos, yy_act;
X+ #ifdef FLEX_REJECT_ENABLED
X+     int yy_full_match;
X+ #endif
X  
X  %% user's declarations go here
X  
X***************
X*** 34,40
X      if ( yy_init )
X  	{
X  	YY_INIT;
X! 	yy_start = 1;
X  	yy_init = 0;
X  	}
X  
X
X--- 37,43 -----
X      if ( yy_init )
X  	{
X  	YY_INIT;
X! 	if (!yy_start) yy_start = 1;
X  	yy_init = 0;
X  	}
X  
X***************
X*** 41,46
X      goto get_next_token;
X  
X  do_action:
X      for ( ; ; )
X  	{
X  	YY_DO_BEFORE_ACTION
X
X--- 44,55 -----
X      goto get_next_token;
X  
X  do_action:
X+ 
X+ #ifdef FLEX_REJECT_ENABLED
X+     /* remember matched text in case we back up due to trailing context */
X+     yy_full_match = yy_c_buf_p;
X+ #endif
X+ 
X      for ( ; ; )
X  	{
X  	YY_DO_BEFORE_ACTION
END_OF_FILE
if test 1605 -ne `wc -c <'flex.skel.diff'`; then
    echo shar: \"'flex.skel.diff'\" unpacked with wrong size!
fi
# end of 'flex.skel.diff'
fi
if test -f 'xfmt.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xfmt.1'\"
else
echo shar: Extracting \"'xfmt.1'\" \(4161 characters\)
sed "s/^X//" >'xfmt.1' <<'END_OF_FILE'
X.TH XFMT 1 LOCAL
X.SH NAME
xfmt \- a simple text formatter
X.SH SYNOPSIS
X.B xfmt
X[
X.B \-i
X] [
X.B \-j
X] [
X.B \-m
X] [
X.B \-x
X] [
X.B \-o
X] [
X.B \-u
X] [
X.B \-c
X] [
X.B \-l n
X] [
X.B \-p n
X] [
X.B \-t n
X] [ filenames ]
X.SH DESCRIPTION
X.I Xfmt
is a simple text formatter.  With no options present, the default
behavior of
X.I xfmt
is to copy its input (from specified files or from stdin, if no files
are specified) to its output but with input reformatted into lines no
longer than 72 characters long.  A blank line is taken to indicate the
beginning of a new paragraph.  Lines that begin with a period are
preserved.
X.PP
The following options modify this behavior:
X.TP
X.B \-i
This option will cause
X.I xfmt 
to preserve indentations.  Blanks or tabs at the beginning of a line
will be considered the beginning of a new paragraph.
X.TP
X.B \-j
Justify output lines.  (The default behavior of
X.I xfmt
is to output lines with a ragged right margin).
X.TP
X.B \-m
Interpret a few commonly used
X.I nroff
X-man commands.
Those understood (in some fashion) are:
X.DS
X .B .I .R .S .G .SM .C
X .IR .BR .RI .BI .RB .IB
X .SH .SS .TH .PP .P .LP .TP .IP .HP
X .RS .RE .DS .DE .NT .NE .VS .VE
X .CT .PN .MS
X .UC (ignored) .DT (ignored) .PD (ignored)
X.DE
X.sp
And a few other nroff commands that occur commonly in man
pages are recognized:
X.DS
X \\fI \\fB \\fR \\fP \\fC
X .sp .br .nf .fi .ti
X .\\" \\*(lq \\*(rq .ta (ignored)
X.DE
X.sp
More details can be found in the document
X.IR cmds.tex .
X.TP
X.B \-x
Interpret a few commonly used
X.I TeX
commands.
Those understood (in some fashion) are:
X.DS
X \\vskip \\bigskip \\medskip \\smallskip \\$ \\# \\{ \\}
X \\& \\% \\^ \\_ \\~ \\' \\" \\\\ \\it \\sl \\bf \\rm \\tt
X \\TeX \\centerline \\rightline \\raggedright \\obeylines \\item
X { } \\(space) ~ $ (ignored) \\backslash \\beginsection
X.DE
X.TP
X.B \-o
Produce bold and underlined text with overstriking.
If the terminal and termcap entries permit, the bold and underlined
portions can be seen on the screen by feeding
X.I xfmt
output to
X.MS ul 1 .
Bold is produced by fonts B/bf, S/tt, and underlined
by I/it, G/sl.
X.TP
X.B \-u
Produce bold, underlined, reversed, and blinking text for terminal
display (using termcap md, us, mr, and mb entries, respectively).
This is useful only if one of the options -m or -x is also chosen.
Bold is produced by font B/bf, underlined by I/it, reversed by S/tt,
and blinking by G/sl.
X.TP
X.B \-c
XFor C code, display comments reversed, flow-of-control keywords
in bold, storage-class keywords underlined, and pre-processor
keywords blinking.
No formatting is done.  The -u option is assumed unless the -o
option is given.
X.TP
X.B \-l n
This option can be used to change the line length from the default of 72
characters.
X.TP
X.B \-p n
Change the page offset.  This option will cause the output lines to be
offset the indicated number of columns from the left.
X.TP
X.B \-t n
Set tab size.  This option is useful only with the
X.B \-i 
or
X.B \-c
options, or for text in the scope of .nf, .EX, .DS, \obeylines or \obeyspaces,
since otherwise tabs are treated the same as space characters.
X.SH EXAMPLES
Display a man page
X.I binmail.1
on the screen with right justification, a page at a time:
X.EX
xfmt -jmu binmail.1 | more -f
X.EE
Display a man page with underlining, but no bold face:
X.EX
xfmt -mo binmail.1 | more -f
X.EE
Prepare a preformatted man page to be displayed with
X.MS ul 1 :
X.EX
xfmt -mo binmail.1 >binmail.doc
X.EE
Display high-lighted C source code on the screen:
X.EX
xfmt -c \fIfile\fR.c
X.EE
X.SH TIPS
In
X.IR vi ,
you can define a macro that will reformat paragraphs by typing
X.I ":map V {!}xfmt^M" 
or by putting the line
X.RS
X.I "map V {!}xfmt^M"
X.RE
in your
X.I .exrc
file.  After defining this macro, pressing
X.I V 
will cause the paragraph under the cursor to be reformatted.  (Use the
X.I u
key to
X.I undo
if necessary.
X.SH "SEE ALSO"
nroff(1), vi(1), ul(1)
X.SH BUGS
TeX command interpretation doesn't have a chance of working except
for files prepared with the limitations of xfmt in mind.
Nroff -man interpretation has maybe a 50-50 chance.
X.SH AUTHORS
original version: bgray@marque.mu.edu (Bill Gray)
X.br
TeX, man, C mods: lee@uhccux.uhcc.hawaii.edu (Greg Lee)
END_OF_FILE
if test 4161 -ne `wc -c <'xfmt.1'`; then
    echo shar: \"'xfmt.1'\" unpacked with wrong size!
fi
# end of 'xfmt.1'
fi
if test -f 'xfmt.l' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xfmt.l'\"
else
echo shar: Extracting \"'xfmt.l'\" \(21023 characters\)
sed "s/^X//" >'xfmt.l' <<'END_OF_FILE'
X%{
X
X/* 
X * (was file: fmt.c)
X * 04/88  bgray
X * file: xfmt.l
X * revised with (f)lex front end
X * 05/88  Greg Lee
X */
X
X/* a simple text formatter */
X
X#ifndef lint
static	char xfmt_sccsid[] = "@(#)xfmt.l <05/30/88>";
X#endif lint
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X
X#ifndef TRUE
X#define TRUE 1
X#endif
X#ifndef FALSE
X#define FALSE 0
X#endif
X
X/* character attributes controlled by font-changing commands */
X#define ROMAN  1	/* plain, from \rm or .R */
X#define ITALIC 2	/* underlined, from \it or .I */
X#define BOLD   3	/* bold, from \bf or .B */
X#define TTYPE  4	/* reversed, from \tt or .S */
X#define SLANTY 5	/* blinking, from \sl or .G */
X
int     attribute = ROMAN,	/* current character attribute */
X        nextattribute = 0;	/* attribute to restore after next
X				 * word for .RB, etc. or after line
X				 * for \beginsection
X				 */
char    nest[80];		/* stack of attributes for each current */
int	level = 1;		/* TeX {}-group */
X
X/* global state of formatter */
char    iflag  = FALSE,		/* preserving left indentation (-i)? */
X        jflag  = FALSE,		/* requested justification with -j? */
X        oflag  = FALSE,		/* requested overprint with -o? */
X        uflag  = FALSE,		/* requested terminal output with -u? */
X        xflag  = FALSE,		/* requested use TeX commands w. -x? */
X        mflag  = FALSE,		/* requested use man commands w. -m? */
X        cflag  = FALSE,		/* requested format C code w. -c? */
X        qtflag = FALSE,		/* saw odd " in processing .RB etc.? */
X        ceflag = FALSE,		/* center next output line? */
X        raflag = FALSE,		/* right adjust next output line? */
X        obflag = FALSE,		/* not concatenating? */
X        njflag = FALSE;		/* not currently justifying? */
X
int     maxlen  = 72,
X        tabsize = 8,
X        indent  = 0,
X        offset  = 0,
X        tpstate = 0,		/* keep track for hanging indentation */
X        tpvalue = 5,		/* amount of hang, from arg of .TP,.HP */
X        spaces  = 0,		/* space to leave after current word */
X        tempi;			/* misc. use in lex pattern section */
X
char   *progname = NULL;
char   *usage = "usage: %s [-ijcmxou] [-l n] [-p n] [-t n] [file ...]\n";
X
int     dir = FALSE;
int     holecnt = 0;
char   *holeptr[256];		/* holeptr[0] is unused */
X
char	oline[2048] = "\0",	/* output line buffer */
X       *olp = oline,
X        aline[2048] = "\0",	/* output line attribute buffer */
X       *alp = aline,
X        oword[512] = "\0",	/* output word buffer */
X       *owp = oword,
X        aword[512] = "\0",	/* output word attribute buffer */
X       *awp = aword;
X
extern char *optarg;		/* from getopt */
extern int  optind;
X
int     max ();
void    exit ();
char   *basename ();
void    copyindent ();
void    puttc ();
void    putts ();
void    lbreak ();
void    putword ();
void    justifyline ();
void    putline ();
void    sputline ();
void    skipline ();
void    addparens ();
void    terminit ();
void    termattr ();
X
X%}
X
X/* lex start state for flags: -x, -m, (none), -mx, respectively */
X%s	TEX MAN PLAIN ALL CCODE
X
X/* match end of TeX command */
wh	[ \t]*/[^a-z]
X
X%%
X
X<MAN,ALL>^".sp"		skipline(1);
X
X/* match various TeX skip commands */
X<TEX,ALL>\\[a-gi-z]+"skip"{wh}	skipline(1);
X
X/* blank line in input gives blank line in output -- not like real TeX */
X\n$			skipline(1);
X
X<MAN,ALL>^".sp "[0-9]+	skipline(atoi(yytext+4));
X
X/* traditional */
X<PLAIN>^\..* {
X			lbreak();
X			(void)printf("%s\n",yytext);
X}
X
X/* escaped special characters -- \\ for \ not like real TeX */
X<TEX,ALL>\\[$#{}&%^_~'"\\] puttc(yytext[1]);
X
X/* some font-changing commands */
X
X<TEX,ALL>"\\it"{wh} |
X<MAN,ALL>"\\f"("I"|"C")	attribute = ITALIC;
X
X<TEX,ALL>"\\sl"{wh} |
X<MAN,ALL>"\\fG"     	attribute = SLANTY;
X
X<TEX,ALL>"\\bf"{wh} |
X<MAN,ALL>"\\fB"     	attribute = BOLD;
X
X<TEX,ALL>"\\rm"{wh} |
X<MAN,ALL>"\\f"("R"|"P")	attribute = ROMAN; /* \fP should not be like \fR */
X
X<TEX,ALL>"\\tt"{wh} |
X<MAN,ALL>"\\fS"     	attribute = TTYPE;
X
X
X<TEX,ALL>"\\TeX"{wh}	putts("TeX");
X
X/* should these 4 TeX commands cause breaks? */
X<TEX,ALL>\\"centerline"{wh}	ceflag = TRUE;
X
X<TEX,ALL>\\"rightline"{wh}	raflag = TRUE;
X
X<TEX,ALL>\\"raggedright"{wh}	njflag = level;
X
X<TEX,ALL>\\"obeylines"{wh}	obflag = level;
X
X<MAN,ALL>^".nf"		lbreak(); obflag = TRUE;
X
X<MAN,ALL>^".fi"		lbreak(); obflag = FALSE;
X
X<TEX,ALL>"{"		nest[level++] = attribute; /* push attr. onto stack */
X
X<TEX,ALL>"}"  {		/* if emerging from {} in which \obeylines or
X			 * \raggedright occurred, cancel  (not a very general
X			 * strategy)
X			 */
X			if (obflag == level) obflag = FALSE;
X			if (njflag == level) njflag = FALSE;
X			/* pop attribute off stack */
X			if (level > 1) attribute = nest[--level];
X			/* } after \item signals end of tag; will not
X			 * work right with {} inside tag */
X			if (tpstate == 1)  {
X				tpstate = 2;
X				putword();
X			}
X}
X
X
X^[ \t]+ {
X			putword();
X			if (iflag || obflag) {
X				putline();
X				tempi = attribute;
X				/* for comments with indentation */
X				if (cflag) attribute = ROMAN;
X				copyindent(yytext);
X				attribute = tempi;
X			}
X			else if (mflag)
X				putline();
X}
X
X<TEX,ALL>"\\ "		putword();
X
X<MAN,ALL,CCODE>\n  {	/* for C code reverse all of multiline comments */
X			if (!cflag) attribute = ROMAN;
X			nextattribute = qtflag = FALSE;
X			/* signal end of tag for hanging indent */
X			if (tpstate == 1) tpstate = 2;
X			putword();
X			if (obflag) putline();
X}
X
X/* more font-changing */
X
X<MAN,ALL>^\.B" "	attribute = BOLD;
X
X<MAN,ALL>^\.(I|C)" "	attribute = ITALIC;
X
X<MAN,ALL>^\.R" "	attribute = ROMAN;
X
X<MAN,ALL>^\.("S"|"SM")" "	attribute = TTYPE;
X
X<MAN,ALL>^\.G" "	attribute = SLANTY;
X
X<MAN,ALL>\\[\|\^&!{}\nacdeprtuz]		;
X
X<MAN,ALL>\\.		puttc(yytext[1]);
X
X<MAN,ALL>^".ti +"[0-9]+  {
X	 		lbreak();
X			for (tempi = 0; tempi < atoi(yytext+5) - 1; tempi++)
X				puttc(' ');
X}
X
X<MAN,ALL>^\.br 		lbreak();
X
X<MAN,ALL>^\.(P|L|"")P 	skipline(1); indent = 5;
X
X/* hanging indent stuff (awfully complicated) */
X
X<MAN,ALL>^\.(T|H)"P "[0-9]+\n  {
X			skipline(1);
X			if (yytext[1] == 'H')
X				tpstate = 4;
X			else	tpstate = 1;
X			tpvalue = atoi(yytext+4);
X			indent = 5;
X}
X
X<TEX,ALL>\\"item"("item")?{wh}  |
X<MAN,ALL>^".HP ".*\n	|
X<MAN,ALL>^".TP".*\n	|
X<MAN,ALL>^".IP"[ \t]*\n?  {
X			skipline(1);
X			if (yytext[1] == 'I' && yytext[3] == '\n')
X				tpstate = 4;
X			else	tpstate = 1;
X			tpvalue = 5;
X			indent = 5;
X}
X
X/* various begin-end commands to set off blocks of text */
X
X<MAN,ALL>^"."(R|D)(S|E)  {
X			if (yytext[1] == 'D' && yytext[2] == 'S') {
X				skipline(1);
X				obflag = TRUE;
X			}
X			else	lbreak();
X			indent = 10;
X			if (yytext[2] == 'E') {
X				indent = 5;
X				obflag = FALSE;
X			}
X}
X
X<MAN,ALL>^".E"(X|E)  {
X			skipline(1);
X			if (yytext[2] == 'E') {
X				indent = 5;
X				obflag = FALSE;
X			}
X			else {	indent = 10;
X				obflag = TRUE;
X			}
X}
X
X
X<MAN,ALL>^".N"(T|E).*  {
X			skipline(1);
X			if (yytext[2] == 'E') {
X				indent = 5;
X				maxlen += 5;
X			}
X			else {	indent = 10;
X				maxlen -= 5;
X				tempi = attribute;
X				attribute = ITALIC;
X				ceflag = TRUE;
X				if (yyleng < 5) putts("NOTE");
X				else putts(yytext+4);
X				skipline(1);
X			}
X}
X
X/* those curious -man commands to join words, alternating fonts */
X
X<MAN,ALL>^\.("IR"|"PN")" "	nextattribute = ROMAN; attribute = ITALIC;
X
X<MAN,ALL>^\."BR "	nextattribute = ROMAN; attribute = BOLD;
X
X<MAN,ALL>^\."RI "	nextattribute = ITALIC; attribute = ROMAN;
X
X<MAN,ALL>^\."BI "	nextattribute = ITALIC; attribute = BOLD;
X
X<MAN,ALL>^\."RB "	nextattribute = BOLD; attribute = ROMAN;
X
X<MAN,ALL>^\."IB "	nextattribute = BOLD; attribute = ITALIC;
X
X/* section headings */
X
X<TEX,ALL>\\"beginsection"{wh}  {
X			skipline(1);
X			nextattribute = attribute;
X			attribute = BOLD;
X}
X
X<MAN,ALL>^\."S"(H|S)" ".* {
X			skipline(1);
X			if (yytext[2] == 'H')
X				indent = 0;
X			attribute = BOLD;
X			putts(yytext+4);
X			lbreak();
X			indent = 5;
X			attribute = ROMAN;
X}
X
X<MAN,ALL>^\."TH ".* {
X			lbreak();
X			indent = 0;
X			addparens(yytext+4, BOLD);
X			raflag = TRUE;
X			skipline(2);
X			indent = 5;
X}
X
X/* "Manual Section" reference */
X<MAN,ALL>^".MS ".*	addparens(yytext+4, ITALIC);
X
X<MAN,ALL>^".CT ".  {
X			if (uflag || oflag) {
X				tempi = attribute;
X				attribute = TTYPE;
X				puttc(toupper(yytext[4]));
X				attribute = tempi;
X			}
X			else {
X				putts("<CTRL/");
X				puttc(yytext[4]);
X				puttc('>');
X			}
X}
X
X<MAN,ALL>^".V"(S|E).* |
X<MAN,ALL>^".UC"(..)?  |
X<MAN,ALL>^\.\\\".*	;
X
X/* for join-words commands, words can be quoted */
X<MAN,ALL>\"  {
X			if (nextattribute || tpstate == 1)  {
X				qtflag = !qtflag;
X			}
X			else puttc('"');
X}
X
X<MAN,ALL,CCODE>" "  {
X			if (nextattribute)  {
X				if (qtflag) puttc(' ');
X				else  {
X					tempi = attribute;
X					attribute = nextattribute;
X					nextattribute = tempi;
X				}
X			}
X			else {
X				putword();
X				if (obflag) copyindent(yytext);
X			}
X}
X
X<TEX,ALL,CCODE>\n  {
X			putword();
X			if (obflag || nextattribute) putline();
X			if (nextattribute) {
X				attribute = nextattribute;
X				nextattribute = 0;
X			}
X}
X
X<TEX,ALL>"~"			puttc(' ');
X
X[ \t]+  {
X			putword();
X			if (obflag) copyindent(yytext);
X}
X
X[\n\r\f]			putword();
X
X<TEX,ALL>\\"backslash"{wh}	puttc('\\');
X
X<TEX>\\    |
X<TEX,ALL>\$|\#			;
X
X<TEX,ALL>\\[A-Za-z]+{wh}	;
X
X<MAN,ALL>\\"*(rq"	puttc('\'');
X
X<MAN,ALL>\\"*(lq"	puttc('`');
X
X<MAN,ALL>\\"("..  {
X			tempi = attribute;
X			attribute = TTYPE;
X			if (yytext[2] != '*') puttc(yytext[2]);
X			puttc(yytext[3]);
X			attribute = tempi;
X}
X
X<MAN,ALL>\\"s"("-")?[0-9] |
X<MAN,ALL>"\\*S"		|
X<MAN,ALL>^".DT"		|
X<MAN,ALL>^".ta ".*	|
X<MAN,ALL>^".PD".*	|
X<MAN,ALL>^".NX".*	;
X
X<CCODE>\"	{	if (attribute != TTYPE) qtflag = !qtflag;
X			puttc('"');
X}
X
X<CCODE>"/*"	{	puttc('/');
X			if (!qtflag) attribute = TTYPE;
X			puttc('*');
X}
X
X<CCODE>"*/"	{	puttc('*');
X			if (!qtflag) attribute = ROMAN;
X			puttc('/');
X}
X
X/* control flow keywords are bold */
X<CCODE>"continue"|"default"|"do"|"goto"|"return"  |
X<CCODE>"if"|"else"|"while"|"break"|"switch"|"case"|"for"  {
X			if (attribute != TTYPE && !qtflag) {
X				attribute = BOLD;
X				putts(yytext);
X				attribute = ROMAN;
X			} else putts(yytext);
X}
X
X/* storage class keywords are underlined */
X<CCODE>("auto"|"char"|"double"|"enum"|"extern"|"float")  |
X<CCODE>("int"|"long"|"register"|"short"|"sizeof"|"static") |
X<CCODE>("struct"|"typedef"|"union"|"unsigned"|"void") {
X
X			if (attribute != TTYPE && !qtflag) {
X				attribute = ITALIC;
X				putts(yytext);
X				attribute = ROMAN;
X			} else putts(yytext);
X}
X
X/* preprocessor keywords are blinking */
X<CCODE>"#"[ \t]*("define"|"undef"|"include"|"if"|"ifdef")  |
X<CCODE>"#"[ \t]*("ifndef"|"else"|"endif"|"line")  {
X
X			if (attribute != TTYPE && !qtflag) {
X				attribute = SLANTY;
X				putts(yytext);
X				attribute = ROMAN;
X			} else putts(yytext);
X}
X
X/* identifiers that happen to contain keywords are plain */
X<CCODE>[a-zA-Z_]+	putts(yytext);
X
X.			puttc(yytext[0]);
X
X
X
X%%
X
X/*
X * Characters, along with the currently active "font"= screen
X * attribute, are collected in a word buffer until we hit a
X * word break (white space), then moved to a line buffer.
X * Words are collected in the line buffer until we hit a line
X * break (end of paragraph) or the line is long enough, then
X * the line is output.
X */
X
main (argc, argv)
int     argc;
char   *argv[];
X{
X	int     c, i;
X
X	progname = basename (argv[0]);
X	while ((c = getopt (argc, argv, "ijcxmoul:p:t:")) != EOF)
X		switch (c) {
X			case 'i': iflag = TRUE; break;
X			case 'j': jflag = TRUE; break;
X			case 'c': cflag = TRUE; break;
X			case 'x': xflag = TRUE; break;
X			case 'm': mflag = TRUE; break;
X			case 'o': oflag = TRUE; break;
X			case 'u': uflag = TRUE; break;
X			case 'l': maxlen = max (0, atoi (optarg));
X				  break;
X			case 'p': offset = max (0, atoi (optarg));
X				  break;
X			case 't': tabsize = max (1, atoi (optarg));
X				  break;
X			default: (void) fprintf (stderr, usage, progname);
X				  exit (1);
X				  break;
X		}
X
X
X/* set lex start state */
X	if (xflag && mflag) {
X		BEGIN (ALL);
X	}
X	else if (xflag) {
X		BEGIN (TEX);
X	}
X	else if (mflag) {
X		indent = 5;
X		BEGIN (MAN);
X	}
X	else if (cflag) {
X		obflag = TRUE;
X		if (!oflag) uflag = TRUE;
X		BEGIN (CCODE);
X	}
X	else {
X		BEGIN (PLAIN);
X	}
X
X/* consult termcap for terminal controls */
X	if (uflag)
X		terminit ();
X
X
X/* call lex scanner */
X	if (optind >= argc) {
X		(void) yylex ();
X		lbreak ();
X	}
X	else
X		for (; (optind < argc); optind++) {
X			if (freopen (argv[optind], "r", yyin) != NULL) {
X				/* unstructured -- couldn't find any other
X				 * way to get flex to look at > 1 file */
X				yy_init = 1;
X				(void) yylex ();
X				lbreak ();
X			}
X			else {
X				(void) fprintf (stderr,
X				    "Couldn't open file: %s", argv[optind]);
X				exit (1);
X			}
X		}
X
X	return (0);
X}				/* main */
X
X
X/* preserve spacing due to spaces or tabs */
void	copyindent (ilp)
char	*ilp;
X{
X	int     col;
X
X	col = (olp - oline) + 1;
X
X	for (; (isspace (*ilp)); col++) {
X		if (*ilp++ == '\t')
X			for (; (col % tabsize); col++) {
X				*olp++ = ' ';
X				*alp++ = (cflag) ? attribute : ROMAN;
X			}
X		*olp++ = ' ';
X		*alp++ = (cflag) ? attribute : ROMAN;
X	}
X}				/* copyindent */
X
X/* one character goes into word buffer */
void puttc (ch)
char    ch;
X{
X	*owp++ = ch;
X	*awp++ = attribute;
X}				/* puttc */
X
X/* put string in word buffer (might have spaces) */
void putts (s)
char   *s;
X{
X	while (*s)
X		puttc (*s++);
X}				/* putts */
X
X/* finish pending word and line and put it out (no justification) */
void lbreak () {
X	putword ();
X	putline ();
X	tpstate = 0;
X}				/* lbreak */
X
X/* append pending word to line buffer */
void putword () {
X	int     plen;
X	char   *p;
X	char   *q;
X	static char     started = 0;
X
X	/* just return if no characters have been accumulated yet */
X	if (owp == oword) {
X		/* this is for the special case in which a file
X		 * starts with \n, which should count as  a "blank line"
X		 */
X		if (!started) {
X			putchar ('\n');
X			started = 1;
X		}
X		return;
X	}
X	started = 1;
X
X	puttc ('\0');
X	p = oword;
X	q = aword;
X	plen = strlen (p);
X
X	/* ugly way to ignore "0.3i" arg of .IP */
X	if (tpstate == 2 && *p == '0' && p[plen - 1] == 'i') {
X		spaces = plen = 0;
X		*p = '\0';
X	}
X
X	/* finish pending line if pending word won't fit */
X	if (!obflag && (olp - oline) + spaces + plen > maxlen - indent) {
X		if ((jflag) && (holecnt) && !njflag)
X			justifyline ();
X		putline ();
X	}
X
X	/* append spaces which were previously decided to go after
X	 * last word put in line buffer */
X	if (spaces) {
X		/* don't use space inside tag of hanging indent to
X		 * right justify */
X		if (!tpstate || tpstate > 3)
X			holeptr[++holecnt] = olp;
X		/* if tag already padded out, permit justification
X		 * of space after next word */
X		if (tpstate == 3)
X			tpstate = 4;
X		for (; (spaces > 0); spaces--) {
X			*olp++ = ' ';
X			/* a matter of taste -- put just " = ROMAN"
X			 * for no underlined spaces between words */
X			*alp++ = (*(alp-1) == ITALIC && *q == ITALIC) ?
X				ITALIC : ROMAN;
X		}
X	}
X
X	/* figure spaces which should go after pending word which
X	 * is just about to be appended in line buffer -- remember
X	 * so they can be put before next word (cf. just above) */
X	if (!obflag) spaces = 1 + endofsentence (p, plen);
X	/* (but if spacing is being preserved, as signaled by
X	 *  obflag, we don't want extra spaces) */
X
X	/* append pending word in line buffer */
X	while (*p) {
X		*olp++ = *p++;
X		*alp++ = *q++;
X	}
X
X	/* part of tortuous way of handling hanging indent */
X		/* tpstate = 0: no hanging indent
X		 *	     1: scanning tag to go in left margin
X		 *	     2: have seen end of tag, time to
X		 *		pad out tag to hanging indent value
X		 *	     3: finished padding
X		 *	     4: finished first line of hanging par.;
X		 *		subsequent lines should be indented
X		 *		to hanging indent value
X		 */
X	if (tpstate == 2) {	/* time to pad tag? */
X		tpstate = 3;	/* signal padding done */
X		if ((olp - oline) + spaces > tpvalue) /* will tag fit? */
X			putline ();	/* no it won't, so start new line */
X		else		/* yes it will, so pad it out */
X			while ((olp - oline) + spaces < tpvalue)
X				spaces++;
X	}
X
X	/* purge word buffer -- get ready for next word */
X	owp = oword;
X	awp = aword;
X}				/* putword */
X
X
X/* increase inter-word spacings for right justification */
void justifyline () {
X	int     n;
X	char   *fp,
X	       *tp,
X	       *fa,
X	       *ta;
X
X	dir = (!(dir));
X	fp = olp - 1;
X	fa = alp - 1;
X	olp = &oline[maxlen - indent];
X	alp = &aline[maxlen - indent];
X	tp = olp - 1;
X	ta = alp - 1;
X	while (tp > fp) {
X		while (fp >= holeptr[holecnt]) {
X			*tp-- = *fp--;
X			*ta-- = *fa--;
X		}
X		if (dir)
X			n = ((tp - fp) - 1) / holecnt + 1;
X		else
X			n = (tp - fp) / holecnt;
X		while (n--) {
X			*tp-- = ' ';
X			*ta-- = ta[1];
X		}
X		holecnt--;
X	}
X}				/* justifyline */
X
X
X/* put out pending line in line buffer */
void putline ()
X{
X	if (ceflag) {
X		spaces = max ((maxlen - (olp - oline)) / 2, 1) + offset;
X		ceflag = FALSE;
X	}
X	else if (raflag) {
X		spaces = max ((maxlen - (olp - oline)), 1) + offset;
X		raflag = FALSE;
X	}
X	else	spaces = indent + offset;
X
X	*olp = '\0';
X
X	if (*oline)
X		/* if -u or -x options, have to do it character
X		 * by character */
X		if (oflag || uflag)
X			sputline ();
X	else
X			(void) printf ("%*s\n", spaces + strlen (oline), oline);
X
X	/* purge line buffer -- get ready for new line */
X	*oline = '\0';
X	olp = oline;
X	alp = aline;
X	spaces = 0;
X	holecnt = 0;
X
X	/* if finished with first line of hanging par., increase
X	 * left indent for subsequent lines */
X	if (tpstate > 2) {
X		indent = tpvalue + 5;
X		tpstate = 4;
X	}
X}				/* putline */
X
X
X/* display characters of line with overstriking or with special
X * terminal attributes */
void sputline () {
X	char   *p;
X	char   *q;
X	char    last = ROMAN;
X
X	if (spaces)
X		(void) printf ("%*s", spaces, NULL);
X
X	for (p = oline, q = aline; *p; p++, q++)
X		if (uflag) {
X			last = newattr (last, *q);
X			(void) printf ("%c", *p);
X		} else
X		switch (*q) {
X			case ROMAN: 
X				(void) printf ("%c", *p);
X				break;
X			case BOLD: 
X			case TTYPE: 
X				if (*p == ' ')
X					printf("%c", *p);
X				else	(void) printf ("%c%c%c", *p, 8, *p);
X				break;
X			case ITALIC: 
X			case SLANTY: 
X				(void) printf ("_%c%c", 8, *p);
X				break;
X		}
X	if (uflag)
X		last = newattr (last, ROMAN);
X	(void) printf ("\n");
X
X}				/* sputline */
X
X/* put blank lines */
void skipline (n)
int     n;
X{
X	lbreak ();
X	for (; (n > 0); n--)
X		(void) printf ("\n");
X	if (xflag)
X		indent = 0;
X}				/* skipline */
X
X
X/* decide how many spaces go after word */
int     endofsentence (p, plen)
char   *p;
int     plen;
X{
X	if (plen < 3)
X		return (FALSE);
X	if (!strchr (".:?!", *(p + plen - 1)))
X		return (FALSE);
X	if (abbr (p))
X		return (FALSE);
X	return (TRUE);
X}				/* endofsentence */
X
X
X/* detect "." which is not real end of sentence */
int     abbr (s)
char   *s;
X{
X	char   *p,
X	       *q,
X	       *r;
X
X	while (*s == '(')
X		s++;
X	q = ".i.e.g.dr.mr.mrs.st.";
X	for (; (*q); q++) {
X		p = q;
X		r = s;
X		while ((*r) && (*p++ == (*r++ | 0x20)));
X		if (!*r)
X			return (TRUE);
X	}
X	return (FALSE);
X}				/* abbr */
X
X
X
char   *basename (s)
char   *s;
X{
X	char   *p;
X
X	if (p = strrchr (s, '/'))
X		return (++p);
X	else
X		return (s);
X}				/* basename */
X
X
X
int     max (a, b)
int     a,
X        b;
X{
X	return ((a > b) ? a : b);
X}				/* max */
X
X
X/* put parentheses around number of manual section */
void addparens (s, a)
char   *s;
int     a;
X{
X	nextattribute = attribute;
X	attribute = a;
X	while (*s && *s != ' ')
X		puttc (*s++);
X	if (*s == ' ')
X		s++, puttc ('(');
X	while (*s && *s != ' ')
X		puttc (*s++);
X	if (*s == ' ')
X		s++;
X	puttc (')');
X	attribute = nextattribute;
X	nextattribute = 0;
X	if (*s && isalpha (*s))
X		puttc (' ');
X	while (*s)
X		puttc (*s++);
X}				/* addparens */
X
X/* terminal commands -- accessing routines */
X
X/*
X *  following derived from:
X *  tcap v1.0 Enhanced terminal control program
X *  Author: Eric Lorenzo Lim
X *  Modified by: Becca Thomas and Rik Farrow
X *  (appeared in Nov. '87 Unix World)
X */
X
X#define SO 0
X#define SE 1
X#define MB 2
X#define MD 3
X#define MR 4
X#define MH 5
X#define ME 6
X#define US 7
X#define UE 8
char   *id[] = {
X	"so", "se", "mb", "md", "mr", "mh", "me", "us", "ue",
X	(char *) NULL,
X};
X
char   *area[50];
char    bp[1024],
X        strbuf[1024];
X
X/* get for later use terminal handling commands we need */
void terminit () {
X	int     id_size = 0;
X	char   *str,
X	       *tmpptr;
X	extern char    *getenv (), *tgetstr (), *tgoto ();
X
X	if ((tmpptr = getenv ("TERM")) == (char *) NULL) {
X		(void) fprintf (stderr, "xfmt: TERM variable not set\n");
X		exit (1);
X	}
X
X	str = strbuf;
X
X	if (tgetent (bp, tmpptr))
X		while (id[id_size] != (char *) NULL) {
X			area[id_size] = tgetstr (id[id_size], &str);
X			if (area[id_size] == (char *) NULL)
X				area[id_size] = "";
X			id_size++;
X		}
X
X
X}				/* terminit */
X
X/* put out a terminal handing command */
void termattr (i)
int     i;
X{
X	(void) printf ("%s", area[i]);
X}				/* termattr */
X
X/* check for change of "font" and send command to terminal
X * when there is a change */
int     newattr (l, a)
int     l,	/* last attribute */
X        a;	/* new attribute */
X{
X	if (l != a) {
X		if (l == BOLD || l == TTYPE || l == SLANTY)
X			termattr (ME);
X		else if (l == ITALIC)
X			termattr (UE);
X
X		switch (a) {
X			case   BOLD:	termattr (MD); break;
X			case ITALIC:	termattr (US); break;
X			case  TTYPE:	termattr (MR); break;
X			case SLANTY:	termattr (MB); break;
X		}
X	}
X	return (a);
X}				/* newattr */
X
END_OF_FILE
if test 21023 -ne `wc -c <'xfmt.l'`; then
    echo shar: \"'xfmt.l'\" unpacked with wrong size!
fi
# end of 'xfmt.l'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

         -- Greg, lee@uhccux.uhcc.hawaii.edu

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.