[comp.sources.misc] v13i092: lj2ps

lishka@uwslh.slh.wisc.edu (Chris Lishka (relaxing in the Mad-City) ) (07/03/90)

Posting-number: Volume 13, Issue 92
Submitted-by: lishka@uwslh.slh.wisc.edu (Chris Lishka (relaxing in the Mad-City) )
Archive-name: lj2ps/part07

---- Cut Here and unpack ----
#!/bin/sh
# This is part 07 of a multipart archive
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= doc/LogFile ==============
if test X"$1" != X"-c" -a -f 'doc/LogFile'; then
	echo "File already exists: skipping 'doc/LogFile'"
else
echo "x - extracting doc/LogFile (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/LogFile &&
XProject:	lj2ps, LaserJet PCL to PostScript translator
XFile:		LogFile
X
XAuthor:		Christopher Lishka
XOrganization:	Wisconsin State Laboratory of Hygiene
X		Data Processing Department
X
XRCS:	$Header: LogFile,v 1.1 90/06/30 15:54:36 lishka Release $
X
X
X063090 - v1.1 - Chris Lishka
X
XThis is the version I am releasing to the general public through
Xcomp.sources.misc.  lj2ps is identical to the 1.0.1.2 local version.
XHowever, I have updated and cleaned up the documentation for this
Xrelease revision.  I also redrew the two scanners with idraw, as much
Xso that I could remember how they work as for other people.
X
X
X061690 - v1.0.1.2 - Chris Lishka
X
XThis is a local revision which fixes a very major bug as well as
Xadding some functionality for those who want to extend this program.
X
XI have added support for tabs.  They function identically to LaserJet
Xtabs for fixed-spacing fonts.  However, the LaserJet does some really
Xstupid things with proportional font tabs, and I chose to use
Xsomething completely different (and more logical) for proportional
Xfonts.  As a small step to indicate incompatibility, a warning is
Xprinted if tabs are used while using a proportional font.  My logic is
Xthat people ought not to be using the brain-damaged LaserJet
Xproportional tabs anyways.
X
XHooks are now present in the scanner for detecting shift-in and
Xshift-out.  Unique tokens are returned for both.  However, shift-in
Xand shift-out are not recognized by the "parser" (actually, the
Xfunction transform()), so only warnings are produced now.  On the
Xother hand, if anyone wants to *add* shift-in and shift-out
Xcapabilities (hint, hint, wink, wink, nudge, nudge ;-), they won't
Xhave to bugger-up the scanner to achieve this (which is somewhat of a
Xpain). 
X
X
X061390 - v1.0.1.1 - Chris Lishka
X
XThis is a new local revision, which is built off the 1.0 major
Xrevision.  It fixes a serious bug, and a few minor ones.
X
XThe 8.5 inch default right margin has been changed to a "very large"
Xright margin.  This fixes the right margin problem when rotating to
Xlandscape mode.
X
XI have added a command-line option -w, which (when set) suppresses
Xwarning messages.
X
XI have added a compile-time option -DDEBUG which controls whether or
Xnot debugging code is included in the executable.  If -DDEBUG is
Xincluded, an extra -d command-line option is available to turn on
Xdifferent levels of diagnostic debugging output.
X
XI have added a compile-time option -DVERBOSE_WARNINGS which controls
Xwhether all types of of warnings are printed.  If not set, only
Ximportant warnings will be printed out.  If set, *all* types of
Xwarnings (both important and trivial) will be printed.
X
X
X060790 - v1.0 - Chris Lishka
X
XThe initial revision of lj2ps.  This version is currently running,
Xalthough the one I am checking in right now has a minor efficiency fix
X(which keeps lj_match_font from running once per attribute!).  This is
Xnot the revision which will be distributed, as that one must have a
Xproper copyright notice attached.
SHAR_EOF
$TOUCH -am 0630160790 doc/LogFile &&
chmod 0644 doc/LogFile ||
echo "restore of doc/LogFile failed"
set `wc -c doc/LogFile`;Wc_c=$1
if test "$Wc_c" != "2980"; then
	echo original size 2980, current size $Wc_c
fi
fi
# ============= doc/compile.options.doc ==============
if test X"$1" != X"-c" -a -f 'doc/compile.options.doc'; then
	echo "File already exists: skipping 'doc/compile.options.doc'"
else
echo "x - extracting doc/compile.options.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/compile.options.doc &&
XProject:	lj2ps, 1.1 (release)
XFile:		compile.options.doc
X
XAuthor:		Chris Lishka
XOrganization:	Wisconsin State Laboratory of Hygiene
X		Data Processing Dept.
X
XDate:		June 13th, 1990
XLast modified:	June 30th, 1990 by Chris Lishka
X
X
Xlj2ps revisions after 1.0 have several compile-time options available.
XThese options allow certain features to be compiled into the
Xexecutable.  Inclusion of the option will make the lj2ps program more
Xfunctional; exclusion will yield a slightly faster and smaller
Xprogram.  The options should be set with the -DOPTION flag for the C
Xcompiler, and will usually be included in a variable definition in the
XMakefile.
X
XWhat follows are descriptions of the options which are currently
Xavailable:
X
XDEBUG
X
XNormally debugging information will be left out.  If DEBUG is defined,
Xthen code to implement debugging will be conditionally compiled into
Xthe final lj2ps executable.  This extra code will allow different
Xlevels of debugging information to be printed out when the -d#
Xcommand-line option is include, where # is the debugging level.
XCurrently, the following levels are offered:
X
X	0	No debugging info.  This is the default.
X	1	Tokens are printed out.  Rather verbose.
X	2	Tokens and input characters are both printed
X		out.  Super-duper verbose.
X
XVERBOSE_WARNINGS
X
XThere are several warning messages that will occur frequently during
Xnormal lj2ps usage.  For example, since there is only one symbol set,
Xlj2ps does not recognize any symbol sets in the PCL change-symbol-set
Xcommand.  This leads to many warnings.  If VERBOSE_WARNINGS is set,
Xthen all warning messages will be printed.  Otherwise, the common (but
Xunimportant) warnings will be supressed.
X
X
SHAR_EOF
$TOUCH -am 0630160890 doc/compile.options.doc &&
chmod 0664 doc/compile.options.doc ||
echo "restore of doc/compile.options.doc failed"
set `wc -c doc/compile.options.doc`;Wc_c=$1
if test "$Wc_c" != "1683"; then
	echo original size 1683, current size $Wc_c
fi
fi
# ============= doc/limitations.doc ==============
if test X"$1" != X"-c" -a -f 'doc/limitations.doc'; then
	echo "File already exists: skipping 'doc/limitations.doc'"
else
echo "x - extracting doc/limitations.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/limitations.doc &&
XProgram:	lj2ps, 1.1 (release)
XFile:		limitations.doc
X
XAuthor:		Christopher Lishka
XOrganization:	Wisconsin State Laboratory of Hygiene 
X		Data Processing Department
X
XDate:		April 25th, 1990
XLast modified:	June  30th, 1990 by Chris Lishka
X
X
XThis file contains known limitations of the lj2ps program.  The
Xlimitations come in two basic varieties: (a) those that exist because
Xof inherent differences between the LaserJet and LaserWriter; and (b)
Xthose that exist because I do not have enough time to fix them.  All
Xlimitations listed should be assumed to belong in the second category
Xunless otherwise noted.
X
X* As has been mentioned many times in the documentation, I did not
X  have time to implement all LaserJet commands in PCL 4 (let alone PCL
X  5).  Instead, I leave this as an exercise for the reader ;-)  I have
X  implemented what was needed by my organization, and represents a
X  subset of PCL 4 which supports (fairly completely) page motion, page
X  setup, and internal and cartridge fonts.  Commands which were left
X  out include:
X
X  ** Macros
X
X  ** Position stack
X
X  ** Graphics -- patterns and grayshades
X
X  ** Graphics -- bitmaps
X
X  ** Secondary font support
X
X  ** Downloadable fonts
X
X
X* Although I put a fair amount of work into the Test Suite and Metrics
X  Suite, they are by no means complete.  They do test a fair amount of
X  LaserJet quirks, and proved to be very helpful in fine tuning lj2ps.
X  Feel free to add more tests to either suite.
X
X* Tabs do not work exactly like the LaserJet when using proportional
X  fonts.  This is because a given tab position depends on the current
X  location of the cursor, which might be different from the LaserJet
X  and LaserWriter.  Therefore, when a proportional font is used, tabs
X  might end up in the wrong places.  However, tabs are not a good
X  thing to use with a proportional font anyway.  Note that tabs used
X  with fixed-width fonts should behave exactly the same way.
X
X* Another problem related to tabs is the mechanism I have used.  On
X  the LaserJet, tabs are counted out using characters printed.  To
X  move to the next tab stop, the LaserJet will simply insert enough
X  space characters to reach a position which is a multiple of eight
X  characters.  With proportional fonts, this results in tab stops not
X  being in fixed columns, but rather dependent on the width of the
X  characters printed before the tab.  (I think this method is
X  downright foolish, because it renders the purpose of tabs useless
X  with proportional fonts).  I have chosen to calculate tabs as being
X  in columns, with the distance between columns being eight space
X  characters in the current font.  This allows tabs to be used to line
X  up text at each tab stop with proportional fonts.  Note that
X  although the two schemes give different results with proportional
X  fonts, the behaviors match exactly when using fixed-width fonts.
X
X* The HMI command cannot be fully implemented.  This is an inherent
X  problem with the lj2ps program.  The HMI command on the LaserJet
X  works in one of two ways:
X
X	(a) If the font is non-proportional, then the HMI command
X	    adjusts the individual width of each character;
X
X        (b) If the font is proportional, then the HMI command only
X	    adjusts the width of the *space* character.
X
X  Unfortunately, lj2ps uses a crude font mapping mechanism for
X  emulating LaserJet fonts in PostScript.  One of the inherent
X  limitations is the inability to adjust the individual width of each
X  character in the PostScript font.  It is for this reason that the
X  HMI command cannot be fully implemented.  Unfortunately, there is no
X  good way to fix this without overhauling the font mapping mechanism.
X
X  The HMI command *does* change lj2ps' notion of the current character
X  spacing (in the variable char_width).  This is useful for doing
X  horizontal tabs using columns.  This is why the HMI command has been
X  implemented at all.
X
X* The postscript file produced by lj2ps is definitely not suitable as
X  encapsulated postscript.  One important example is that the
X  "initclip" command must be used when resetting the right margin to
X  insure that the clip-path can "grow" if the right margin gets
X  bigger. 
X
X* To effectively emulate LaserJet relative horizontal motion commands
X  with the current font mechanism, I had to move horizontal motion
X  into the generated PostScript program.  Therefore, although
X  horizontal motion is tracked in lj2ps, it is only updated every time
X  an absolute horizontal motion is performed (including non-command
X  motions such as newline).  This makes the horizontal cursor position
X  in the lj2ps program innaccurate much of the time.  The only fix I
X  can think of is to replace the font emulation mechanism with
X  something better.  Note that vertical motion is tracked completely
X  in lj2ps, and is of little importance in the generated PostScript
X  code.
X
X
SHAR_EOF
$TOUCH -am 0630160890 doc/limitations.doc &&
chmod 0664 doc/limitations.doc ||
echo "restore of doc/limitations.doc failed"
set `wc -c doc/limitations.doc`;Wc_c=$1
if test "$Wc_c" != "4873"; then
	echo original size 4873, current size $Wc_c
fi
fi
# ============= doc/lj2ps.l ==============
if test X"$1" != X"-c" -a -f 'doc/lj2ps.l'; then
	echo "File already exists: skipping 'doc/lj2ps.l'"
else
echo "x - extracting doc/lj2ps.l (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/lj2ps.l &&
X.\"  Program:		lj2ps, LaserJet PCL to PostScript Translator
X.\"  File:		lj2ps.l	(man page documentation)
X.\"
X.\"  Author:		Chris Lishka
X.\"  Organization:	Wisconsin State Laboratory of Hygiene
X.\"			Data Processing Section
X.\"
X.TH LJLPR l "June 30th, 1990 (Revision 1.1)"
X.SH NAME
X\fBlj2ps\fR \- print \fILaserJet\fR files on a \fIPostScript\fR printer
X.SH SYNOPSIS
X\fBljlpr [ \fIoptions\fB ]  [ \fIfiles\fB ] \fR
X.SH DESCRIPTION
X.PP
X\fBlj2ps\fR is a translator that reads in a file of text and
X\fILaserJet PCL\fR commands and converts it to \fIPostScript.\fR
X\fBlj2ps\fR can currently translate a subset of \fIPCL 4.\fR  It will
Xproperly convert page motion, page setup, and primary font commands.
XLeft out are macros, position stack commands, secondary font support,
Xgraphics (both bitmap and pattern/grayscale), and downloadable fonts.
X.PP
X\fBlj2ps\fR is set up to mimic a \fILaserJet Series II\fR with the
X\fIHewlett Packard F\fR and \fIG\fR font cartridges plugged into the
Xleft and right ports, respectively.  Command-line options are provided
Xthat duplicate the functions in the main menu, accessible from the
Xfront panel.
X.PP
XIf \fIfiles\fR are listed on the command line, then \fBlj2ps\fR will
Xread each consecutively as if they were all one file.  If no files are
Xlisted, then input will be read from the \fIstandard input.\fR  All
Xoutput is written to the \fIstandard output,\fR and errors to the
X\fIstandard error.\fR
X.SH OPTIONS
X.PP
X.IP "\fBLaserJet II Main Menu Options\fR" 2
X.IP "\fB-c##\fR" 5
XSets the numbers of copies to \fB##\fR.  The default is one copy.
X.IP "\fB-mf\fR" 5
XSpecifies that paper is to be fed in manually.  The default is to
Xautomatically feed paper in from the tray.
X.IP "\fB-fs?\fR" 5
XChange the default font source to \fB?\fR, where \fB?\fR is \fBL\fR
X(left cartridge), \fBR\fR (right cartridge), \fBI\fR (internal), or
X\fBS\fR (soft font).  The default is \fBI\fR (internal).
X.IP "\fB-fn##\fR" 5
XUse font number \fB##\fR from the default font source.  The default is
Xfont number zero.
X.IP "\fB-fl##\fR" 5
XSet the form length to \fB##\fR lines.  The default is 60 lines.
X.IP "\fBPage Orientation\fR" 2
X.IP "\fB-p\fR" 5
XPrint in portrait mode.  This is the default.
X.IP "\fB-l\fR" 5
XPrint in landscape mode.
X.IP "\fBPage Scaling and Offsets\fR" 2
X.IP "\fB-xs##\fR" 5
XScale the width of the page by \fB##\fR.  The default is 1.0 (no
Xscaling). 
X.IP "\fB-ys##\fR" 5
XScale the length of the page by \fB##\fR.  The default is 1.0 (no
Xscaling).
X.IP "\fB-xo##\fR" 5
XOffset the left margin by \fB##\fR inches.  The default is 0.0 inches. 
X.IP "\fB-yo##\fR" 5
XOffest the top margin by \fB##\fR inches.  The default is 0.0 inches.
X.IP "\fBMiscellaneous\fR" 2
X.IP "\fB-X\fR" 5
XPrint a list of all options recognized.
X.IP "\fB-w\fR" 5
XDo not print warning messages.
X.SH "SEE ALSO"
XPlease refer to your local printing software to determine how to send
Xthe \fIPostScript\fR output of \fBlj2ps\fR to your printer.
X.SH RESTRICTIONS
XOnly a subset of \fIPCL 4\fR is currently recognized.
X.SH DIAGNOSTICS
X.PP
X\fBljlpr\fR will return with exit code 0 if no errors are
Xencountered or exit code 1 if a fatal error occurs.
X.PP
XFour types of messages are printed:
X.PP
X\fBWarnings\fR are printed to inform the user of possible problems
Xwith the output.  Although warnings are never serious, they do
Xindicate possible problems with the LaserJet commands, or features
Xbeing used that are not actually implemented in \fBlj2ps\fR.  Warnings
Xcan be turned off with the \fB-w\fR option.
X.PP
X\fBErrors\fR indicate recoverable problems in the input or output that
Xshould be corrected.  The program will continue running if an error is
Xencountered, although the output will likely be missing some features.
X.PP
X\fBFatal Errors\fR are non-recoverable errors, and will cause the
Xprogram to immediately terminate with a non-zero exit code.  Fatal
Xerrors must be corrected before \fBlj2ps\fR will accept the entire
Xinput file.
X.PP
X\fBInternal Errors\fR indicate that an internal consistency check has
Xfailed, and will cause immediate termination of execution.  Please
Xcontact the person maintaining \fBlj2ps\fR and describe the internal
Xerror, so that she or he may fix it.
X.SH BUGS
X.PP
XTabs do not work properly with proportional fonts.  However, the
X\fILaserJet\fR's scheme for handling tabs with proportional fonts is
Xbadly botched, so you shouldn't be using proportional fonts anyway.
X.PP
XThe behavior of the HMI command is different from the \fILaserJet\fR.
X.PP
XThe \fIPostScript\fR file produced by \fBlj2ps\fR is not suitable as
X\fIEncapsulated PostScript,\fR because initclip is used to reset the
Xright margin.
X
X
SHAR_EOF
$TOUCH -am 0630160890 doc/lj2ps.l &&
chmod 0664 doc/lj2ps.l ||
echo "restore of doc/lj2ps.l failed"
set `wc -c doc/lj2ps.l`;Wc_c=$1
if test "$Wc_c" != "4619"; then
	echo original size 4619, current size $Wc_c
fi
fi
# ============= doc/measurements.doc ==============
if test X"$1" != X"-c" -a -f 'doc/measurements.doc'; then
	echo "File already exists: skipping 'doc/measurements.doc'"
else
echo "x - extracting doc/measurements.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/measurements.doc &&
XProject:	lj2ps, 1.1 (release)
XFile:		measurements.doc
X
XAuthor:		Christopher Lishka
XOrganization:	Wisconsin State Laboratory of Hygiene
X		Data Processing Dept.
X
XDate:		June 30th, 1990
X
X
XMeasurement	Name	Units per Inch	Inches per Unit	Comments
X===============	=======	===============	===============	=======================
X
XInch		in	1		1		The default unit; fixed
X
XPage Height	ph	Default=0.0909	Default=11	Depends on page size
X
XPage Width	pw	Default=0.1176	Default=8.5	Depends on page size
X
XDots		dt	300		0.0033		Fixed
X
XDecipoints	dp	720		0.0031		Fixed
X
XLines/Inch	li	Default=6	Default=0.1667	Can be reset by user
X
XColumns/Inch	ci					Depends on current font
SHAR_EOF
$TOUCH -am 0630160890 doc/measurements.doc &&
chmod 0664 doc/measurements.doc ||
echo "restore of doc/measurements.doc failed"
set `wc -c doc/measurements.doc`;Wc_c=$1
if test "$Wc_c" != "657"; then
	echo original size 657, current size $Wc_c
fi
fi
# ============= doc/parameter.scanner.idraw ==============
if test X"$1" != X"-c" -a -f 'doc/parameter.scanner.idraw'; then
	echo "File already exists: skipping 'doc/parameter.scanner.idraw'"
else
echo "x - extracting doc/parameter.scanner.idraw (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/parameter.scanner.idraw &&
X%!PS-Adobe-2.0 EPSF-1.2
X%%DocumentFonts: Courier
X%%Pages: 1
X%%BoundingBox: 101 41 511 775
X%%EndComments
X
X50 dict begin
X
X/arrowHeight 8 def
X/arrowWidth 4 def
X/none null def
X/numGraphicParameters 17 def
X/stringLimit 65535 def
X
X/Begin {
Xsave
XnumGraphicParameters dict begin
X} def
X
X/End {
Xend
Xrestore
X} def
X
X/SetB {
Xdup type /nulltype eq {
Xpop
Xfalse /brushRightArrow idef
Xfalse /brushLeftArrow idef
Xtrue /brushNone idef
X} {
X/brushDashOffset idef
X/brushDashArray idef
X0 ne /brushRightArrow idef
X0 ne /brushLeftArrow idef
X/brushWidth idef
Xfalse /brushNone idef
X} ifelse
X} def
X
X/SetCFg {
X/fgblue idef
X/fggreen idef
X/fgred idef
X} def
X
X/SetCBg {
X/bgblue idef
X/bggreen idef
X/bgred idef
X} def
X
X/SetF {
X/printSize idef
X/printFont idef
X} def
X
X/SetP {
Xdup type /nulltype eq {
Xpop true /patternNone idef
X} {
X/patternGrayLevel idef
XpatternGrayLevel -1 eq {
X/patternString idef
X} if
Xfalse /patternNone idef
X} ifelse
X} def
X
X/BSpl {
X0 begin
Xstorexyn
Xnewpath
Xn 1 gt {
X0 0 0 0 0 0 1 1 true subspline
Xn 2 gt {
X0 0 0 0 1 1 2 2 false subspline
X1 1 n 3 sub {
X/i exch def
Xi 1 sub dup i dup i 1 add dup i 2 add dup false subspline
X} for
Xn 3 sub dup n 2 sub dup n 1 sub dup 2 copy false subspline
X} if
Xn 2 sub dup n 1 sub dup 2 copy 2 copy false subspline
XpatternNone not brushLeftArrow not brushRightArrow not and and { ifill } if
XbrushNone not { istroke } if
X0 0 1 1 leftarrow
Xn 2 sub dup n 1 sub dup rightarrow
X} if
Xend
X} dup 0 4 dict put def
X
X/Circ {
Xnewpath
X0 360 arc
XpatternNone not { ifill } if
XbrushNone not { istroke } if
X} def
X
X/CBSpl {
X0 begin
Xdup 2 gt {
Xstorexyn
Xnewpath
Xn 1 sub dup 0 0 1 1 2 2 true subspline
X1 1 n 3 sub {
X/i exch def
Xi 1 sub dup i dup i 1 add dup i 2 add dup false subspline
X} for
Xn 3 sub dup n 2 sub dup n 1 sub dup 0 0 false subspline
Xn 2 sub dup n 1 sub dup 0 0 1 1 false subspline
XpatternNone not { ifill } if
XbrushNone not { istroke } if
X} {
XPoly
X} ifelse
Xend
X} dup 0 4 dict put def
X
X/Elli {
X0 begin
Xnewpath
X4 2 roll
Xtranslate
Xscale
X0 0 1 0 360 arc
XpatternNone not { ifill } if
XbrushNone not { istroke } if
Xend
X} dup 0 1 dict put def
X
X/Line {
X0 begin
X2 storexyn
Xnewpath
Xx 0 get y 0 get moveto
Xx 1 get y 1 get lineto
XbrushNone not { istroke } if
X0 0 1 1 leftarrow
X0 0 1 1 rightarrow
Xend
X} dup 0 4 dict put def
X
X/MLine {
X0 begin
Xstorexyn
Xnewpath
Xn 1 gt {
Xx 0 get y 0 get moveto
X1 1 n 1 sub {
X/i exch def
Xx i get y i get lineto
X} for
XpatternNone not brushLeftArrow not brushRightArrow not and and { ifill } if
XbrushNone not { istroke } if
X0 0 1 1 leftarrow
Xn 2 sub dup n 1 sub dup rightarrow
X} if
Xend
X} dup 0 4 dict put def
X
X/Poly {
X3 1 roll
Xnewpath
Xmoveto
X-1 add
X{ lineto } repeat
Xclosepath
XpatternNone not { ifill } if
XbrushNone not { istroke } if
X} def
X
X/Rect {
X0 begin
X/t exch def
X/r exch def
X/b exch def
X/l exch def
Xnewpath
Xl b moveto
Xl t lineto
Xr t lineto
Xr b lineto
Xclosepath
XpatternNone not { ifill } if
XbrushNone not { istroke } if
Xend
X} dup 0 4 dict put def
X
X/Text {
Xishow
X} def
X
X/idef {
Xdup where { pop pop pop } { exch def } ifelse
X} def
X
X/ifill {
X0 begin
Xgsave
XpatternGrayLevel -1 ne {
Xfgred bgred fgred sub patternGrayLevel mul add
Xfggreen bggreen fggreen sub patternGrayLevel mul add
Xfgblue bgblue fgblue sub patternGrayLevel mul add setrgbcolor
Xeofill
X} {
Xeoclip
XoriginalCTM setmatrix
Xpathbbox /t exch def /r exch def /b exch def /l exch def
X/w r l sub ceiling cvi def
X/h t b sub ceiling cvi def
X/imageByteWidth w 8 div ceiling cvi def
X/imageHeight h def
Xbgred bggreen bgblue setrgbcolor
Xeofill
Xfgred fggreen fgblue setrgbcolor
Xw 0 gt h 0 gt and {
Xl b translate w h scale
Xw h true [w 0 0 h neg 0 h] { patternproc } imagemask
X} if
X} ifelse
Xgrestore
Xend
X} dup 0 8 dict put def
X
X/istroke {
Xgsave
XbrushDashOffset -1 eq {
X[] 0 setdash
X1 setgray
X} {
XbrushDashArray brushDashOffset setdash
Xfgred fggreen fgblue setrgbcolor
X} ifelse
XbrushWidth setlinewidth
XoriginalCTM setmatrix
Xstroke
Xgrestore
X} def
X
X/ishow {
X0 begin
Xgsave
XprintFont findfont printSize scalefont setfont
Xfgred fggreen fgblue setrgbcolor
X/vertoffset printSize neg def {
X0 vertoffset moveto show
X/vertoffset vertoffset printSize sub def
X} forall
Xgrestore
Xend
X} dup 0 3 dict put def
X
X/patternproc {
X0 begin
X/patternByteLength patternString length def
X/patternHeight patternByteLength 8 mul sqrt cvi def
X/patternWidth patternHeight def
X/patternByteWidth patternWidth 8 idiv def
X/imageByteMaxLength imageByteWidth imageHeight mul
XstringLimit patternByteWidth sub min def
X/imageMaxHeight imageByteMaxLength imageByteWidth idiv patternHeight idiv
XpatternHeight mul patternHeight max def
X/imageHeight imageHeight imageMaxHeight sub store
X/imageString imageByteWidth imageMaxHeight mul patternByteWidth add string def
X0 1 imageMaxHeight 1 sub {
X/y exch def
X/patternRow y patternByteWidth mul patternByteLength mod def
X/patternRowString patternString patternRow patternByteWidth getinterval def
X/imageRow y imageByteWidth mul def
X0 patternByteWidth imageByteWidth 1 sub {
X/x exch def
XimageString imageRow x add patternRowString putinterval
X} for
X} for
XimageString
Xend
X} dup 0 12 dict put def
X
X/min {
Xdup 3 2 roll dup 4 3 roll lt { exch } if pop
X} def
X
X/max {
Xdup 3 2 roll dup 4 3 roll gt { exch } if pop
X} def
X
X/arrowhead {
X0 begin
Xtransform originalCTM itransform
X/taily exch def
X/tailx exch def
Xtransform originalCTM itransform
X/tipy exch def
X/tipx exch def
X/dy tipy taily sub def
X/dx tipx tailx sub def
X/angle dx 0 ne dy 0 ne or { dy dx atan } { 90 } ifelse def
Xgsave
XoriginalCTM setmatrix
Xtipx tipy translate
Xangle rotate
Xnewpath
X0 0 moveto
XarrowHeight neg arrowWidth 2 div lineto
XarrowHeight neg arrowWidth 2 div neg lineto
Xclosepath
XpatternNone not {
XoriginalCTM setmatrix
X/padtip arrowHeight 2 exp 0.25 arrowWidth 2 exp mul add sqrt brushWidth mul
XarrowWidth div def
X/padtail brushWidth 2 div def
Xtipx tipy translate
Xangle rotate
Xpadtip 0 translate
XarrowHeight padtip add padtail add arrowHeight div dup scale
Xarrowheadpath
Xifill
X} if
XbrushNone not {
XoriginalCTM setmatrix
Xtipx tipy translate
Xangle rotate
Xarrowheadpath
Xistroke
X} if
Xgrestore
Xend
X} dup 0 9 dict put def
X
X/arrowheadpath {
Xnewpath
X0 0 moveto
XarrowHeight neg arrowWidth 2 div lineto
XarrowHeight neg arrowWidth 2 div neg lineto
Xclosepath
X} def
X
X/leftarrow {
X0 begin
Xy exch get /taily exch def
Xx exch get /tailx exch def
Xy exch get /tipy exch def
Xx exch get /tipx exch def
XbrushLeftArrow { tipx tipy tailx taily arrowhead } if
Xend
X} dup 0 4 dict put def
X
X/rightarrow {
X0 begin
Xy exch get /tipy exch def
Xx exch get /tipx exch def
Xy exch get /taily exch def
Xx exch get /tailx exch def
XbrushRightArrow { tipx tipy tailx taily arrowhead } if
Xend
X} dup 0 4 dict put def
X
X/midpoint {
X0 begin
X/y1 exch def
X/x1 exch def
X/y0 exch def
X/x0 exch def
Xx0 x1 add 2 div
Xy0 y1 add 2 div
Xend
X} dup 0 4 dict put def
X
X/thirdpoint {
X0 begin
X/y1 exch def
X/x1 exch def
X/y0 exch def
X/x0 exch def
Xx0 2 mul x1 add 3 div
Xy0 2 mul y1 add 3 div
Xend
X} dup 0 4 dict put def
X
X/subspline {
X0 begin
X/movetoNeeded exch def
Xy exch get /y3 exch def
Xx exch get /x3 exch def
Xy exch get /y2 exch def
Xx exch get /x2 exch def
Xy exch get /y1 exch def
Xx exch get /x1 exch def
Xy exch get /y0 exch def
Xx exch get /x0 exch def
Xx1 y1 x2 y2 thirdpoint
X/p1y exch def
X/p1x exch def
Xx2 y2 x1 y1 thirdpoint
X/p2y exch def
X/p2x exch def
Xx1 y1 x0 y0 thirdpoint
Xp1x p1y midpoint
X/p0y exch def
X/p0x exch def
Xx2 y2 x3 y3 thirdpoint
Xp2x p2y midpoint
X/p3y exch def
X/p3x exch def
XmovetoNeeded { p0x p0y moveto } if
Xp1x p1y p2x p2y p3x p3y curveto
Xend
X} dup 0 17 dict put def
X
X/storexyn {
X/n exch def
X/y n array def
X/x n array def
Xn 1 sub -1 0 {
X/i exch def
Xy i 3 2 roll put
Xx i 3 2 roll put
X} for
X} def
X
X%%EndProlog
X
X%I Idraw 5 Grid 8
X
X%%Page: 1 1
X
XBegin
X%I b u
X%I cfg u
X%I cbg u
X%I f u
X%I p u
X%I t
X[ 0.96 0 0 0.96 0 0 ] concat
X/originalCTM matrix currentmatrix def
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 2.88889 0 0 2.88889 127.5 804.556 ] concat
X%I
X[
X(Parameter Scanner for lj2ps)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 133 142 ] concat
X%I
X[
X(* All end states include a description of the token recognized)
X()
X(* All states include the three letter code that is used in the C-code \(where)
X(  it is preceded by the prefix SP_\).)
X()
X(* All transitions are marked with the characters that cause the transition.)
X()
X(* The action for all transitions is to store the character in a buffer.)
X()
X(* The action for end states UNK, PE, and PC is to accept the last character.)
X(  The action for the end state PE0 is to put the character back into the)
X(  input stream.)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 241 775 ] concat
X%I
X[
X(lj2ps, version 1.1 \(release\))
X] Text
XEnd
X
XBegin %I Pict
X%I b u
X%I cfg u
X%I cbg u
X%I f u
X%I p u
X%I t
X[ 0.804699 0 0 0.804699 60.6917 140.023 ] concat
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 1 0 0 1 416 287 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 513 718 ] concat
X%I
X[
X(End)
X(Parameter)
X(\(Zero Numeric\))
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 502 680 ] concat
X%I
X[
X(PE0)
X] Text
XEnd
X
XEnd %I eop
X
XBegin %I Pict
X%I b u
X%I cfg u
X%I cbg u
X%I f u
X%I p u
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 1 0 0 1 414 78 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 510 500 ] concat
X%I
X[
X(Unknown)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 500 470 ] concat
X%I
X[
X(UNK)
X] Text
XEnd
X
XEnd %I eop
X
XBegin %I Pict
X%I b u
X%I cfg u
X%I cbg u
X%I f u
X%I p u
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 1 0 0 1 419 -135 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 515 290 ] concat
X%I
X[
X(End)
X(Parameter)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 508 257 ] concat
X%I
X[
X(PE)
X] Text
XEnd
X
XEnd %I eop
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 398.056 -22.7305 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 475.307 318.462 ] concat
X%I
X[
X(Continue)
X(Parameter)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 468.869 291.907 ] concat
X%I
X[
X(PC)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 258.233 265.547 ] concat
X%I
X[
X(PINT)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 207.342 387.666 ] concat
X%I
X[
X(FLP)
X] Text
XEnd
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Gray80
X0.2 0.2 0.2 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 93.8796 208.023 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 109.388 521.465 ] concat
X%I
X[
X(PRM)
X] Text
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X133 419 450 295 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X132 410 455 150 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X218 129 218 210 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X102 384 197 119 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X251 244 450 276 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X245 113 459 258 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X250 97 448 129 Line
XEnd
X
XBegin %I BSpl
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I 6
X212 275
X199 308
X175 316
X162 305
X168 278
X194 263
X6 BSpl
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X234 273 451 475 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X235 124 460 466 Line
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 61.6917 209.023 ] concat
X%I
X249 231 450 140 Line
XEnd
X
XBegin %I BSpl
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.534872 0.601209 -0.601209 0.534872 266.082 24.2328 ] concat
X%I 6
X212 275
X199 308
X175 316
X162 305
X168 278
X194 263
X6 BSpl
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 109.169 472.964 ] concat
X%I
X[
X(+ | - | 0-9)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 177.568 295.126 ] concat
X%I
X[
X(0-9)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 189.639 298.344 ] concat
X%I
X[
X()
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 202.514 452.042 ] concat
X%I
X[
X(0-9)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 240.335 368.353 ] concat
X%I
X[
X(P)
X(e)
X(r)
X(i)
X(o)
X(d)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 243.554 446.409 ] concat
X%I
X[
X(Other)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 292.64 289.493 ] concat
X%I
X[
X(Lowercase)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 158.888 584.888 ] concat
X%I
X[
X(Other)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 269.304 420.659 ] concat
X%I
X[
X(Uppercase)
X(   or)
X( Symbol)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 261.257 393.299 ] concat
X%I
X[
X(Lowercase)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 252.405 333.751 ] concat
X%I
X[
X(Other)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 289.421 338.579 ] concat
X%I
X[
X(Uppercase)
X(   or)
X( Symbol)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 171.935 505.957 ] concat
X%I
X[
X(Lowercase)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 0.804699 0 0 0.804699 195.272 556.653 ] concat
X%I
X[
X(Uppercase)
X(   or)
X( Symbol)
X] Text
XEnd
X
XBegin %I Line
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 1 0 0 1 -6 51 ] concat
X%I
X169 513 429 643 Line
XEnd
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Gray80
X0.2 0.2 0.2 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 188.88 70.0228 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Gray80
X0.2 0.2 0.2 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.804699 0 0 0.804699 188.88 -47.9772 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Gray80
X0.2 0.2 0.2 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.576954 0 0 0.576954 168.772 -31.7798 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Elli
X%I b 65535
X1 0 1 [] 0 SetB
X%I cfg Black
X0 0 0 SetCFg
X%I cbg White
X1 1 1 SetCBg
X%I p
X0 SetP
X%I t
X[ 0.576954 0 0 0.576954 369.948 -33.5331 ] concat
X%I
X61 418 31 33 Elli
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 226 213 ] concat
X%I
X[
X(= Intermediate State)
X] Text
XEnd
X
XBegin %I Text
X%I cfg Black
X0 0 0 SetCFg
X%I f *-courier-medium-r-*-80-*
X/Courier 8 SetF
X%I t
X[ 1 0 0 1 426 212 ] concat
X%I
X[
X(= End State)
X] Text
XEnd
X
XEnd %I eop
X
Xshowpage
X
X%%Trailer
X
Xend
SHAR_EOF
$TOUCH -am 0630160890 doc/parameter.scanner.idraw &&
chmod 0644 doc/parameter.scanner.idraw ||
echo "restore of doc/parameter.scanner.idraw failed"
set `wc -c doc/parameter.scanner.idraw`;Wc_c=$1
if test "$Wc_c" != "17644"; then
	echo original size 17644, current size $Wc_c
fi
fi
# ============= doc/scanner.doc ==============
if test X"$1" != X"-c" -a -f 'doc/scanner.doc'; then
	echo "File already exists: skipping 'doc/scanner.doc'"
else
echo "x - extracting doc/scanner.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/scanner.doc &&
XProgram:	lj2ps, 1.1 (release)
XFile:		scanner.doc
X
XAuthor:		Christopher Lishka
XOrganization:	Wisconsin State Laboratory of Hygiene
X		Data Deprocessing Dept.
X
XDate:		March, 1990
X
X
X1. Introduction
X
XIn creating a LaserJet-to-Postscript converter, it is necessary to
Xdevelop a scanner for properly distinguishing between text and
XLaserJet commands.  This document details the scanner I created, which
Xwas a major section of the lj2ps program.
X
XAt first I used lex to generate a scanner module, which I tied into my
Xprogram with the interface in scan.h.  Although lex was likely not the
Xmost efficient choice (due to the overwhelming features it offers), it
Xdid allow me to modify my scanner as needed as more and more bugs were
Xdiscovered in my original design.
X
XHowever, the use of lex proved to be a rocky road ending in a wide
Xravine.  Besides struggling with the state feature of lex, I
Xencountered many small problems that are common when lex is used.  The
Xfinal straw was when I discovered that lex could not handle null
Xcharacters in the input stream.  If the scanner was to be useful and
Xextendable, null characters *had* to be handled, for their use in
Xbitmaps graphics was very common.  This implied that the lex scanner I
Xhad built had to be tossed out.  The development effort of the lex
Xscanner was not wasted though.  It did provide a suitable platform for
Xrevising my initial scanner design.
X
X
X2. The Table-Driven Finite State Automata
X
XIn place of the inadequate lex scanner, I decided to create a
Xhand-coded, state-driven FSA.  This would provide a fast and efficient
Xscanner that could overcome the defficiencies of the lex system.
XHowever, it would also take more time to develop the FSA and translate
Xit into tables.
X
XCertain characteristics of the LaserJet PCL scanner lent themselves
Xwell to improved efficiency and compact design.  One important
Xcharacteristic was that no *actions* were required on the transitions
Xfrom state to state.  Instead, a single default action of copying the
Xcurrent character to a token buffer was all that was needed.  This
Xallowed for the complete elimination of the action table.  Another
Xmajor aspect was the relatively small number of character classes.
XThis allowed for a simple character class table translation mechanism.
X
X
X3. Implementation Details
X
XWhat follows is the important details of my implementation.
X
X* There are actually *two* scanners.  Although this may seem somewhat
X  "kludgy", it actually saves development time (which was a factor)
X  because a true parser does not need to be written.  Instead, which
X  scanner is being used is recorded in a global variable, and it is
X  this one that is activated when scan() is run.
X
X  The reason that two separate scanners can be used lies in the
X  LaserJet PCL language, which consists of text with embedded
X  commands.  One scanner is responsible for scanning normal text, and
X  is able to differentiate command prefixes (which always start with
X  an escape character) from the surrounding text.  The other scanner
X  is responsible for breaking up command parameters into useful
X  tokens.
X
X  Each scanner has separate state and character class tables, as well
X  as the necessary state constants that go with them.  The text
X  scanner's tables and constants all start with "st_" or "ST_",
X  whereas the parameter scanner uses "sp_" and "SP_".
X
X  One problem that may crop up in the future is commands that require
X  trailing data.  Currently these commands are not implemented.  I
X  have not put provisions in for reading variable length data after a
X  PCL command.  However, it would be fairly trivial to add another
X  function to the scanner module (say, scan_data(length)) that would
X  read in a fixed number of characters (which would be interpreted as
X  8-bit bytes).
X
X* I have defined mnemonic constants for the various states.  These
X  have to be in numeric order (starting with zero) and must correspond
X  directly to the states indexes in the state tables.  If this were a
X  perfect world, C would have better enumeration facilities (believe
X  me-I looked into this) and would allow enumerations as indexes into
X  arrays.  Since we must live with the flaws, this is what I have come
X  up with.
X
X  Also note that there are two "special" state types: those marked
X  START and END.  START should always be state 1, whereas END should
X  always be state 0.  These two constants are used to label the start
X  and end states in both scanners, so they must remain the same for
X  both.  I know that fixing the start and end states to predefined
X  numbers was a kludge, but it was a fairly easy (and, hopefully,
X  minor) solution.
X
X* My scanner differs slightly from the "traditional" model.  In mine,
X  the *only* way to end the scanning of a token is to jump to the
X  *single* END state.  "Blasphemy!" some may cry out, but actually
X  this works quite well.  Once the END state is reached, the scanner
X  is finished.  You can find out what token was scanned by maintaining
X  a notion of what the previous state was and referring back to it
X  when END is reached.  Hence the use of the variable prev_state in
X  the function scan().
X
X  Related to the single END state is the demise of "actions."
X  Although no actions on transitions are required, without a single
X  END state one would need to keep a record of (a) which states are
X  end states and (b) whether a put-back or accept of the last read
X  character should be performed on reaching an end state.  (I actually
X  considered using multiple end states first, but then settled on this
X  because it was actually easier.)  With only one END state, the only
X  thing that can be done when reaching here is to put-back the
X  character that caused the transition to this state.  Therefore, the
X  actions in my scanner are *always* an implicit accept of each
X  character on a transition with a put-back of a character upon
X  arrival at the single END state.  This makes everything much easier
X  conceptually.
X
X  One consequence of this design is that the scanner must contain
X  explicit error states.  In addition, *all* characters must belong to
X  some character class and all character classes must have a
X  transition to another state (in many states, most characters will
X  have a transition to an error state).  This actually turns out to be
X  a useful mechanism for scanning LaserJet PCL, because all characters
X  can be text or data, and illegal characters in a command just cause
X  the command to be ignored.
X
X* The token numbers to be returned are determined at the end of scan()
X  in a large switch() statement (actually two switch()'s because of
X  the multiple scanners).  This was the easiest way to do it, and was
X  relatively efficient.  Note that prev_state must be examined,
X  because curr_state will *always* equal END when the switch() is
X  reached.
X
X  
SHAR_EOF
$TOUCH -am 0630160890 doc/scanner.doc &&
chmod 0664 doc/scanner.doc ||
echo "restore of doc/scanner.doc failed"
set `wc -c doc/scanner.doc`;Wc_c=$1
if test "$Wc_c" != "6829"; then
	echo original size 6829, current size $Wc_c
fi
fi
# ============= doc/suggestions.doc ==============
if test X"$1" != X"-c" -a -f 'doc/suggestions.doc'; then
	echo "File already exists: skipping 'doc/suggestions.doc'"
else
echo "x - extracting doc/suggestions.doc (Text)"
sed 's/^X//' << 'SHAR_EOF' > doc/suggestions.doc &&
XProgram:	lj2ps, 1.1 (release)
XFile:		suggestions.doc
X
XAuthor:		Christopher Lishka
XOrganization:	Wisconsin State Laboratory of Hygiene 
X		Data Processing Department
X
XDate:		April 25th, 1990
XLast modified:	June  30th, 1990, by Chris Lishka
X
X
XBesides adding missing PCL commands, there are many areas where lj2ps
Xcould be improved.  This file contains suggestions for those who want
Xto extend the lj2ps program.
X
X* Add the missing commands LaserJet commands.  These include:
X
X  ** The position stack commands (fairly easy)
X
X  ** Secondary font support (fairly easy)
X
X  ** Macros (medium difficulty)
X
X  ** Graphics commands (difficult)
X
X  ** HP soft fonts (very difficult)
X
X
X* Extend either the Test Suite or Metrics Suite (or both!) to include
X  more tests which would better test LaserJet operations and quirks.
X
X
X* The font mechanism should be completely replaced.  Here are some
X  suggestions for this area:
X
X  ** Currently the fonts information is hard-coded into the file
X     ljfonts.c.  A parser should be written that reads a file
X     describing which fonts are mounted in the virtual LaserJet.
X
X  ** Currently there are two PostScript functions for setting the
X     current font: F and FS.  In reality, only FS should be needed.
X     However, the scaling information for each font would need to be
X     changed, and I don't have the time to do this.
X
X  ** Rescaleable, downloadable LaserJet fonts should be created for
X     the LaserWriter.  The only way that the two machines will have
X     similar looking fonts is to custom-make LaserJet fonts for the
X     LaserWriter.  This, of course, is a helluva lot of work!  On the
X     other hand, it would improve the output immensely.
X
X
X* Using two separate scanners is rather kludgy.  It is very likely
X  that the text scanner could be replaced by a tightly-coded loop
X  which would read a character, check to see if it was "special", and
X  add it to the buffer if it wasn't.  Special characters would include:
X
X  (a) The escape character: this would throw execution into a special
X      command scanner/parser, which would handle recognition and
X      execution of all PCL commands.  This parser would need to be
X      able to read long sequences of binary information (for commands
X      with data).  After the command was finished, the parser would
X      return to the above text loop.
X
X  (b) Left and right parentheses, backslash: these must be quoted in
X      PostScript programs, and cannot simply be written out.
X
X  (c) Newline: perform PostScript code to write a newline.
X
X  (d) Form feed: perform PostScript code to start a new page.
X
X  (e) Tab: perform PostScript code to move to the next tab-stop.
X
X  (f) Shift in: switch to the secondary character set.
X
X  (g) Shift out: switch to the primary character set.
X
X  (h) Null, and other non-special, non-printable characters: these
X      should produce a warning, even though the LaserJet would let
X      them slip by.
X
X
X* I never implemented a real parser for the PCL commands.  Instead,
X  each PCL command prefix has its own dedicated function.  Each of
X  these functions has a small parser built into it.  As you might
X  guess (especially after looking at the code!) this causes a lot of
X  similar code to be duplicated in each function.  It would be nice to
X  implement a single "real" parser for the PCL commands, in
X  conjunction with the scanner changes mentioned above.  This would
X  make the overall design much cleaner, and may improve the efficiency
X  some. 
SHAR_EOF
$TOUCH -am 0630160890 doc/suggestions.doc &&
chmod 0664 doc/suggestions.doc ||
echo "restore of doc/suggestions.doc failed"
set `wc -c doc/suggestions.doc`;Wc_c=$1
if test "$Wc_c" != "3480"; then
	echo original size 3480, current size $Wc_c
fi
fi
echo "End of part 7, continue with part 8"
exit 0