xref: /titanic_53/usr/src/tools/codereview/lwlp.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate static char sccsid[] = "%Z%%M%	%I%	%E% SMI";
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * lwlp - Convert ASCII text to PostScript
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  * Usage:
35*7c478bd9Sstevel@tonic-gate  *	lwlp [-{2|4|8}] [-p] [-L] [-r] [-n#] [-l#|-w#] [-c#] [-t#]
36*7c478bd9Sstevel@tonic-gate  *		[-hstring] [-Bstring] [-Istring] [-Xstring] [-Pfile] [file ...]
37*7c478bd9Sstevel@tonic-gate  *
38*7c478bd9Sstevel@tonic-gate  * Options:
39*7c478bd9Sstevel@tonic-gate  *	-{1|2|4|8}	print multiple logical pages per page
40*7c478bd9Sstevel@tonic-gate  *	-d		debug, don't remove temporary file
41*7c478bd9Sstevel@tonic-gate  *	-L		specify Landscape instead of Portrait
42*7c478bd9Sstevel@tonic-gate  *	-p		filter input through pr
43*7c478bd9Sstevel@tonic-gate  *	-r		toggle page reversal flag (default is off)
44*7c478bd9Sstevel@tonic-gate  *	-e		elide unchanged functions
45*7c478bd9Sstevel@tonic-gate  *	-n#		number with numberwidth digits
46*7c478bd9Sstevel@tonic-gate  *	-l#		specify number of lines/logical page, default 66
47*7c478bd9Sstevel@tonic-gate  *	-w#		specify number of columns
48*7c478bd9Sstevel@tonic-gate  *	-c#		specify number of copies
49*7c478bd9Sstevel@tonic-gate  *	-t#		specify tab spacing
50*7c478bd9Sstevel@tonic-gate  *	-htext		specify header text
51*7c478bd9Sstevel@tonic-gate  *	-Btext		specify bold font selector
52*7c478bd9Sstevel@tonic-gate  *	-Itext		specify italic font selector
53*7c478bd9Sstevel@tonic-gate  *	-Xtext		specify bold-italic font selector
54*7c478bd9Sstevel@tonic-gate  *	-Gtext		specify graying selector
55*7c478bd9Sstevel@tonic-gate  *	-Pfile		specify different Postscript prologue file
56*7c478bd9Sstevel@tonic-gate  *
57*7c478bd9Sstevel@tonic-gate  * If no files are specified, stdin is used.
58*7c478bd9Sstevel@tonic-gate  * Form feeds handled
59*7c478bd9Sstevel@tonic-gate  * Backspacing with underlining (or overprinting) works
60*7c478bd9Sstevel@tonic-gate  * The output conforms to Adobe 2.0
61*7c478bd9Sstevel@tonic-gate  *
62*7c478bd9Sstevel@tonic-gate  * Problems:
63*7c478bd9Sstevel@tonic-gate  *	- assumes fixed-width (non-proportional) font in some places
64*7c478bd9Sstevel@tonic-gate  *	- can't back up (using backspaces) over tabs
65*7c478bd9Sstevel@tonic-gate  *	- assumes 8.5 x 11.0 paper
66*7c478bd9Sstevel@tonic-gate  *	- uses logical page with aspect ratio of 3 * 4
67*7c478bd9Sstevel@tonic-gate  *
68*7c478bd9Sstevel@tonic-gate  */
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #define	USAGE1	"[-{1|2|4|8}] [-p] [-L] [-r] [-n<numberwidth]"
71*7c478bd9Sstevel@tonic-gate #define	USAGE2	"[-l<lines>|-w<columns>] [-c<count>] [-t<tabs>]"
72*7c478bd9Sstevel@tonic-gate #define	USAGE3	"[-hstring] [-Bstring] [-Istring] [-Xstring] [-Gstring]"
73*7c478bd9Sstevel@tonic-gate #define	USAGE4	"[-Pfile] [file ...]"
74*7c478bd9Sstevel@tonic-gate #define	USAGE6	"[-hstring] [-e] oldfile newfile"
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate #include <stdio.h>
77*7c478bd9Sstevel@tonic-gate #include <string.h>
78*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
79*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
80*7c478bd9Sstevel@tonic-gate #include <ctype.h>
81*7c478bd9Sstevel@tonic-gate #include <pwd.h>
82*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
83*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
84*7c478bd9Sstevel@tonic-gate #include <unistd.h>
85*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
86*7c478bd9Sstevel@tonic-gate #include <time.h>
87*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate /*
90*7c478bd9Sstevel@tonic-gate  * Configurable...
91*7c478bd9Sstevel@tonic-gate  * BUFOUT should be fairly large
92*7c478bd9Sstevel@tonic-gate  */
93*7c478bd9Sstevel@tonic-gate #define	BUFIN			1024	/* maximum length of an input line */
94*7c478bd9Sstevel@tonic-gate #define	BUFOUT			(BUFIN * 5)
95*7c478bd9Sstevel@tonic-gate #define	MAXPAGES		10000
96*7c478bd9Sstevel@tonic-gate #define	REVERSE_OFF		0
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate #define	DEFAULT_PAPER_HEIGHT	11.0
99*7c478bd9Sstevel@tonic-gate #define	DEFAULT_PAPER_WIDTH	8.50
100*7c478bd9Sstevel@tonic-gate #define	DEFAULT_PAGE_HEIGHT	10.0
101*7c478bd9Sstevel@tonic-gate #define	DEFAULT_PAGE_WIDTH	7.50
102*7c478bd9Sstevel@tonic-gate #define	DEFAULT_LINES_PER_PAGE	66
103*7c478bd9Sstevel@tonic-gate #define	DEFAULT_TAB_SIZE	8
104*7c478bd9Sstevel@tonic-gate static char	*default_font = "Courier";
105*7c478bd9Sstevel@tonic-gate static char	*default_font_bold = "Courier-Bold";
106*7c478bd9Sstevel@tonic-gate static char	*default_font_italic = "Courier-Oblique";
107*7c478bd9Sstevel@tonic-gate static char	*default_font_bold_italic = "Courier-BoldOblique";
108*7c478bd9Sstevel@tonic-gate static char	*select_default_font = "FRN";
109*7c478bd9Sstevel@tonic-gate static char	*select_default_font_bold = "FRB";
110*7c478bd9Sstevel@tonic-gate static char	*select_default_font_italic = "FIN";
111*7c478bd9Sstevel@tonic-gate static char	*select_default_font_bold_italic = "FIB";
112*7c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT			select_default_font
113*7c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT_BOLD		select_default_font_bold
114*7c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT_ITALIC		select_default_font_italic
115*7c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT_BOLD_ITALIC	select_default_font_bold_italic
116*7c478bd9Sstevel@tonic-gate #define	DEFAULT_CHAR_WIDTH	(.6)
117*7c478bd9Sstevel@tonic-gate #define	DEFAULT_SPACES_AFTER_NUMBER	1
118*7c478bd9Sstevel@tonic-gate #define	DEFAULT_DESCENDER_FRACTION	0.3
119*7c478bd9Sstevel@tonic-gate #define	LWLP			"lwlp"
120*7c478bd9Sstevel@tonic-gate #define	CODEREVIEW		"codereview"
121*7c478bd9Sstevel@tonic-gate #define	END_C_FUNCTION		'}'
122*7c478bd9Sstevel@tonic-gate #define	END_ASM_FUNCTION	"SET_SIZE("
123*7c478bd9Sstevel@tonic-gate static char	*banner =
124*7c478bd9Sstevel@tonic-gate 	"**********************************************************";
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate /*
127*7c478bd9Sstevel@tonic-gate  * PostScript command strings
128*7c478bd9Sstevel@tonic-gate  */
129*7c478bd9Sstevel@tonic-gate #define	LINETO			"lineto"
130*7c478bd9Sstevel@tonic-gate #define	NEWPATH			"newpath"
131*7c478bd9Sstevel@tonic-gate #define	SETLINEWIDTH		"setlinewidth"
132*7c478bd9Sstevel@tonic-gate #define	STROKE			"stroke"
133*7c478bd9Sstevel@tonic-gate /*
134*7c478bd9Sstevel@tonic-gate  * PostScript command strings defined in the prologue file
135*7c478bd9Sstevel@tonic-gate  */
136*7c478bd9Sstevel@tonic-gate #define	BACKSPACE		"B"
137*7c478bd9Sstevel@tonic-gate #define	MOVETO			"M"	/* x y */
138*7c478bd9Sstevel@tonic-gate #define	SHOW			"S"	/* string */
139*7c478bd9Sstevel@tonic-gate #define	TAB			"T"	/* spaces */
140*7c478bd9Sstevel@tonic-gate #define	ZEROMOVETO		"Z"	/* y */
141*7c478bd9Sstevel@tonic-gate #define	SELECT_FONT		"SFT"	/* size font */
142*7c478bd9Sstevel@tonic-gate #define	SET_WIDTHS		"SWT"
143*7c478bd9Sstevel@tonic-gate #define	START_PAGE		"SPG"	/* angle scale x y */
144*7c478bd9Sstevel@tonic-gate #define	END_PAGE		"EPG"
145*7c478bd9Sstevel@tonic-gate #define	FLUSH_PAGE		"FPG"	/* ncopies */
146*7c478bd9Sstevel@tonic-gate #define	SHADE			"SHD"	/* x0 y0 x1 y1 */
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate /*
149*7c478bd9Sstevel@tonic-gate  * Conformance requires that no PostScript line exceed 256 characters
150*7c478bd9Sstevel@tonic-gate  */
151*7c478bd9Sstevel@tonic-gate #define	POINTS_PER_INCH		72
152*7c478bd9Sstevel@tonic-gate #define	MAX_OUTPUT_LINE_LENGTH	256
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate #define	START_X			0	/* position of start of each line */
155*7c478bd9Sstevel@tonic-gate #define	THREE_HOLE_X		1.0	/* portrait x offset (inches) 3 hole */
156*7c478bd9Sstevel@tonic-gate #define	THREE_HOLE_Y		0.5	/* landscape y offset (inches) 3 hole */
157*7c478bd9Sstevel@tonic-gate #define	RULE_WIDTH		0.25	/* width in units of paging rules */
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate static struct print_state {
160*7c478bd9Sstevel@tonic-gate 	int	page_count;
161*7c478bd9Sstevel@tonic-gate 	int	logical_page_count;
162*7c478bd9Sstevel@tonic-gate 	int	lineno;
163*7c478bd9Sstevel@tonic-gate 	long	offset;
164*7c478bd9Sstevel@tonic-gate 	float	row;
165*7c478bd9Sstevel@tonic-gate 	char	*font;
166*7c478bd9Sstevel@tonic-gate }	current, saved;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate struct format_state {
169*7c478bd9Sstevel@tonic-gate 	int	numberwidth, linenumber, altlinenumber;
170*7c478bd9Sstevel@tonic-gate 	int	makegray;
171*7c478bd9Sstevel@tonic-gate 	char	*font;
172*7c478bd9Sstevel@tonic-gate };
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate static int	change_seen, dots_inserted, in_change, old_stuff, makegray;
175*7c478bd9Sstevel@tonic-gate static int	lines_per_page;
176*7c478bd9Sstevel@tonic-gate static int	columns;
177*7c478bd9Sstevel@tonic-gate static float	point_size;
178*7c478bd9Sstevel@tonic-gate static int	start_x, start_y, end_x;
179*7c478bd9Sstevel@tonic-gate static int	landscape, rot_text;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate static int	ncopies;
182*7c478bd9Sstevel@tonic-gate static int	tabstop;
183*7c478bd9Sstevel@tonic-gate static int	reverse;
184*7c478bd9Sstevel@tonic-gate static int	elide;
185*7c478bd9Sstevel@tonic-gate static int	usetmp;
186*7c478bd9Sstevel@tonic-gate static int	dflag, lflag, pflag, vflag, wflag;
187*7c478bd9Sstevel@tonic-gate static int	numberwidth, linenumber, altlinenumber;
188*7c478bd9Sstevel@tonic-gate static int	boldlength, itlclength, bitclength, graylength;
189*7c478bd9Sstevel@tonic-gate static char	*boldstring, *itlcstring, *bitcstring, *graystring;
190*7c478bd9Sstevel@tonic-gate #define	HEADER_EXPLICIT	1
191*7c478bd9Sstevel@tonic-gate #define	HEADER_IMPLICIT	2
192*7c478bd9Sstevel@tonic-gate static int	header = HEADER_IMPLICIT;
193*7c478bd9Sstevel@tonic-gate static char	*headerstring;
194*7c478bd9Sstevel@tonic-gate static char	*bannerfile;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate static char	bufin[BUFIN];		/* input buffer */
197*7c478bd9Sstevel@tonic-gate static char	bufout[BUFOUT];		/* output buffer */
198*7c478bd9Sstevel@tonic-gate static long	*page_map;		/* offset of first byte of each page */
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate static char	*username, *hostname, *currentdate;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate static void	preamble(void);
203*7c478bd9Sstevel@tonic-gate static void	postamble(void);
204*7c478bd9Sstevel@tonic-gate static void	setcurrentfont(char *, FILE *);
205*7c478bd9Sstevel@tonic-gate static void	savestate(FILE *);
206*7c478bd9Sstevel@tonic-gate static void	restorestate(FILE *);
207*7c478bd9Sstevel@tonic-gate static void	save_format_state(struct format_state *);
208*7c478bd9Sstevel@tonic-gate static void	printfile(FILE *);
209*7c478bd9Sstevel@tonic-gate static int	printpage(FILE *, FILE *);
210*7c478bd9Sstevel@tonic-gate static int	startpage(FILE *);
211*7c478bd9Sstevel@tonic-gate static void	endpage(FILE *);
212*7c478bd9Sstevel@tonic-gate static void	copypage(FILE *, long, long);
213*7c478bd9Sstevel@tonic-gate static void	process_elide(FILE *);
214*7c478bd9Sstevel@tonic-gate static void	setheaderfile(char *);
215*7c478bd9Sstevel@tonic-gate static void	restore_format_state(struct format_state *, FILE *);
216*7c478bd9Sstevel@tonic-gate static void	flushpage(FILE *);
217*7c478bd9Sstevel@tonic-gate static void	setuppage(FILE *);
218*7c478bd9Sstevel@tonic-gate static void	reversepages(FILE *);
219*7c478bd9Sstevel@tonic-gate static void	proc(char *, FILE *);
220*7c478bd9Sstevel@tonic-gate static void	setup(void);
221*7c478bd9Sstevel@tonic-gate static int	printbanner(char *, FILE *);
222*7c478bd9Sstevel@tonic-gate static char	*fgetline(char *, int, FILE *);
223*7c478bd9Sstevel@tonic-gate static void	fatal(char *fmt, ...);
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate static char	*prologue;
226*7c478bd9Sstevel@tonic-gate static char	*progname;
227*7c478bd9Sstevel@tonic-gate static int	iscodereview;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate static char	*default_prologue[] = {
230*7c478bd9Sstevel@tonic-gate "%%EndComments\n",
231*7c478bd9Sstevel@tonic-gate "%\n",
232*7c478bd9Sstevel@tonic-gate "% PostScript Prologue for lwlp LaserWriter Line Printer\n",
233*7c478bd9Sstevel@tonic-gate "%\n",
234*7c478bd9Sstevel@tonic-gate "/SFT {findfont exch scalefont setfont}bind def\n",
235*7c478bd9Sstevel@tonic-gate "/SWT {( ) stringwidth pop dup /W exch def neg /NW exch def}bind def\n",
236*7c478bd9Sstevel@tonic-gate "/SPG {/SV save def translate dup scale rotate}bind def\n",
237*7c478bd9Sstevel@tonic-gate "/EPG {SV restore}bind def\n",
238*7c478bd9Sstevel@tonic-gate "/FPG {/#copies exch def showpage}bind def\n",
239*7c478bd9Sstevel@tonic-gate "/B {NW 0 rmoveto}def\n",
240*7c478bd9Sstevel@tonic-gate "/M /moveto load def\n",
241*7c478bd9Sstevel@tonic-gate "/T {W mul 0 rmoveto}def\n",
242*7c478bd9Sstevel@tonic-gate "/S /show load def\n",
243*7c478bd9Sstevel@tonic-gate "/Z {0 exch moveto}bind def\n",
244*7c478bd9Sstevel@tonic-gate "/SHD {save 5 1 roll			% S x1 y1 x0 y0\n",
245*7c478bd9Sstevel@tonic-gate "	2 copy moveto			% S x1 y1 x0 y0\n",
246*7c478bd9Sstevel@tonic-gate "	3 index exch lineto		% S x1 y1 x0\n",
247*7c478bd9Sstevel@tonic-gate "	3 -1 roll 2 index lineto	% S y1 x0\n",
248*7c478bd9Sstevel@tonic-gate "	exch lineto			% S\n",
249*7c478bd9Sstevel@tonic-gate "	0.95 setgray fill		% S\n",
250*7c478bd9Sstevel@tonic-gate "	restore}def\n",
251*7c478bd9Sstevel@tonic-gate "%%EndProlog\n",
252*7c478bd9Sstevel@tonic-gate 	NULL
253*7c478bd9Sstevel@tonic-gate };
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate struct layout {
256*7c478bd9Sstevel@tonic-gate 	float	scale;
257*7c478bd9Sstevel@tonic-gate 	int	pages, page_rows, page_cols;
258*7c478bd9Sstevel@tonic-gate 	int	rotation;
259*7c478bd9Sstevel@tonic-gate };
260*7c478bd9Sstevel@tonic-gate static struct layout	*layoutp;
261*7c478bd9Sstevel@tonic-gate static struct layout	layout1 = { 1.000000, 1, 1, 1, 0 };
262*7c478bd9Sstevel@tonic-gate static struct layout	layout2 = { 0.666666, 2, 2, 1, 90 };
263*7c478bd9Sstevel@tonic-gate static struct layout	layout4 = { 0.500000, 4, 2, 2, 0 };
264*7c478bd9Sstevel@tonic-gate static struct layout	layout8 = { 0.333333, 8, 4, 2, 90 };
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate static int	box_width, box_height;
267*7c478bd9Sstevel@tonic-gate static int	gap_width, gap_height;
268*7c478bd9Sstevel@tonic-gate static int	margin_x, margin_y;
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate static struct position {
271*7c478bd9Sstevel@tonic-gate 	int	base_x;
272*7c478bd9Sstevel@tonic-gate 	int	base_y;
273*7c478bd9Sstevel@tonic-gate }	positions[8];
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate int
276*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
277*7c478bd9Sstevel@tonic-gate {
278*7c478bd9Sstevel@tonic-gate 	int	ch, i, j, first_file;
279*7c478bd9Sstevel@tonic-gate 	char	*pc;
280*7c478bd9Sstevel@tonic-gate 	FILE	*infile;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	if ((pc = strrchr(argv[0], '/')) != NULL)
283*7c478bd9Sstevel@tonic-gate 		progname = pc + 1;
284*7c478bd9Sstevel@tonic-gate 	else
285*7c478bd9Sstevel@tonic-gate 		progname = argv[0];
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	lines_per_page = DEFAULT_LINES_PER_PAGE;
288*7c478bd9Sstevel@tonic-gate 	layoutp = &layout1;
289*7c478bd9Sstevel@tonic-gate 	tabstop = DEFAULT_TAB_SIZE;
290*7c478bd9Sstevel@tonic-gate 	current.page_count = 0;
291*7c478bd9Sstevel@tonic-gate 	ncopies = 1;
292*7c478bd9Sstevel@tonic-gate 	reverse = REVERSE_OFF;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
295*7c478bd9Sstevel@tonic-gate 	if (iscodereview = strncmp(progname, CODEREVIEW,
296*7c478bd9Sstevel@tonic-gate 			sizeof (CODEREVIEW) - 1) == 0) {
297*7c478bd9Sstevel@tonic-gate 		layoutp = &layout2;
298*7c478bd9Sstevel@tonic-gate 		numberwidth = 4;
299*7c478bd9Sstevel@tonic-gate 		columns = 85;		/* extra space for numbering */
300*7c478bd9Sstevel@tonic-gate 		wflag = -1;
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	while ((ch = getopt(argc, argv,
304*7c478bd9Sstevel@tonic-gate 			"1248B:c:deG:h:I:l:Ln:P:prt:vw:X:")) != -1) {
305*7c478bd9Sstevel@tonic-gate 		switch (ch) {
306*7c478bd9Sstevel@tonic-gate 		case '1':
307*7c478bd9Sstevel@tonic-gate 			layoutp = &layout1;
308*7c478bd9Sstevel@tonic-gate 			break;
309*7c478bd9Sstevel@tonic-gate 		case '2':
310*7c478bd9Sstevel@tonic-gate 			layoutp = &layout2;
311*7c478bd9Sstevel@tonic-gate 			break;
312*7c478bd9Sstevel@tonic-gate 		case '4':
313*7c478bd9Sstevel@tonic-gate 			layoutp = &layout4;
314*7c478bd9Sstevel@tonic-gate 			break;
315*7c478bd9Sstevel@tonic-gate 		case '8':
316*7c478bd9Sstevel@tonic-gate 			layoutp = &layout8;
317*7c478bd9Sstevel@tonic-gate 			break;
318*7c478bd9Sstevel@tonic-gate 		case 'B':
319*7c478bd9Sstevel@tonic-gate 			boldlength = strlen(optarg);
320*7c478bd9Sstevel@tonic-gate 			boldstring = malloc((size_t)(boldlength + 1));
321*7c478bd9Sstevel@tonic-gate 			(void) strcpy(boldstring, optarg);
322*7c478bd9Sstevel@tonic-gate 			break;
323*7c478bd9Sstevel@tonic-gate 		case 'c':
324*7c478bd9Sstevel@tonic-gate 			ncopies = atof(optarg);
325*7c478bd9Sstevel@tonic-gate 			if (ncopies <= 0) {
326*7c478bd9Sstevel@tonic-gate 				fatal("number of copies must be > 0");
327*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
328*7c478bd9Sstevel@tonic-gate 			}
329*7c478bd9Sstevel@tonic-gate 			break;
330*7c478bd9Sstevel@tonic-gate 		case 'd':
331*7c478bd9Sstevel@tonic-gate 			dflag = 1;
332*7c478bd9Sstevel@tonic-gate 			break;
333*7c478bd9Sstevel@tonic-gate 		case 'e':
334*7c478bd9Sstevel@tonic-gate 			elide = 1;
335*7c478bd9Sstevel@tonic-gate 			break;
336*7c478bd9Sstevel@tonic-gate 		case 'G':
337*7c478bd9Sstevel@tonic-gate 			graylength = strlen(optarg);
338*7c478bd9Sstevel@tonic-gate 			graystring = malloc((size_t)(graylength + 1));
339*7c478bd9Sstevel@tonic-gate 			(void) strcpy(graystring, optarg);
340*7c478bd9Sstevel@tonic-gate 			break;
341*7c478bd9Sstevel@tonic-gate 		case 'h':
342*7c478bd9Sstevel@tonic-gate 			header = HEADER_EXPLICIT;
343*7c478bd9Sstevel@tonic-gate 			i = strlen(optarg);
344*7c478bd9Sstevel@tonic-gate 			headerstring = malloc((size_t)(i + 1));
345*7c478bd9Sstevel@tonic-gate 			(void) strcpy(headerstring, optarg);
346*7c478bd9Sstevel@tonic-gate 			if (strcmp(headerstring, "-") == 0)
347*7c478bd9Sstevel@tonic-gate 				header = HEADER_IMPLICIT;
348*7c478bd9Sstevel@tonic-gate 			break;
349*7c478bd9Sstevel@tonic-gate 		case 'I':
350*7c478bd9Sstevel@tonic-gate 			itlclength = strlen(optarg);
351*7c478bd9Sstevel@tonic-gate 			itlcstring = malloc((size_t)(itlclength + 1));
352*7c478bd9Sstevel@tonic-gate 			(void) strcpy(itlcstring, optarg);
353*7c478bd9Sstevel@tonic-gate 			break;
354*7c478bd9Sstevel@tonic-gate 		case 'l':
355*7c478bd9Sstevel@tonic-gate 			lines_per_page = atoi(optarg);
356*7c478bd9Sstevel@tonic-gate 			if (lines_per_page < 1) {
357*7c478bd9Sstevel@tonic-gate 				fatal("invalid number of lines/page");
358*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
359*7c478bd9Sstevel@tonic-gate 			}
360*7c478bd9Sstevel@tonic-gate 			lflag = 1;
361*7c478bd9Sstevel@tonic-gate 			if (wflag > 0) {
362*7c478bd9Sstevel@tonic-gate 				fatal("can't have both -l and -w");
363*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
364*7c478bd9Sstevel@tonic-gate 			}
365*7c478bd9Sstevel@tonic-gate 			wflag = 0;
366*7c478bd9Sstevel@tonic-gate 			break;
367*7c478bd9Sstevel@tonic-gate 		case 'L':
368*7c478bd9Sstevel@tonic-gate 			landscape = 1;
369*7c478bd9Sstevel@tonic-gate 			break;
370*7c478bd9Sstevel@tonic-gate 		case 'm':
371*7c478bd9Sstevel@tonic-gate 			break;
372*7c478bd9Sstevel@tonic-gate 		case 'n':
373*7c478bd9Sstevel@tonic-gate 			numberwidth = atoi(optarg);
374*7c478bd9Sstevel@tonic-gate 			if (numberwidth < 2) {
375*7c478bd9Sstevel@tonic-gate 				fatal("invalid numbering width");
376*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
377*7c478bd9Sstevel@tonic-gate 			}
378*7c478bd9Sstevel@tonic-gate 			break;
379*7c478bd9Sstevel@tonic-gate 		case 'P':
380*7c478bd9Sstevel@tonic-gate 			prologue = optarg;
381*7c478bd9Sstevel@tonic-gate 			break;
382*7c478bd9Sstevel@tonic-gate 		case 'p':
383*7c478bd9Sstevel@tonic-gate 			pflag = 1;
384*7c478bd9Sstevel@tonic-gate 			break;
385*7c478bd9Sstevel@tonic-gate 		case 'r':
386*7c478bd9Sstevel@tonic-gate 			reverse = !reverse;
387*7c478bd9Sstevel@tonic-gate 			break;
388*7c478bd9Sstevel@tonic-gate 		case 't':
389*7c478bd9Sstevel@tonic-gate 			tabstop = atoi(optarg);
390*7c478bd9Sstevel@tonic-gate 			if (tabstop < 1) {
391*7c478bd9Sstevel@tonic-gate 				fatal("negative tabstop");
392*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
393*7c478bd9Sstevel@tonic-gate 			}
394*7c478bd9Sstevel@tonic-gate 			break;
395*7c478bd9Sstevel@tonic-gate 		case 'v':
396*7c478bd9Sstevel@tonic-gate 			vflag = 1;
397*7c478bd9Sstevel@tonic-gate 			break;
398*7c478bd9Sstevel@tonic-gate 		case 'w':
399*7c478bd9Sstevel@tonic-gate 			columns = atoi(optarg);
400*7c478bd9Sstevel@tonic-gate 			if (columns < 1) {
401*7c478bd9Sstevel@tonic-gate 				fatal("invalid number of columns");
402*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
403*7c478bd9Sstevel@tonic-gate 			}
404*7c478bd9Sstevel@tonic-gate 			wflag = 1;
405*7c478bd9Sstevel@tonic-gate 			if (lflag) {
406*7c478bd9Sstevel@tonic-gate 				fatal("can't have both -l and -w");
407*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
408*7c478bd9Sstevel@tonic-gate 			}
409*7c478bd9Sstevel@tonic-gate 			break;
410*7c478bd9Sstevel@tonic-gate 		case 'X':
411*7c478bd9Sstevel@tonic-gate 			bitclength = strlen(optarg);
412*7c478bd9Sstevel@tonic-gate 			bitcstring = malloc((size_t)(bitclength + 1));
413*7c478bd9Sstevel@tonic-gate 			(void) strcpy(bitcstring, optarg);
414*7c478bd9Sstevel@tonic-gate 			break;
415*7c478bd9Sstevel@tonic-gate 		default:
416*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
417*7c478bd9Sstevel@tonic-gate 					"usage: %s %s\n\t%s\n\t%s\n\t%s\n",
418*7c478bd9Sstevel@tonic-gate 					iscodereview ? LWLP : progname,
419*7c478bd9Sstevel@tonic-gate 					USAGE1, USAGE2, USAGE3, USAGE4);
420*7c478bd9Sstevel@tonic-gate 			if (iscodereview)
421*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "\t%s [%s flags] %s\n",
422*7c478bd9Sstevel@tonic-gate 						CODEREVIEW, LWLP, USAGE6);
423*7c478bd9Sstevel@tonic-gate 			exit(1);
424*7c478bd9Sstevel@tonic-gate 		}
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	if (elide && !iscodereview) {
428*7c478bd9Sstevel@tonic-gate 		fatal("-e option valid only with codereview");
429*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
430*7c478bd9Sstevel@tonic-gate 	}
431*7c478bd9Sstevel@tonic-gate 	usetmp = reverse || elide;
432*7c478bd9Sstevel@tonic-gate 	/* allocate page_map if we need one */
433*7c478bd9Sstevel@tonic-gate 	if (reverse) {
434*7c478bd9Sstevel@tonic-gate 		page_map = malloc((size_t)(MAXPAGES * sizeof (long *)));
435*7c478bd9Sstevel@tonic-gate 		if (page_map == NULL) {
436*7c478bd9Sstevel@tonic-gate 			fatal("unable to allocate memory for page reversal");
437*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
438*7c478bd9Sstevel@tonic-gate 		}
439*7c478bd9Sstevel@tonic-gate 	}
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	/*
442*7c478bd9Sstevel@tonic-gate 	 * Check that all files are readable
443*7c478bd9Sstevel@tonic-gate 	 * This is so that no output at all is produced if any file is not
444*7c478bd9Sstevel@tonic-gate 	 * readable in case the output is being piped to a printer
445*7c478bd9Sstevel@tonic-gate 	 */
446*7c478bd9Sstevel@tonic-gate 	first_file = optind;
447*7c478bd9Sstevel@tonic-gate 	for (j = first_file; j < argc; j++) {
448*7c478bd9Sstevel@tonic-gate 		if (access(argv[j], R_OK) == -1 && !(iscodereview &&
449*7c478bd9Sstevel@tonic-gate 		    strcmp(argv[j], "-") == 0)) {
450*7c478bd9Sstevel@tonic-gate 			fatal("cannot access %s", argv[j]);
451*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 	}
454*7c478bd9Sstevel@tonic-gate 	if (iscodereview && (first_file + 2) != argc) {
455*7c478bd9Sstevel@tonic-gate 		fatal("codereview: need old and new file");
456*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
457*7c478bd9Sstevel@tonic-gate 	}
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 	/* compute logical point size, logical dimensions */
460*7c478bd9Sstevel@tonic-gate 	if (!landscape) {
461*7c478bd9Sstevel@tonic-gate 		rot_text = layoutp->rotation;
462*7c478bd9Sstevel@tonic-gate 		start_y = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH;
463*7c478bd9Sstevel@tonic-gate 		start_x = START_X;
464*7c478bd9Sstevel@tonic-gate 		end_x = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH;
465*7c478bd9Sstevel@tonic-gate 		if (wflag) {
466*7c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
467*7c478bd9Sstevel@tonic-gate 					((columns + 0.5) * DEFAULT_CHAR_WIDTH);
468*7c478bd9Sstevel@tonic-gate 			lines_per_page = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
469*7c478bd9Sstevel@tonic-gate 					point_size;
470*7c478bd9Sstevel@tonic-gate 		} else {
471*7c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
472*7c478bd9Sstevel@tonic-gate 					(lines_per_page + 0.5);
473*7c478bd9Sstevel@tonic-gate 			columns = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
474*7c478bd9Sstevel@tonic-gate 					(point_size * DEFAULT_CHAR_WIDTH);
475*7c478bd9Sstevel@tonic-gate 		}
476*7c478bd9Sstevel@tonic-gate 	} else {
477*7c478bd9Sstevel@tonic-gate 		rot_text = 90 - layoutp->rotation;
478*7c478bd9Sstevel@tonic-gate 		start_y = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH;
479*7c478bd9Sstevel@tonic-gate 		start_x = START_X;
480*7c478bd9Sstevel@tonic-gate 		end_x = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH;
481*7c478bd9Sstevel@tonic-gate 		if (wflag) {
482*7c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
483*7c478bd9Sstevel@tonic-gate 					((columns + 0.5) * DEFAULT_CHAR_WIDTH);
484*7c478bd9Sstevel@tonic-gate 			lines_per_page = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
485*7c478bd9Sstevel@tonic-gate 					point_size;
486*7c478bd9Sstevel@tonic-gate 		} else {
487*7c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
488*7c478bd9Sstevel@tonic-gate 					(lines_per_page + 0.5);
489*7c478bd9Sstevel@tonic-gate 			columns = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
490*7c478bd9Sstevel@tonic-gate 					(point_size * DEFAULT_CHAR_WIDTH);
491*7c478bd9Sstevel@tonic-gate 		}
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	box_height = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH / layoutp->page_rows;
495*7c478bd9Sstevel@tonic-gate 	if (layoutp->rotation == 0)
496*7c478bd9Sstevel@tonic-gate 		box_width = box_height /
497*7c478bd9Sstevel@tonic-gate 				DEFAULT_PAGE_HEIGHT * DEFAULT_PAGE_WIDTH;
498*7c478bd9Sstevel@tonic-gate 	else
499*7c478bd9Sstevel@tonic-gate 		box_width = box_height *
500*7c478bd9Sstevel@tonic-gate 				DEFAULT_PAGE_HEIGHT / DEFAULT_PAGE_WIDTH;
501*7c478bd9Sstevel@tonic-gate 	gap_width = DEFAULT_PAPER_WIDTH * POINTS_PER_INCH /
502*7c478bd9Sstevel@tonic-gate 			layoutp->page_cols - box_width;
503*7c478bd9Sstevel@tonic-gate 	gap_height = DEFAULT_PAPER_HEIGHT * POINTS_PER_INCH /
504*7c478bd9Sstevel@tonic-gate 			layoutp->page_rows - box_height;
505*7c478bd9Sstevel@tonic-gate 	margin_x = gap_width/2;
506*7c478bd9Sstevel@tonic-gate 	margin_y = gap_height/2;
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	columns -= numberwidth + DEFAULT_SPACES_AFTER_NUMBER;
509*7c478bd9Sstevel@tonic-gate 	if (columns <= 0) {
510*7c478bd9Sstevel@tonic-gate 		fatal("numbering width exceeds number of columns");
511*7c478bd9Sstevel@tonic-gate 		/* NOT REACHED */
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 	/* compute physical "lower left corner" of each logical page */
514*7c478bd9Sstevel@tonic-gate 	for (j = 0; j < layoutp->pages; j++) {
515*7c478bd9Sstevel@tonic-gate 		int	phys_row;		/* 0 is bottom row */
516*7c478bd9Sstevel@tonic-gate 		int	phys_col;		/* 0 is left column */
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 		if (landscape == (rot_text == 0)) {
519*7c478bd9Sstevel@tonic-gate 			/* logical pages run physically up and down */
520*7c478bd9Sstevel@tonic-gate 			phys_row = j % layoutp->page_rows;
521*7c478bd9Sstevel@tonic-gate 			phys_col = j / layoutp->page_rows;
522*7c478bd9Sstevel@tonic-gate 		} else {
523*7c478bd9Sstevel@tonic-gate 			/* logical pages run physically left to right */
524*7c478bd9Sstevel@tonic-gate 			phys_row = j / layoutp->page_cols;
525*7c478bd9Sstevel@tonic-gate 			phys_col = j % layoutp->page_cols;
526*7c478bd9Sstevel@tonic-gate 		}
527*7c478bd9Sstevel@tonic-gate 		if (rot_text == 0) {
528*7c478bd9Sstevel@tonic-gate 			/* top physical row is logically first */
529*7c478bd9Sstevel@tonic-gate 			phys_row = layoutp->page_rows - 1 - phys_row;
530*7c478bd9Sstevel@tonic-gate 		}
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 		positions[j].base_x = margin_x +
533*7c478bd9Sstevel@tonic-gate 				phys_col * (box_width + gap_width);
534*7c478bd9Sstevel@tonic-gate 		positions[j].base_y = margin_y +
535*7c478bd9Sstevel@tonic-gate 				phys_row * (box_height + gap_height);
536*7c478bd9Sstevel@tonic-gate 		if (rot_text != 0) {
537*7c478bd9Sstevel@tonic-gate 			positions[j].base_x += box_width;
538*7c478bd9Sstevel@tonic-gate 		}
539*7c478bd9Sstevel@tonic-gate 	}
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	if (vflag) {
542*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n\n", progname, sccsid);
543*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Lines/page = %d\n", lines_per_page);
544*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Columns = %d\n", columns);
545*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < layoutp->pages; j++) {
546*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\tx=%3d, y=%3d\n",
547*7c478bd9Sstevel@tonic-gate 					positions[j].base_x,
548*7c478bd9Sstevel@tonic-gate 					positions[j].base_y);
549*7c478bd9Sstevel@tonic-gate 		}
550*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "box_width=%3d, box_height=%3d\n",
551*7c478bd9Sstevel@tonic-gate 				box_width, box_height);
552*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "gap_width=%3d, gap_height=%3d\n",
553*7c478bd9Sstevel@tonic-gate 				gap_width, gap_height);
554*7c478bd9Sstevel@tonic-gate 	}
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	setup();
557*7c478bd9Sstevel@tonic-gate 	preamble();
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	if (iscodereview) {
560*7c478bd9Sstevel@tonic-gate 		char	command[BUFSIZ];
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 		(void) snprintf(command, BUFSIZ, "diff -b -D %s %s %s",
563*7c478bd9Sstevel@tonic-gate 			CODEREVIEW, argv[first_file+1], argv[first_file]);
564*7c478bd9Sstevel@tonic-gate 		infile = popen(command, "r");
565*7c478bd9Sstevel@tonic-gate 		bannerfile = argv[first_file+1];
566*7c478bd9Sstevel@tonic-gate 		if (ungetc(getc(infile), infile) == EOF) {
567*7c478bd9Sstevel@tonic-gate 			(void) pclose(infile);
568*7c478bd9Sstevel@tonic-gate 			(void) sprintf(command,
569*7c478bd9Sstevel@tonic-gate 					"echo No differences encountered");
570*7c478bd9Sstevel@tonic-gate 			infile = popen(command, "r");
571*7c478bd9Sstevel@tonic-gate 		}
572*7c478bd9Sstevel@tonic-gate 		setheaderfile(bannerfile);
573*7c478bd9Sstevel@tonic-gate 		printfile(infile);
574*7c478bd9Sstevel@tonic-gate 		(void) pclose(infile);
575*7c478bd9Sstevel@tonic-gate 	} else if (first_file == argc) {	/* no files on command line */
576*7c478bd9Sstevel@tonic-gate 		if (vflag)
577*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\tprinting stdin\n");
578*7c478bd9Sstevel@tonic-gate 		setheaderfile("stdin");
579*7c478bd9Sstevel@tonic-gate 		printfile(stdin);
580*7c478bd9Sstevel@tonic-gate 	} else {
581*7c478bd9Sstevel@tonic-gate 		for (i = first_file; i < argc; i++) {
582*7c478bd9Sstevel@tonic-gate 			if ((infile = fopen(argv[i], "r")) == (FILE *)NULL) {
583*7c478bd9Sstevel@tonic-gate 				fatal("can't open %s for reading", argv[i]);
584*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
585*7c478bd9Sstevel@tonic-gate 			}
586*7c478bd9Sstevel@tonic-gate 			if (pflag) {
587*7c478bd9Sstevel@tonic-gate 				char	cmdbuf[BUFSIZ];
588*7c478bd9Sstevel@tonic-gate 				(void) snprintf(cmdbuf, BUFSIZ, "pr %s",
589*7c478bd9Sstevel@tonic-gate 				    argv[i]);
590*7c478bd9Sstevel@tonic-gate 				(void) fclose(infile);
591*7c478bd9Sstevel@tonic-gate 				infile = popen(cmdbuf, "r");
592*7c478bd9Sstevel@tonic-gate 			}
593*7c478bd9Sstevel@tonic-gate 			if (vflag)
594*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "\tprinting %s\n",
595*7c478bd9Sstevel@tonic-gate 						argv[i]);
596*7c478bd9Sstevel@tonic-gate 			setheaderfile(argv[i]);
597*7c478bd9Sstevel@tonic-gate 			printfile(infile);
598*7c478bd9Sstevel@tonic-gate 			if (pflag)
599*7c478bd9Sstevel@tonic-gate 				(void) pclose(infile);
600*7c478bd9Sstevel@tonic-gate 			else
601*7c478bd9Sstevel@tonic-gate 				(void) fclose(infile);
602*7c478bd9Sstevel@tonic-gate 		}
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	postamble();
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 	if (fflush(stdout) == EOF) {
608*7c478bd9Sstevel@tonic-gate 		fatal("write error on stdout");
609*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
610*7c478bd9Sstevel@tonic-gate 	}
611*7c478bd9Sstevel@tonic-gate 	exit(0);
612*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
613*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
614*7c478bd9Sstevel@tonic-gate }
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate /*
617*7c478bd9Sstevel@tonic-gate  * Initial lines sent to the LaserWriter
618*7c478bd9Sstevel@tonic-gate  * Generates the PostScript header and includes the prologue file
619*7c478bd9Sstevel@tonic-gate  * There is limited checking for I/O errors here
620*7c478bd9Sstevel@tonic-gate  */
621*7c478bd9Sstevel@tonic-gate void
622*7c478bd9Sstevel@tonic-gate preamble(void)
623*7c478bd9Sstevel@tonic-gate {
624*7c478bd9Sstevel@tonic-gate 	(void) printf("%%!PS-Adobe-2.0\n");
625*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Creator: %s on %s\n", progname, hostname);
626*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%CreationDate: %s\n", currentdate);
627*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%For: %s\n", username);
628*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%DocumentFonts: %s %s %s %s\n",
629*7c478bd9Sstevel@tonic-gate 		default_font, default_font_bold,
630*7c478bd9Sstevel@tonic-gate 		default_font_italic, default_font_bold_italic);
631*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Pages: (atend)\n");
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	if (prologue == NULL) {
634*7c478bd9Sstevel@tonic-gate 		char	**cpp;
635*7c478bd9Sstevel@tonic-gate 		for (cpp = default_prologue; *cpp; cpp++) {
636*7c478bd9Sstevel@tonic-gate 			(void) fputs(*cpp, stdout);
637*7c478bd9Sstevel@tonic-gate 		}
638*7c478bd9Sstevel@tonic-gate 	} else {
639*7c478bd9Sstevel@tonic-gate 		FILE	*fp;
640*7c478bd9Sstevel@tonic-gate 		if ((fp = fopen(prologue, "r")) == NULL) {
641*7c478bd9Sstevel@tonic-gate 			fatal("can't open prologue file %s", prologue);
642*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
643*7c478bd9Sstevel@tonic-gate 		}
644*7c478bd9Sstevel@tonic-gate 		while (fgets(bufin, sizeof (bufin), fp) != NULL)
645*7c478bd9Sstevel@tonic-gate 			(void) fputs(bufin, stdout);
646*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
647*7c478bd9Sstevel@tonic-gate 	}
648*7c478bd9Sstevel@tonic-gate 	if (ferror(stdout) || fflush(stdout) == EOF) {
649*7c478bd9Sstevel@tonic-gate 		fatal("write error on stdout");
650*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
651*7c478bd9Sstevel@tonic-gate 	}
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT,
654*7c478bd9Sstevel@tonic-gate 			point_size, default_font, SELECT_FONT);
655*7c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT_BOLD,
656*7c478bd9Sstevel@tonic-gate 			point_size, default_font_bold, SELECT_FONT);
657*7c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT_ITALIC,
658*7c478bd9Sstevel@tonic-gate 			point_size, default_font_italic, SELECT_FONT);
659*7c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT_BOLD_ITALIC,
660*7c478bd9Sstevel@tonic-gate 			point_size, default_font_bold_italic, SELECT_FONT);
661*7c478bd9Sstevel@tonic-gate }
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate void
664*7c478bd9Sstevel@tonic-gate postamble(void)
665*7c478bd9Sstevel@tonic-gate {
666*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Trailer\n");
667*7c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Pages: %d\n", current.page_count);
668*7c478bd9Sstevel@tonic-gate }
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate int
671*7c478bd9Sstevel@tonic-gate printbanner(char *filename, FILE *outfile)
672*7c478bd9Sstevel@tonic-gate {
673*7c478bd9Sstevel@tonic-gate 	char		buffer[BUFSIZ];
674*7c478bd9Sstevel@tonic-gate 	struct stat	statbuf;
675*7c478bd9Sstevel@tonic-gate 	struct format_state	format_state;
676*7c478bd9Sstevel@tonic-gate 	int		nlines = 0;
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 	/* we've already verified readability */
679*7c478bd9Sstevel@tonic-gate 	(void) stat(filename, &statbuf);
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 	save_format_state(&format_state);
682*7c478bd9Sstevel@tonic-gate 	numberwidth = 0;
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 	setcurrentfont(DEFAULT_FONT_BOLD_ITALIC, outfile);
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	current.row -= point_size;
687*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row, MOVETO);
688*7c478bd9Sstevel@tonic-gate 	proc(banner, outfile);
689*7c478bd9Sstevel@tonic-gate 	nlines++;
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	current.row -= point_size;
692*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row, MOVETO);
693*7c478bd9Sstevel@tonic-gate 	(void) snprintf(buffer, BUFSIZ, "%8ld %.24s", statbuf.st_size,
694*7c478bd9Sstevel@tonic-gate 	    ctime(&statbuf.st_mtime));
695*7c478bd9Sstevel@tonic-gate 	proc(buffer, outfile);
696*7c478bd9Sstevel@tonic-gate 	nlines++;
697*7c478bd9Sstevel@tonic-gate 
698*7c478bd9Sstevel@tonic-gate 	do {
699*7c478bd9Sstevel@tonic-gate 		current.row -= point_size;
700*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row,
701*7c478bd9Sstevel@tonic-gate 		    MOVETO);
702*7c478bd9Sstevel@tonic-gate 		filename += sprintf(buffer, "%.*s", columns, filename);
703*7c478bd9Sstevel@tonic-gate 		proc(buffer, outfile);
704*7c478bd9Sstevel@tonic-gate 		nlines++;
705*7c478bd9Sstevel@tonic-gate 	} while (strlen(filename) != 0);
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	current.row -= point_size;
708*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row, MOVETO);
709*7c478bd9Sstevel@tonic-gate 	proc(banner, outfile);
710*7c478bd9Sstevel@tonic-gate 	nlines++;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	restore_format_state(&format_state, outfile);
713*7c478bd9Sstevel@tonic-gate 	savestate(outfile);
714*7c478bd9Sstevel@tonic-gate 	return (nlines);
715*7c478bd9Sstevel@tonic-gate }
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate void
718*7c478bd9Sstevel@tonic-gate setcurrentfont(char *newfont, FILE *outfile)
719*7c478bd9Sstevel@tonic-gate {
720*7c478bd9Sstevel@tonic-gate 	if (current.font != newfont) {
721*7c478bd9Sstevel@tonic-gate 		if (newfont)
722*7c478bd9Sstevel@tonic-gate 			current.font = newfont;
723*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%s\n", current.font);
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate }
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate void
728*7c478bd9Sstevel@tonic-gate savestate(FILE *f)
729*7c478bd9Sstevel@tonic-gate {
730*7c478bd9Sstevel@tonic-gate 	current.offset = ftell(f);
731*7c478bd9Sstevel@tonic-gate 	saved = current;
732*7c478bd9Sstevel@tonic-gate }
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate void
735*7c478bd9Sstevel@tonic-gate restorestate(FILE *f)
736*7c478bd9Sstevel@tonic-gate {
737*7c478bd9Sstevel@tonic-gate 	char	*font;
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	font = current.font;
740*7c478bd9Sstevel@tonic-gate 	(void) fseek(f, saved.offset, 0);
741*7c478bd9Sstevel@tonic-gate 	current = saved;
742*7c478bd9Sstevel@tonic-gate 	setcurrentfont(font, f);
743*7c478bd9Sstevel@tonic-gate }
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate void
746*7c478bd9Sstevel@tonic-gate save_format_state(struct format_state *fs)
747*7c478bd9Sstevel@tonic-gate {
748*7c478bd9Sstevel@tonic-gate 	fs->numberwidth = numberwidth;
749*7c478bd9Sstevel@tonic-gate 	fs->linenumber = linenumber;
750*7c478bd9Sstevel@tonic-gate 	fs->altlinenumber = altlinenumber;
751*7c478bd9Sstevel@tonic-gate 	fs->makegray = makegray;
752*7c478bd9Sstevel@tonic-gate 	fs->font = current.font;
753*7c478bd9Sstevel@tonic-gate }
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate void
756*7c478bd9Sstevel@tonic-gate restore_format_state(struct format_state *fs, FILE *outfile)
757*7c478bd9Sstevel@tonic-gate {
758*7c478bd9Sstevel@tonic-gate 	numberwidth = fs->numberwidth;
759*7c478bd9Sstevel@tonic-gate 	linenumber = fs->linenumber;
760*7c478bd9Sstevel@tonic-gate 	altlinenumber = fs->altlinenumber;
761*7c478bd9Sstevel@tonic-gate 	makegray = fs->makegray;
762*7c478bd9Sstevel@tonic-gate 	setcurrentfont(fs->font, outfile);
763*7c478bd9Sstevel@tonic-gate }
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate /*
766*7c478bd9Sstevel@tonic-gate  * Print a file
767*7c478bd9Sstevel@tonic-gate  *
768*7c478bd9Sstevel@tonic-gate  * The input stream may be stdin, a file, or a pipe
769*7c478bd9Sstevel@tonic-gate  */
770*7c478bd9Sstevel@tonic-gate void
771*7c478bd9Sstevel@tonic-gate printfile(FILE *infile)
772*7c478bd9Sstevel@tonic-gate {
773*7c478bd9Sstevel@tonic-gate 	int	eof;
774*7c478bd9Sstevel@tonic-gate 	char	*p;
775*7c478bd9Sstevel@tonic-gate 	FILE	*outfile;
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate 	if (reverse)
778*7c478bd9Sstevel@tonic-gate 		page_map[0] = 0L;
779*7c478bd9Sstevel@tonic-gate 	if (usetmp) {
780*7c478bd9Sstevel@tonic-gate 		(void) snprintf(bufin, BUFIN, "/tmp/%sXXXXXX", progname);
781*7c478bd9Sstevel@tonic-gate 		p = mktemp(bufin);
782*7c478bd9Sstevel@tonic-gate 		if ((outfile = fopen(p, "w+")) == NULL) {
783*7c478bd9Sstevel@tonic-gate 			fatal("can't open temporary file %s", p);
784*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
785*7c478bd9Sstevel@tonic-gate 		}
786*7c478bd9Sstevel@tonic-gate 		if (!dflag)
787*7c478bd9Sstevel@tonic-gate 			(void) unlink(p);
788*7c478bd9Sstevel@tonic-gate 		else
789*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "will not unlink %s\n", p);
790*7c478bd9Sstevel@tonic-gate 	}
791*7c478bd9Sstevel@tonic-gate 	else
792*7c478bd9Sstevel@tonic-gate 		outfile = stdout;
793*7c478bd9Sstevel@tonic-gate 
794*7c478bd9Sstevel@tonic-gate 	setcurrentfont(DEFAULT_FONT, outfile);
795*7c478bd9Sstevel@tonic-gate 	change_seen = 0;
796*7c478bd9Sstevel@tonic-gate 	dots_inserted = 0;
797*7c478bd9Sstevel@tonic-gate 	in_change = 0;
798*7c478bd9Sstevel@tonic-gate 	makegray = 0;
799*7c478bd9Sstevel@tonic-gate 	linenumber = 0;
800*7c478bd9Sstevel@tonic-gate 	altlinenumber = 0;
801*7c478bd9Sstevel@tonic-gate 	current.logical_page_count = 0;
802*7c478bd9Sstevel@tonic-gate 	do {
803*7c478bd9Sstevel@tonic-gate 		current.row = start_y;
804*7c478bd9Sstevel@tonic-gate 		eof = printpage(infile, outfile);
805*7c478bd9Sstevel@tonic-gate 	} while (!eof);
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate 	if (((int)current.row) != start_y)
808*7c478bd9Sstevel@tonic-gate 		endpage(outfile);
809*7c478bd9Sstevel@tonic-gate 	if ((current.logical_page_count % layoutp->pages) != 0)
810*7c478bd9Sstevel@tonic-gate 		flushpage(outfile);
811*7c478bd9Sstevel@tonic-gate 	if (vflag)
812*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\n");
813*7c478bd9Sstevel@tonic-gate 	if (fflush(outfile) == EOF) {
814*7c478bd9Sstevel@tonic-gate 		fatal("write error while flushing output");
815*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
816*7c478bd9Sstevel@tonic-gate 	}
817*7c478bd9Sstevel@tonic-gate 	if (usetmp) {
818*7c478bd9Sstevel@tonic-gate 		if (reverse)
819*7c478bd9Sstevel@tonic-gate 			reversepages(outfile);
820*7c478bd9Sstevel@tonic-gate 		else
821*7c478bd9Sstevel@tonic-gate 			copypage(outfile, 0L, current.offset);
822*7c478bd9Sstevel@tonic-gate 		(void) fclose(outfile);
823*7c478bd9Sstevel@tonic-gate 	}
824*7c478bd9Sstevel@tonic-gate }
825*7c478bd9Sstevel@tonic-gate 
826*7c478bd9Sstevel@tonic-gate void
827*7c478bd9Sstevel@tonic-gate process_elide(FILE *outfile)
828*7c478bd9Sstevel@tonic-gate {
829*7c478bd9Sstevel@tonic-gate 	if (!change_seen && !in_change) {
830*7c478bd9Sstevel@tonic-gate 		/* don't include function in output */
831*7c478bd9Sstevel@tonic-gate 		restorestate(outfile);
832*7c478bd9Sstevel@tonic-gate 		if (!dots_inserted) {
833*7c478bd9Sstevel@tonic-gate 			struct format_state	format_state;
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 			save_format_state(&format_state);
836*7c478bd9Sstevel@tonic-gate 			numberwidth = 0;
837*7c478bd9Sstevel@tonic-gate 			current.lineno++;
838*7c478bd9Sstevel@tonic-gate 			current.row -= point_size;
839*7c478bd9Sstevel@tonic-gate 			setcurrentfont(DEFAULT_FONT_BOLD_ITALIC,
840*7c478bd9Sstevel@tonic-gate 				outfile);
841*7c478bd9Sstevel@tonic-gate 			proc("______unchanged_portion_omitted_",
842*7c478bd9Sstevel@tonic-gate 				outfile);
843*7c478bd9Sstevel@tonic-gate 			restore_format_state(&format_state,
844*7c478bd9Sstevel@tonic-gate 				outfile);
845*7c478bd9Sstevel@tonic-gate 			savestate(outfile);
846*7c478bd9Sstevel@tonic-gate 			dots_inserted = 1;
847*7c478bd9Sstevel@tonic-gate 		}
848*7c478bd9Sstevel@tonic-gate 	} else {
849*7c478bd9Sstevel@tonic-gate 		savestate(outfile);
850*7c478bd9Sstevel@tonic-gate 		change_seen = in_change;
851*7c478bd9Sstevel@tonic-gate 		dots_inserted = 0;
852*7c478bd9Sstevel@tonic-gate 	}
853*7c478bd9Sstevel@tonic-gate }
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate /*
856*7c478bd9Sstevel@tonic-gate  * Process the next page
857*7c478bd9Sstevel@tonic-gate  * Return 1 on EOF, 0 otherwise
858*7c478bd9Sstevel@tonic-gate  */
859*7c478bd9Sstevel@tonic-gate int
860*7c478bd9Sstevel@tonic-gate printpage(FILE *infile, FILE *outfile)
861*7c478bd9Sstevel@tonic-gate {
862*7c478bd9Sstevel@tonic-gate 	int	tmplinenumber;
863*7c478bd9Sstevel@tonic-gate 	char	command[BUFSIZ], flag[BUFSIZ];
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate 	if (ungetc(getc(infile), infile) == EOF)
866*7c478bd9Sstevel@tonic-gate 		return (1);
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 	current.lineno = 0;
869*7c478bd9Sstevel@tonic-gate 	current.lineno += startpage(outfile);
870*7c478bd9Sstevel@tonic-gate 	if (bannerfile) {
871*7c478bd9Sstevel@tonic-gate 		current.lineno += printbanner(bannerfile, outfile);
872*7c478bd9Sstevel@tonic-gate 		bannerfile = NULL;
873*7c478bd9Sstevel@tonic-gate 	}
874*7c478bd9Sstevel@tonic-gate 	for (; current.lineno < lines_per_page; ) {
875*7c478bd9Sstevel@tonic-gate 		if (fgetline(bufin, sizeof (bufin), infile) == (char *)NULL) {
876*7c478bd9Sstevel@tonic-gate 			if (elide)
877*7c478bd9Sstevel@tonic-gate 				process_elide(outfile);
878*7c478bd9Sstevel@tonic-gate 			return (1);
879*7c478bd9Sstevel@tonic-gate 		}
880*7c478bd9Sstevel@tonic-gate 		/*
881*7c478bd9Sstevel@tonic-gate 		 * Allow C comment delimiters around flag; only really applies
882*7c478bd9Sstevel@tonic-gate 		 * to #else and #endif, but we don't expect to see C comments
883*7c478bd9Sstevel@tonic-gate 		 * around flag for #if. Also accept flag with no C comment
884*7c478bd9Sstevel@tonic-gate 		 * delimiters.
885*7c478bd9Sstevel@tonic-gate 		 */
886*7c478bd9Sstevel@tonic-gate 		if (iscodereview &&
887*7c478bd9Sstevel@tonic-gate 		    (sscanf(bufin, "#%32s /* %80s */", command, flag) == 2 ||
888*7c478bd9Sstevel@tonic-gate 		    sscanf(bufin, "#%32s %80s", command, flag) == 2) &&
889*7c478bd9Sstevel@tonic-gate 		    strcmp(flag, CODEREVIEW) == 0) {
890*7c478bd9Sstevel@tonic-gate 			if (strcmp(command, "ifdef") == 0) {
891*7c478bd9Sstevel@tonic-gate 				change_seen = 1;
892*7c478bd9Sstevel@tonic-gate 				in_change = 1;
893*7c478bd9Sstevel@tonic-gate 				makegray = 1;
894*7c478bd9Sstevel@tonic-gate 				old_stuff = 1;
895*7c478bd9Sstevel@tonic-gate 				tmplinenumber = linenumber;
896*7c478bd9Sstevel@tonic-gate 				linenumber = altlinenumber;
897*7c478bd9Sstevel@tonic-gate 				altlinenumber = tmplinenumber;
898*7c478bd9Sstevel@tonic-gate 				setcurrentfont(DEFAULT_FONT_ITALIC, outfile);
899*7c478bd9Sstevel@tonic-gate 			} else if (strcmp(command, "ifndef") == 0) {
900*7c478bd9Sstevel@tonic-gate 				change_seen = 1;
901*7c478bd9Sstevel@tonic-gate 				in_change = 1;
902*7c478bd9Sstevel@tonic-gate 				makegray = 1;
903*7c478bd9Sstevel@tonic-gate 				old_stuff = 0;
904*7c478bd9Sstevel@tonic-gate 				setcurrentfont(DEFAULT_FONT_BOLD, outfile);
905*7c478bd9Sstevel@tonic-gate 			} else if (strcmp(command, "else") == 0) {
906*7c478bd9Sstevel@tonic-gate 				makegray = 1;
907*7c478bd9Sstevel@tonic-gate 				old_stuff = !old_stuff;
908*7c478bd9Sstevel@tonic-gate 				tmplinenumber = linenumber;
909*7c478bd9Sstevel@tonic-gate 				linenumber = altlinenumber;
910*7c478bd9Sstevel@tonic-gate 				altlinenumber = tmplinenumber;
911*7c478bd9Sstevel@tonic-gate 				if (!old_stuff)
912*7c478bd9Sstevel@tonic-gate 					setcurrentfont(DEFAULT_FONT_BOLD,
913*7c478bd9Sstevel@tonic-gate 							outfile);
914*7c478bd9Sstevel@tonic-gate 				else
915*7c478bd9Sstevel@tonic-gate 					setcurrentfont(DEFAULT_FONT_ITALIC,
916*7c478bd9Sstevel@tonic-gate 							outfile);
917*7c478bd9Sstevel@tonic-gate 			} else /* if (strcmp(command, "endif") == 0) */ {
918*7c478bd9Sstevel@tonic-gate 				in_change = 0;
919*7c478bd9Sstevel@tonic-gate 				makegray = 0;
920*7c478bd9Sstevel@tonic-gate 				savestate(outfile);
921*7c478bd9Sstevel@tonic-gate 				setcurrentfont(DEFAULT_FONT, outfile);
922*7c478bd9Sstevel@tonic-gate 				if (old_stuff) {
923*7c478bd9Sstevel@tonic-gate 					tmplinenumber = linenumber;
924*7c478bd9Sstevel@tonic-gate 					linenumber = altlinenumber;
925*7c478bd9Sstevel@tonic-gate 					altlinenumber = tmplinenumber;
926*7c478bd9Sstevel@tonic-gate 				}
927*7c478bd9Sstevel@tonic-gate 			}
928*7c478bd9Sstevel@tonic-gate 			continue;
929*7c478bd9Sstevel@tonic-gate 		}
930*7c478bd9Sstevel@tonic-gate 		current.lineno++;
931*7c478bd9Sstevel@tonic-gate 		current.row -= point_size;
932*7c478bd9Sstevel@tonic-gate 		if (bufin[0] == '\f')
933*7c478bd9Sstevel@tonic-gate 			break;
934*7c478bd9Sstevel@tonic-gate 		proc(bufin, outfile);
935*7c478bd9Sstevel@tonic-gate 		if (elide && (bufin[0] == END_C_FUNCTION ||
936*7c478bd9Sstevel@tonic-gate 		    (strstr(bufin, END_ASM_FUNCTION) != NULL)))
937*7c478bd9Sstevel@tonic-gate 			process_elide(outfile);
938*7c478bd9Sstevel@tonic-gate 	}
939*7c478bd9Sstevel@tonic-gate 	endpage(outfile);
940*7c478bd9Sstevel@tonic-gate 	return (0);
941*7c478bd9Sstevel@tonic-gate }
942*7c478bd9Sstevel@tonic-gate 
943*7c478bd9Sstevel@tonic-gate /*
944*7c478bd9Sstevel@tonic-gate  * Start a new page
945*7c478bd9Sstevel@tonic-gate  */
946*7c478bd9Sstevel@tonic-gate int
947*7c478bd9Sstevel@tonic-gate startpage(FILE *outfile)
948*7c478bd9Sstevel@tonic-gate {
949*7c478bd9Sstevel@tonic-gate 	int	logical_page, lines, buflen;
950*7c478bd9Sstevel@tonic-gate 	struct format_state	format_state;
951*7c478bd9Sstevel@tonic-gate 	char	buf[8];
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate 	logical_page = current.logical_page_count % layoutp->pages;
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate 	if (logical_page == 0)
956*7c478bd9Sstevel@tonic-gate 		setuppage(outfile);
957*7c478bd9Sstevel@tonic-gate 	else
958*7c478bd9Sstevel@tonic-gate 		setcurrentfont((char *)NULL, outfile);
959*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%s ", SET_WIDTHS);
960*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %f %d %d %s\n",
961*7c478bd9Sstevel@tonic-gate 			rot_text, layoutp->scale,
962*7c478bd9Sstevel@tonic-gate 			positions[logical_page].base_x,
963*7c478bd9Sstevel@tonic-gate 			positions[logical_page].base_y,
964*7c478bd9Sstevel@tonic-gate 			START_PAGE);
965*7c478bd9Sstevel@tonic-gate 	lines = 0;
966*7c478bd9Sstevel@tonic-gate 	if (header) {
967*7c478bd9Sstevel@tonic-gate 		save_format_state(&format_state);
968*7c478bd9Sstevel@tonic-gate 		setcurrentfont(DEFAULT_FONT_BOLD, outfile);
969*7c478bd9Sstevel@tonic-gate 		numberwidth = 0;
970*7c478bd9Sstevel@tonic-gate 		makegray = 0;
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 		current.row -= point_size;
973*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row,
974*7c478bd9Sstevel@tonic-gate 				MOVETO);
975*7c478bd9Sstevel@tonic-gate 		proc(headerstring, outfile);
976*7c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, 8, "%d", current.logical_page_count + 1);
977*7c478bd9Sstevel@tonic-gate 		buflen = strlen(buf);
978*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s (%s)%s\n",
979*7c478bd9Sstevel@tonic-gate 				(int)(end_x - (buflen + 0.5) *
980*7c478bd9Sstevel@tonic-gate 				    DEFAULT_CHAR_WIDTH * point_size),
981*7c478bd9Sstevel@tonic-gate 				current.row, MOVETO, buf, SHOW);
982*7c478bd9Sstevel@tonic-gate 		current.row -= point_size;
983*7c478bd9Sstevel@tonic-gate 		restore_format_state(&format_state, outfile);
984*7c478bd9Sstevel@tonic-gate 		lines = 2;
985*7c478bd9Sstevel@tonic-gate 	}
986*7c478bd9Sstevel@tonic-gate 	return (lines);
987*7c478bd9Sstevel@tonic-gate }
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate void
990*7c478bd9Sstevel@tonic-gate setheaderfile(char *filename)
991*7c478bd9Sstevel@tonic-gate {
992*7c478bd9Sstevel@tonic-gate 	if (header == HEADER_IMPLICIT)
993*7c478bd9Sstevel@tonic-gate 		headerstring = filename;
994*7c478bd9Sstevel@tonic-gate }
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate /*
997*7c478bd9Sstevel@tonic-gate  * Setup page
998*7c478bd9Sstevel@tonic-gate  */
999*7c478bd9Sstevel@tonic-gate void
1000*7c478bd9Sstevel@tonic-gate setuppage(FILE *outfile)
1001*7c478bd9Sstevel@tonic-gate {
1002*7c478bd9Sstevel@tonic-gate 	int	i, ilimit;
1003*7c478bd9Sstevel@tonic-gate 	int	begin, end, place;
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%%%%Page: ? %d\n", current.page_count + 1);
1006*7c478bd9Sstevel@tonic-gate 	setcurrentfont((char *)NULL, outfile);
1007*7c478bd9Sstevel@tonic-gate 	if (layoutp->pages == 1)
1008*7c478bd9Sstevel@tonic-gate 		return;
1009*7c478bd9Sstevel@tonic-gate 
1010*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%f %s %s\n",
1011*7c478bd9Sstevel@tonic-gate 			RULE_WIDTH, SETLINEWIDTH, NEWPATH);
1012*7c478bd9Sstevel@tonic-gate 	begin = 0; end = DEFAULT_PAPER_WIDTH * POINTS_PER_INCH;
1013*7c478bd9Sstevel@tonic-gate 	for (i = 1, ilimit = layoutp->page_rows; i < ilimit; i++) {
1014*7c478bd9Sstevel@tonic-gate 		place = margin_y - gap_height/2 + i * (box_height+gap_height);
1015*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s ", begin, place, MOVETO);
1016*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s\n", end, place, LINETO);
1017*7c478bd9Sstevel@tonic-gate 	}
1018*7c478bd9Sstevel@tonic-gate 	begin = 0; end = DEFAULT_PAPER_HEIGHT * POINTS_PER_INCH;
1019*7c478bd9Sstevel@tonic-gate 	for (i = 1, ilimit = layoutp->page_cols; i < ilimit; i++) {
1020*7c478bd9Sstevel@tonic-gate 		place = margin_x - gap_width/2 + i * (box_width+gap_width);
1021*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s ", place, begin, MOVETO);
1022*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s\n", place, end, LINETO);
1023*7c478bd9Sstevel@tonic-gate 	}
1024*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%s\n", STROKE);
1025*7c478bd9Sstevel@tonic-gate }
1026*7c478bd9Sstevel@tonic-gate 
1027*7c478bd9Sstevel@tonic-gate /*
1028*7c478bd9Sstevel@tonic-gate  * Terminate the logical page and indicate the start of the next
1029*7c478bd9Sstevel@tonic-gate  */
1030*7c478bd9Sstevel@tonic-gate void
1031*7c478bd9Sstevel@tonic-gate endpage(FILE *outfile)
1032*7c478bd9Sstevel@tonic-gate {
1033*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%s\n", END_PAGE);
1034*7c478bd9Sstevel@tonic-gate 	current.logical_page_count++;
1035*7c478bd9Sstevel@tonic-gate 	if (vflag)
1036*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "x");
1037*7c478bd9Sstevel@tonic-gate 	if ((current.logical_page_count % layoutp->pages) == 0)
1038*7c478bd9Sstevel@tonic-gate 		flushpage(outfile);
1039*7c478bd9Sstevel@tonic-gate }
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate /*
1042*7c478bd9Sstevel@tonic-gate  * Flush the physical page
1043*7c478bd9Sstevel@tonic-gate  * Record the start of the next page
1044*7c478bd9Sstevel@tonic-gate  */
1045*7c478bd9Sstevel@tonic-gate void
1046*7c478bd9Sstevel@tonic-gate flushpage(FILE *outfile)
1047*7c478bd9Sstevel@tonic-gate {
1048*7c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %s\n", ncopies, FLUSH_PAGE);
1049*7c478bd9Sstevel@tonic-gate 	current.page_count++;
1050*7c478bd9Sstevel@tonic-gate 	current.offset = ftell(outfile);
1051*7c478bd9Sstevel@tonic-gate 	if (reverse) {
1052*7c478bd9Sstevel@tonic-gate 		if (current.page_count >= MAXPAGES) {
1053*7c478bd9Sstevel@tonic-gate 			fatal("page reversal limit (%d) reached", MAXPAGES);
1054*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
1055*7c478bd9Sstevel@tonic-gate 		}
1056*7c478bd9Sstevel@tonic-gate 		page_map[current.page_count] = current.offset;
1057*7c478bd9Sstevel@tonic-gate 	}
1058*7c478bd9Sstevel@tonic-gate 	if (vflag)
1059*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "|");
1060*7c478bd9Sstevel@tonic-gate }
1061*7c478bd9Sstevel@tonic-gate 
1062*7c478bd9Sstevel@tonic-gate /*
1063*7c478bd9Sstevel@tonic-gate  * reverse the order of pages
1064*7c478bd9Sstevel@tonic-gate  */
1065*7c478bd9Sstevel@tonic-gate void
1066*7c478bd9Sstevel@tonic-gate reversepages(FILE *outfile)
1067*7c478bd9Sstevel@tonic-gate {
1068*7c478bd9Sstevel@tonic-gate 	int	i;
1069*7c478bd9Sstevel@tonic-gate 
1070*7c478bd9Sstevel@tonic-gate 	if (vflag)
1071*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\nreversing %d page%s\n",
1072*7c478bd9Sstevel@tonic-gate 				current.page_count,
1073*7c478bd9Sstevel@tonic-gate 				current.page_count > 1 ? "s" : "");
1074*7c478bd9Sstevel@tonic-gate 	for (i = current.page_count - 1; i >= 0; i--) {
1075*7c478bd9Sstevel@tonic-gate 		copypage(outfile, page_map[i], page_map[i+1]);
1076*7c478bd9Sstevel@tonic-gate 	}
1077*7c478bd9Sstevel@tonic-gate }
1078*7c478bd9Sstevel@tonic-gate 
1079*7c478bd9Sstevel@tonic-gate /*
1080*7c478bd9Sstevel@tonic-gate  * copy a page (or more) from tempfile to stdout
1081*7c478bd9Sstevel@tonic-gate  */
1082*7c478bd9Sstevel@tonic-gate void
1083*7c478bd9Sstevel@tonic-gate copypage(FILE *outfile, long off_beg, long off_end)
1084*7c478bd9Sstevel@tonic-gate {
1085*7c478bd9Sstevel@tonic-gate 	int	bytecount, nbytes;
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 	if (fseek(outfile, off_beg, 0) == -1L) {
1088*7c478bd9Sstevel@tonic-gate 		fatal("temporary file seek error");
1089*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
1090*7c478bd9Sstevel@tonic-gate 	}
1091*7c478bd9Sstevel@tonic-gate 	nbytes = off_end - off_beg;
1092*7c478bd9Sstevel@tonic-gate 	while (nbytes > 0) {
1093*7c478bd9Sstevel@tonic-gate 		bytecount = nbytes;
1094*7c478bd9Sstevel@tonic-gate 		if (bytecount > sizeof (bufout))
1095*7c478bd9Sstevel@tonic-gate 			bytecount = sizeof (bufout);
1096*7c478bd9Sstevel@tonic-gate 		bytecount = fread(bufout, 1, bytecount, outfile);
1097*7c478bd9Sstevel@tonic-gate 		if (bytecount <= 0) {
1098*7c478bd9Sstevel@tonic-gate 			fatal("temporary file read error");
1099*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
1100*7c478bd9Sstevel@tonic-gate 		}
1101*7c478bd9Sstevel@tonic-gate 		if (fwrite(bufout, 1, bytecount, stdout) != bytecount) {
1102*7c478bd9Sstevel@tonic-gate 			fatal("write error during page copy");
1103*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
1104*7c478bd9Sstevel@tonic-gate 		}
1105*7c478bd9Sstevel@tonic-gate 		nbytes -= bytecount;
1106*7c478bd9Sstevel@tonic-gate 	}
1107*7c478bd9Sstevel@tonic-gate }
1108*7c478bd9Sstevel@tonic-gate 
1109*7c478bd9Sstevel@tonic-gate /*
1110*7c478bd9Sstevel@tonic-gate  * Process a line of input, escaping characters when necessary and handling
1111*7c478bd9Sstevel@tonic-gate  * tabs
1112*7c478bd9Sstevel@tonic-gate  *
1113*7c478bd9Sstevel@tonic-gate  * The output is improved somewhat by coalescing consecutive tabs and
1114*7c478bd9Sstevel@tonic-gate  * backspaces and eliminating tabs at the end of a line
1115*7c478bd9Sstevel@tonic-gate  *
1116*7c478bd9Sstevel@tonic-gate  * Overprinting (presumably most often used in underlining) can be far from
1117*7c478bd9Sstevel@tonic-gate  * optimal; in particular the way nroff underlines by sequences like
1118*7c478bd9Sstevel@tonic-gate  * "_\ba_\bb_\bc" creates a large volume of PostScript.  This isn't too
1119*7c478bd9Sstevel@tonic-gate  * serious since a lot of nroff underlining is unlikely.
1120*7c478bd9Sstevel@tonic-gate  *
1121*7c478bd9Sstevel@tonic-gate  * Since a newline is generated for each call there will be more
1122*7c478bd9Sstevel@tonic-gate  * newlines in the output than is necessary
1123*7c478bd9Sstevel@tonic-gate  */
1124*7c478bd9Sstevel@tonic-gate void
1125*7c478bd9Sstevel@tonic-gate proc(char *in, FILE *outfile)
1126*7c478bd9Sstevel@tonic-gate {
1127*7c478bd9Sstevel@tonic-gate 	int	i;
1128*7c478bd9Sstevel@tonic-gate 	char	*last, *p, *q;
1129*7c478bd9Sstevel@tonic-gate 	int	currentp, instr, tabc, tabto, grayed;
1130*7c478bd9Sstevel@tonic-gate 	char	*altfont;
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 	currentp = 0;
1133*7c478bd9Sstevel@tonic-gate 	instr = 0;
1134*7c478bd9Sstevel@tonic-gate 	tabto = 0;
1135*7c478bd9Sstevel@tonic-gate 	if (iscodereview) {
1136*7c478bd9Sstevel@tonic-gate 		grayed = makegray;
1137*7c478bd9Sstevel@tonic-gate 		altfont = current.font;
1138*7c478bd9Sstevel@tonic-gate 	} else {
1139*7c478bd9Sstevel@tonic-gate 		grayed = 0;
1140*7c478bd9Sstevel@tonic-gate 		altfont = DEFAULT_FONT;
1141*7c478bd9Sstevel@tonic-gate 	}
1142*7c478bd9Sstevel@tonic-gate 	/* subtract slop factor */
1143*7c478bd9Sstevel@tonic-gate 	last = bufout + MAX_OUTPUT_LINE_LENGTH - 20;
1144*7c478bd9Sstevel@tonic-gate 	for (;;) { /* check for any special line treatment */
1145*7c478bd9Sstevel@tonic-gate 		if (graylength && strncmp(in, graystring, graylength) == 0) {
1146*7c478bd9Sstevel@tonic-gate 			grayed++;
1147*7c478bd9Sstevel@tonic-gate 			in += graylength;
1148*7c478bd9Sstevel@tonic-gate 		} else if (boldlength &&
1149*7c478bd9Sstevel@tonic-gate 				strncmp(in, boldstring, boldlength) == 0) {
1150*7c478bd9Sstevel@tonic-gate 			altfont = DEFAULT_FONT_BOLD;
1151*7c478bd9Sstevel@tonic-gate 			in += boldlength;
1152*7c478bd9Sstevel@tonic-gate 		} else if (itlclength &&
1153*7c478bd9Sstevel@tonic-gate 				strncmp(in, itlcstring, itlclength) == 0) {
1154*7c478bd9Sstevel@tonic-gate 			altfont = DEFAULT_FONT_ITALIC;
1155*7c478bd9Sstevel@tonic-gate 			in += itlclength;
1156*7c478bd9Sstevel@tonic-gate 		} else if (bitclength &&
1157*7c478bd9Sstevel@tonic-gate 				strncmp(in, bitcstring, bitclength) == 0) {
1158*7c478bd9Sstevel@tonic-gate 			altfont = DEFAULT_FONT_BOLD_ITALIC;
1159*7c478bd9Sstevel@tonic-gate 			in += bitclength;
1160*7c478bd9Sstevel@tonic-gate 		} else
1161*7c478bd9Sstevel@tonic-gate 			break;
1162*7c478bd9Sstevel@tonic-gate 	}
1163*7c478bd9Sstevel@tonic-gate 	if (grayed) {
1164*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %d %.2f %s\n",
1165*7c478bd9Sstevel@tonic-gate 			start_x, current.row -
1166*7c478bd9Sstevel@tonic-gate 				DEFAULT_DESCENDER_FRACTION * point_size,
1167*7c478bd9Sstevel@tonic-gate 			end_x, current.row +
1168*7c478bd9Sstevel@tonic-gate 				(1.0 - DEFAULT_DESCENDER_FRACTION) * point_size,
1169*7c478bd9Sstevel@tonic-gate 			SHADE);
1170*7c478bd9Sstevel@tonic-gate 	}
1171*7c478bd9Sstevel@tonic-gate 
1172*7c478bd9Sstevel@tonic-gate 	linenumber++;
1173*7c478bd9Sstevel@tonic-gate 	if (!in_change)
1174*7c478bd9Sstevel@tonic-gate 		altlinenumber++;
1175*7c478bd9Sstevel@tonic-gate 	if (*in == '\0')
1176*7c478bd9Sstevel@tonic-gate 		return;
1177*7c478bd9Sstevel@tonic-gate 
1178*7c478bd9Sstevel@tonic-gate 	if (start_x != 0) {
1179*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s\n",
1180*7c478bd9Sstevel@tonic-gate 				start_x, current.row, MOVETO);
1181*7c478bd9Sstevel@tonic-gate 	}
1182*7c478bd9Sstevel@tonic-gate 	else
1183*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%.2f %s\n",
1184*7c478bd9Sstevel@tonic-gate 				current.row, ZEROMOVETO);
1185*7c478bd9Sstevel@tonic-gate 	if (numberwidth) {
1186*7c478bd9Sstevel@tonic-gate 		setcurrentfont(DEFAULT_FONT, outfile);
1187*7c478bd9Sstevel@tonic-gate 		(void) sprintf(bufout, "%*d", numberwidth, linenumber);
1188*7c478bd9Sstevel@tonic-gate 		for (q = bufout, i = 0; *q == ' '; q++, i++)
1189*7c478bd9Sstevel@tonic-gate 			;
1190*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %s (%s)%s %d %s ",
1191*7c478bd9Sstevel@tonic-gate 			i, TAB, q, SHOW, DEFAULT_SPACES_AFTER_NUMBER, TAB);
1192*7c478bd9Sstevel@tonic-gate 	}
1193*7c478bd9Sstevel@tonic-gate 	setcurrentfont(altfont, outfile);
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate 	q = bufout;
1196*7c478bd9Sstevel@tonic-gate 	*q = '\0';
1197*7c478bd9Sstevel@tonic-gate 	for (p = in; *p != '\0'; p++) {
1198*7c478bd9Sstevel@tonic-gate 		switch (*p) {
1199*7c478bd9Sstevel@tonic-gate 		case '\t':
1200*7c478bd9Sstevel@tonic-gate 			/*
1201*7c478bd9Sstevel@tonic-gate 			 * Count the number of tabs that immediately follow
1202*7c478bd9Sstevel@tonic-gate 			 * the one we're looking at
1203*7c478bd9Sstevel@tonic-gate 			 */
1204*7c478bd9Sstevel@tonic-gate 			tabc = 0;
1205*7c478bd9Sstevel@tonic-gate 			while (*(p + 1) == '\t') {
1206*7c478bd9Sstevel@tonic-gate 				p++;
1207*7c478bd9Sstevel@tonic-gate 				tabc++;
1208*7c478bd9Sstevel@tonic-gate 			}
1209*7c478bd9Sstevel@tonic-gate 			if (currentp > 0) {	/* not beginning of line */
1210*7c478bd9Sstevel@tonic-gate 				i = tabstop - (currentp % tabstop) +
1211*7c478bd9Sstevel@tonic-gate 						tabc * tabstop;
1212*7c478bd9Sstevel@tonic-gate 				if (instr) {
1213*7c478bd9Sstevel@tonic-gate 					(void) snprintf(q,
1214*7c478bd9Sstevel@tonic-gate 					    BUFOUT - (q - bufout), ")%s ",
1215*7c478bd9Sstevel@tonic-gate 					    SHOW);
1216*7c478bd9Sstevel@tonic-gate 					q += strlen(q);
1217*7c478bd9Sstevel@tonic-gate 					instr = 0;
1218*7c478bd9Sstevel@tonic-gate 				}
1219*7c478bd9Sstevel@tonic-gate 			}
1220*7c478bd9Sstevel@tonic-gate 			else
1221*7c478bd9Sstevel@tonic-gate 				i = (tabc + 1) * tabstop;
1222*7c478bd9Sstevel@tonic-gate 			tabto += i;
1223*7c478bd9Sstevel@tonic-gate 			currentp += i;
1224*7c478bd9Sstevel@tonic-gate 			break;
1225*7c478bd9Sstevel@tonic-gate 		case '\b':
1226*7c478bd9Sstevel@tonic-gate 			/* backspacing over tabs doesn't work... */
1227*7c478bd9Sstevel@tonic-gate 			if (tabto != 0) {
1228*7c478bd9Sstevel@tonic-gate 				fatal("attempt to backspace over a tab");
1229*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
1230*7c478bd9Sstevel@tonic-gate 			}
1231*7c478bd9Sstevel@tonic-gate 			p++;
1232*7c478bd9Sstevel@tonic-gate 			for (i = 1; *p == '\b'; p++)
1233*7c478bd9Sstevel@tonic-gate 				i++;
1234*7c478bd9Sstevel@tonic-gate 			p--;
1235*7c478bd9Sstevel@tonic-gate 			if (currentp - i < 0) {
1236*7c478bd9Sstevel@tonic-gate 				fatal("too many backspaces");
1237*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
1238*7c478bd9Sstevel@tonic-gate 			}
1239*7c478bd9Sstevel@tonic-gate 			if (instr) {
1240*7c478bd9Sstevel@tonic-gate 				*q = '\0';
1241*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n",
1242*7c478bd9Sstevel@tonic-gate 						bufout, SHOW);
1243*7c478bd9Sstevel@tonic-gate 			}
1244*7c478bd9Sstevel@tonic-gate 			instr = 0;
1245*7c478bd9Sstevel@tonic-gate 			if (currentp >= columns)
1246*7c478bd9Sstevel@tonic-gate 				i -= currentp-columns;
1247*7c478bd9Sstevel@tonic-gate 			if (i <= 0) {
1248*7c478bd9Sstevel@tonic-gate 				/* backspace in truncated line */
1249*7c478bd9Sstevel@tonic-gate 				bufout[0] = '\0';
1250*7c478bd9Sstevel@tonic-gate 			} else if (i == 1) {
1251*7c478bd9Sstevel@tonic-gate 				/* frequent case gets special attention */
1252*7c478bd9Sstevel@tonic-gate 				(void) snprintf(bufout, BUFOUT, "%s ",
1253*7c478bd9Sstevel@tonic-gate 				    BACKSPACE);
1254*7c478bd9Sstevel@tonic-gate 			} else
1255*7c478bd9Sstevel@tonic-gate 				(void) snprintf(bufout, BUFOUT, "-%d %s ", i,
1256*7c478bd9Sstevel@tonic-gate 				    TAB);
1257*7c478bd9Sstevel@tonic-gate 			q = bufout + strlen(bufout);
1258*7c478bd9Sstevel@tonic-gate 			currentp -= i;
1259*7c478bd9Sstevel@tonic-gate 			break;
1260*7c478bd9Sstevel@tonic-gate 		case '\f':
1261*7c478bd9Sstevel@tonic-gate 			tabto = 0;		/* optimizes */
1262*7c478bd9Sstevel@tonic-gate 			*q = '\0';
1263*7c478bd9Sstevel@tonic-gate 			if (instr)
1264*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n",
1265*7c478bd9Sstevel@tonic-gate 						bufout, SHOW);
1266*7c478bd9Sstevel@tonic-gate 			else
1267*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s\n", bufout);
1268*7c478bd9Sstevel@tonic-gate 			endpage(outfile);
1269*7c478bd9Sstevel@tonic-gate 			(void) startpage(outfile);
1270*7c478bd9Sstevel@tonic-gate 			current.row = start_y;
1271*7c478bd9Sstevel@tonic-gate 			(void) fprintf(outfile, "%d %.2f %s\n",
1272*7c478bd9Sstevel@tonic-gate 					start_x, current.row, MOVETO);
1273*7c478bd9Sstevel@tonic-gate 			if (numberwidth)
1274*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%d %s\n", numberwidth +
1275*7c478bd9Sstevel@tonic-gate 					DEFAULT_SPACES_AFTER_NUMBER, TAB);
1276*7c478bd9Sstevel@tonic-gate 			q = bufout;
1277*7c478bd9Sstevel@tonic-gate 			currentp = 0;
1278*7c478bd9Sstevel@tonic-gate 			instr = 0;
1279*7c478bd9Sstevel@tonic-gate 			break;
1280*7c478bd9Sstevel@tonic-gate 		case '\r':
1281*7c478bd9Sstevel@tonic-gate 			tabto = 0;		/* optimizes */
1282*7c478bd9Sstevel@tonic-gate 			if (instr) {
1283*7c478bd9Sstevel@tonic-gate 				*q = '\0';
1284*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n",
1285*7c478bd9Sstevel@tonic-gate 						bufout, SHOW);
1286*7c478bd9Sstevel@tonic-gate 				instr = 0;
1287*7c478bd9Sstevel@tonic-gate 				q = bufout;
1288*7c478bd9Sstevel@tonic-gate 			}
1289*7c478bd9Sstevel@tonic-gate 			(void) fprintf(outfile, "%d %.2f %s\n",
1290*7c478bd9Sstevel@tonic-gate 					start_x, current.row, MOVETO);
1291*7c478bd9Sstevel@tonic-gate 			if (numberwidth)
1292*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%d %s\n", numberwidth +
1293*7c478bd9Sstevel@tonic-gate 					DEFAULT_SPACES_AFTER_NUMBER, TAB);
1294*7c478bd9Sstevel@tonic-gate 			currentp = 0;
1295*7c478bd9Sstevel@tonic-gate 			break;
1296*7c478bd9Sstevel@tonic-gate 		case '\\':
1297*7c478bd9Sstevel@tonic-gate 		case '(':
1298*7c478bd9Sstevel@tonic-gate 		case ')':
1299*7c478bd9Sstevel@tonic-gate 			if (currentp < columns) {
1300*7c478bd9Sstevel@tonic-gate 				if (!instr) {
1301*7c478bd9Sstevel@tonic-gate 					if (tabto) {
1302*7c478bd9Sstevel@tonic-gate 						(void) snprintf(q,
1303*7c478bd9Sstevel@tonic-gate 						    BUFOUT - (q - bufout),
1304*7c478bd9Sstevel@tonic-gate 						    "%d %s ", tabto, TAB);
1305*7c478bd9Sstevel@tonic-gate 						q += strlen(q);
1306*7c478bd9Sstevel@tonic-gate 						tabto = 0;
1307*7c478bd9Sstevel@tonic-gate 					}
1308*7c478bd9Sstevel@tonic-gate 					*q++ = '(';
1309*7c478bd9Sstevel@tonic-gate 					instr = 1;
1310*7c478bd9Sstevel@tonic-gate 				}
1311*7c478bd9Sstevel@tonic-gate 				*q++ = '\\';
1312*7c478bd9Sstevel@tonic-gate 				*q++ = *p;
1313*7c478bd9Sstevel@tonic-gate 			}
1314*7c478bd9Sstevel@tonic-gate 			currentp++;
1315*7c478bd9Sstevel@tonic-gate 			break;
1316*7c478bd9Sstevel@tonic-gate 		default: {
1317*7c478bd9Sstevel@tonic-gate 			/*
1318*7c478bd9Sstevel@tonic-gate 			 * According to the PostScript Language Manual,
1319*7c478bd9Sstevel@tonic-gate 			 * PostScript files can contain only "the printable
1320*7c478bd9Sstevel@tonic-gate 			 * subset of the ASCII character set (plus the
1321*7c478bd9Sstevel@tonic-gate 			 * newline marker)".
1322*7c478bd9Sstevel@tonic-gate 			 */
1323*7c478bd9Sstevel@tonic-gate 			char	pchar;
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate 			pchar = *p;
1326*7c478bd9Sstevel@tonic-gate 			if (currentp < columns) {
1327*7c478bd9Sstevel@tonic-gate 				if (!instr) {
1328*7c478bd9Sstevel@tonic-gate 					if (tabto) {
1329*7c478bd9Sstevel@tonic-gate 						(void) snprintf(q,
1330*7c478bd9Sstevel@tonic-gate 						    BUFOUT - (q - bufout),
1331*7c478bd9Sstevel@tonic-gate 						    "%d %s ", tabto, TAB);
1332*7c478bd9Sstevel@tonic-gate 						q += strlen(q);
1333*7c478bd9Sstevel@tonic-gate 						tabto = 0;
1334*7c478bd9Sstevel@tonic-gate 					}
1335*7c478bd9Sstevel@tonic-gate 					*q++ = '(';
1336*7c478bd9Sstevel@tonic-gate 					instr = 1;
1337*7c478bd9Sstevel@tonic-gate 				}
1338*7c478bd9Sstevel@tonic-gate 				if (!isascii(pchar) || !isprint(pchar)) {
1339*7c478bd9Sstevel@tonic-gate 					if (iscntrl(pchar)) {
1340*7c478bd9Sstevel@tonic-gate 						if (pchar == '\177')
1341*7c478bd9Sstevel@tonic-gate 							pchar = '_';
1342*7c478bd9Sstevel@tonic-gate 						else
1343*7c478bd9Sstevel@tonic-gate 							pchar += '@';
1344*7c478bd9Sstevel@tonic-gate 						*q++ = '^';
1345*7c478bd9Sstevel@tonic-gate 					} else {
1346*7c478bd9Sstevel@tonic-gate 						*q++ = '\\';
1347*7c478bd9Sstevel@tonic-gate 						*q++ = '0' + ((pchar>>6) & 7);
1348*7c478bd9Sstevel@tonic-gate 						*q++ = '0' + ((pchar>>3) & 7);
1349*7c478bd9Sstevel@tonic-gate 						pchar = '0' + (pchar & 7);
1350*7c478bd9Sstevel@tonic-gate 					}
1351*7c478bd9Sstevel@tonic-gate 				}
1352*7c478bd9Sstevel@tonic-gate 				*q++ = pchar;
1353*7c478bd9Sstevel@tonic-gate 			}
1354*7c478bd9Sstevel@tonic-gate 			currentp++;
1355*7c478bd9Sstevel@tonic-gate 			break;
1356*7c478bd9Sstevel@tonic-gate 			}
1357*7c478bd9Sstevel@tonic-gate 		}
1358*7c478bd9Sstevel@tonic-gate 		if (q >= last) {
1359*7c478bd9Sstevel@tonic-gate 			*q = '\0';
1360*7c478bd9Sstevel@tonic-gate 			if (instr)
1361*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n", bufout,
1362*7c478bd9Sstevel@tonic-gate 				    SHOW);
1363*7c478bd9Sstevel@tonic-gate 			else
1364*7c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s\n", bufout);
1365*7c478bd9Sstevel@tonic-gate 			q = bufout;
1366*7c478bd9Sstevel@tonic-gate 			instr = 0;
1367*7c478bd9Sstevel@tonic-gate 		}
1368*7c478bd9Sstevel@tonic-gate 	}
1369*7c478bd9Sstevel@tonic-gate 	if (instr) {
1370*7c478bd9Sstevel@tonic-gate 		(void) snprintf(q, BUFOUT - (q - bufout), ")%s", SHOW);
1371*7c478bd9Sstevel@tonic-gate 		q += strlen(q);
1372*7c478bd9Sstevel@tonic-gate 	}
1373*7c478bd9Sstevel@tonic-gate 	else
1374*7c478bd9Sstevel@tonic-gate 		*q = '\0';
1375*7c478bd9Sstevel@tonic-gate 	if (q >= last) {
1376*7c478bd9Sstevel@tonic-gate 		fatal("bufout overflow");
1377*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
1378*7c478bd9Sstevel@tonic-gate 	}
1379*7c478bd9Sstevel@tonic-gate 	if (bufout[0] != '\0')
1380*7c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%s\n", bufout);
1381*7c478bd9Sstevel@tonic-gate }
1382*7c478bd9Sstevel@tonic-gate 
1383*7c478bd9Sstevel@tonic-gate /*
1384*7c478bd9Sstevel@tonic-gate  * Initialize globals:
1385*7c478bd9Sstevel@tonic-gate  *	username - login name of user
1386*7c478bd9Sstevel@tonic-gate  *	hostname - name of machine on which lwlp is run
1387*7c478bd9Sstevel@tonic-gate  *	currentdate - what it says
1388*7c478bd9Sstevel@tonic-gate  * Possible system dependencies here...
1389*7c478bd9Sstevel@tonic-gate  */
1390*7c478bd9Sstevel@tonic-gate void
1391*7c478bd9Sstevel@tonic-gate setup(void)
1392*7c478bd9Sstevel@tonic-gate {
1393*7c478bd9Sstevel@tonic-gate 	int	len;
1394*7c478bd9Sstevel@tonic-gate 	char	*p;
1395*7c478bd9Sstevel@tonic-gate 	long	t;
1396*7c478bd9Sstevel@tonic-gate 	struct utsname	utsname;
1397*7c478bd9Sstevel@tonic-gate 	struct passwd	*pw;
1398*7c478bd9Sstevel@tonic-gate 
1399*7c478bd9Sstevel@tonic-gate 	if ((p = getlogin()) == (char *)NULL) {
1400*7c478bd9Sstevel@tonic-gate 		if ((pw = getpwuid(getuid())) == (struct passwd *)NULL)
1401*7c478bd9Sstevel@tonic-gate 			p = "Whoknows";
1402*7c478bd9Sstevel@tonic-gate 		else
1403*7c478bd9Sstevel@tonic-gate 			p = pw->pw_name;
1404*7c478bd9Sstevel@tonic-gate 		endpwent();
1405*7c478bd9Sstevel@tonic-gate 	}
1406*7c478bd9Sstevel@tonic-gate 	username = strdup(p);
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 	(void) uname(&utsname);
1409*7c478bd9Sstevel@tonic-gate 	hostname = strdup(utsname.nodename);
1410*7c478bd9Sstevel@tonic-gate 
1411*7c478bd9Sstevel@tonic-gate 	t = time((long *)0);
1412*7c478bd9Sstevel@tonic-gate 	p = ctime(&t);
1413*7c478bd9Sstevel@tonic-gate 	len = strlen(p);
1414*7c478bd9Sstevel@tonic-gate 	*(p + len - 1) = '\0';		/* zap the newline character */
1415*7c478bd9Sstevel@tonic-gate 	currentdate = strdup(p);
1416*7c478bd9Sstevel@tonic-gate 	current.font = DEFAULT_FONT;
1417*7c478bd9Sstevel@tonic-gate }
1418*7c478bd9Sstevel@tonic-gate 
1419*7c478bd9Sstevel@tonic-gate /*
1420*7c478bd9Sstevel@tonic-gate  * Special version of fgets
1421*7c478bd9Sstevel@tonic-gate  * Read until a formfeed, newline, or overflow
1422*7c478bd9Sstevel@tonic-gate  * If a formfeed is the first character, return it immediately
1423*7c478bd9Sstevel@tonic-gate  * If a formfeed is found after the first character, replace it by a newline
1424*7c478bd9Sstevel@tonic-gate  * and push the formfeed back onto the input stream
1425*7c478bd9Sstevel@tonic-gate  * A special case is a formfeed followed by a newline in which case the
1426*7c478bd9Sstevel@tonic-gate  * newline is ignored
1427*7c478bd9Sstevel@tonic-gate  * The input buffer will be null-terminated and will *not* end with a newline
1428*7c478bd9Sstevel@tonic-gate  * The buffer size n includes the null
1429*7c478bd9Sstevel@tonic-gate  */
1430*7c478bd9Sstevel@tonic-gate char *
1431*7c478bd9Sstevel@tonic-gate fgetline(char *s, int n, FILE *iop)
1432*7c478bd9Sstevel@tonic-gate {
1433*7c478bd9Sstevel@tonic-gate 	int	ch;
1434*7c478bd9Sstevel@tonic-gate 	char	*cs;
1435*7c478bd9Sstevel@tonic-gate 
1436*7c478bd9Sstevel@tonic-gate 	if (n < 2) {
1437*7c478bd9Sstevel@tonic-gate 		fatal("fgetline called with bad buffer size!?");
1438*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
1439*7c478bd9Sstevel@tonic-gate 	}
1440*7c478bd9Sstevel@tonic-gate 
1441*7c478bd9Sstevel@tonic-gate 	cs = s;
1442*7c478bd9Sstevel@tonic-gate 	n--;				/* the null */
1443*7c478bd9Sstevel@tonic-gate 
1444*7c478bd9Sstevel@tonic-gate 	/*
1445*7c478bd9Sstevel@tonic-gate 	 * Check out the special cases
1446*7c478bd9Sstevel@tonic-gate 	 */
1447*7c478bd9Sstevel@tonic-gate 	if ((ch = getc(iop)) == EOF)
1448*7c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
1449*7c478bd9Sstevel@tonic-gate 	if (ch == '\f') {
1450*7c478bd9Sstevel@tonic-gate 		if ((ch = getc(iop)) != '\n') {
1451*7c478bd9Sstevel@tonic-gate 			/*
1452*7c478bd9Sstevel@tonic-gate 			 * If EOF was just read it will be noticed
1453*7c478bd9Sstevel@tonic-gate 			 * next time through
1454*7c478bd9Sstevel@tonic-gate 			 */
1455*7c478bd9Sstevel@tonic-gate 			if (ungetc(ch, iop) == EOF && !feof(iop)) {
1456*7c478bd9Sstevel@tonic-gate 				/*
1457*7c478bd9Sstevel@tonic-gate 				 * Shouldn't happen since a getc()
1458*7c478bd9Sstevel@tonic-gate 				 * was just done
1459*7c478bd9Sstevel@tonic-gate 				 */
1460*7c478bd9Sstevel@tonic-gate 				fatal("fgetline - ungetc failed");
1461*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
1462*7c478bd9Sstevel@tonic-gate 			}
1463*7c478bd9Sstevel@tonic-gate 		}
1464*7c478bd9Sstevel@tonic-gate 		*cs++ = '\f';
1465*7c478bd9Sstevel@tonic-gate 		*cs = '\0';
1466*7c478bd9Sstevel@tonic-gate 		return (s);
1467*7c478bd9Sstevel@tonic-gate 	}
1468*7c478bd9Sstevel@tonic-gate 
1469*7c478bd9Sstevel@tonic-gate 	/*
1470*7c478bd9Sstevel@tonic-gate 	 * Check for "weird" input characters is made in proc()
1471*7c478bd9Sstevel@tonic-gate 	 */
1472*7c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
1473*7c478bd9Sstevel@tonic-gate 		if (ch == '\f' || ch == '\n')
1474*7c478bd9Sstevel@tonic-gate 			break;
1475*7c478bd9Sstevel@tonic-gate 		*cs++ = ch;
1476*7c478bd9Sstevel@tonic-gate 		if ((ch = getc(iop)) == EOF)
1477*7c478bd9Sstevel@tonic-gate 			break;
1478*7c478bd9Sstevel@tonic-gate 	}
1479*7c478bd9Sstevel@tonic-gate 
1480*7c478bd9Sstevel@tonic-gate 	if (ch == EOF && cs == s)		/* Nothing was read */
1481*7c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
1482*7c478bd9Sstevel@tonic-gate 	if (ch == '\f') {
1483*7c478bd9Sstevel@tonic-gate 		if (ungetc(ch, iop) == EOF)
1484*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fgetline - can't ungetc??\n");
1485*7c478bd9Sstevel@tonic-gate 	} else if (ch != '\n' && ch != EOF) {
1486*7c478bd9Sstevel@tonic-gate 		fatal("fgetline - input line too long");
1487*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
1488*7c478bd9Sstevel@tonic-gate 	}
1489*7c478bd9Sstevel@tonic-gate 	*cs = '\0';
1490*7c478bd9Sstevel@tonic-gate 	return (s);
1491*7c478bd9Sstevel@tonic-gate }
1492*7c478bd9Sstevel@tonic-gate 
1493*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1494*7c478bd9Sstevel@tonic-gate void
1495*7c478bd9Sstevel@tonic-gate fatal(char *fmt, ...)
1496*7c478bd9Sstevel@tonic-gate {
1497*7c478bd9Sstevel@tonic-gate 	va_list ap;
1498*7c478bd9Sstevel@tonic-gate 
1499*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", progname);
1500*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
1501*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, ap);
1502*7c478bd9Sstevel@tonic-gate 	va_end(ap);
1503*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
1504*7c478bd9Sstevel@tonic-gate 	exit(1);
1505*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
1506*7c478bd9Sstevel@tonic-gate }
1507