xref: /titanic_44/usr/src/tools/codereview/lwlp.c (revision 3c2f5c48add277395adec64900d8a1140c59ea3e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate static char sccsid[] = "%Z%%M%	%I%	%E% SMI";
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * lwlp - Convert ASCII text to PostScript
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * Usage:
357c478bd9Sstevel@tonic-gate  *	lwlp [-{2|4|8}] [-p] [-L] [-r] [-n#] [-l#|-w#] [-c#] [-t#]
367c478bd9Sstevel@tonic-gate  *		[-hstring] [-Bstring] [-Istring] [-Xstring] [-Pfile] [file ...]
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * Options:
397c478bd9Sstevel@tonic-gate  *	-{1|2|4|8}	print multiple logical pages per page
407c478bd9Sstevel@tonic-gate  *	-d		debug, don't remove temporary file
417c478bd9Sstevel@tonic-gate  *	-L		specify Landscape instead of Portrait
427c478bd9Sstevel@tonic-gate  *	-p		filter input through pr
437c478bd9Sstevel@tonic-gate  *	-r		toggle page reversal flag (default is off)
447c478bd9Sstevel@tonic-gate  *	-e		elide unchanged functions
457c478bd9Sstevel@tonic-gate  *	-n#		number with numberwidth digits
467c478bd9Sstevel@tonic-gate  *	-l#		specify number of lines/logical page, default 66
477c478bd9Sstevel@tonic-gate  *	-w#		specify number of columns
487c478bd9Sstevel@tonic-gate  *	-c#		specify number of copies
497c478bd9Sstevel@tonic-gate  *	-t#		specify tab spacing
507c478bd9Sstevel@tonic-gate  *	-htext		specify header text
517c478bd9Sstevel@tonic-gate  *	-Btext		specify bold font selector
527c478bd9Sstevel@tonic-gate  *	-Itext		specify italic font selector
537c478bd9Sstevel@tonic-gate  *	-Xtext		specify bold-italic font selector
547c478bd9Sstevel@tonic-gate  *	-Gtext		specify graying selector
557c478bd9Sstevel@tonic-gate  *	-Pfile		specify different Postscript prologue file
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * If no files are specified, stdin is used.
587c478bd9Sstevel@tonic-gate  * Form feeds handled
597c478bd9Sstevel@tonic-gate  * Backspacing with underlining (or overprinting) works
607c478bd9Sstevel@tonic-gate  * The output conforms to Adobe 2.0
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  * Problems:
637c478bd9Sstevel@tonic-gate  *	- assumes fixed-width (non-proportional) font in some places
647c478bd9Sstevel@tonic-gate  *	- can't back up (using backspaces) over tabs
657c478bd9Sstevel@tonic-gate  *	- assumes 8.5 x 11.0 paper
667c478bd9Sstevel@tonic-gate  *	- uses logical page with aspect ratio of 3 * 4
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #define	USAGE1	"[-{1|2|4|8}] [-p] [-L] [-r] [-n<numberwidth]"
717c478bd9Sstevel@tonic-gate #define	USAGE2	"[-l<lines>|-w<columns>] [-c<count>] [-t<tabs>]"
727c478bd9Sstevel@tonic-gate #define	USAGE3	"[-hstring] [-Bstring] [-Istring] [-Xstring] [-Gstring]"
737c478bd9Sstevel@tonic-gate #define	USAGE4	"[-Pfile] [file ...]"
74*3c2f5c48Sjwadams #define	USAGE6	"[-hstring] [-e] [-y comment] oldfile newfile"
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #include <stdio.h>
777c478bd9Sstevel@tonic-gate #include <string.h>
787c478bd9Sstevel@tonic-gate #include <stdlib.h>
797c478bd9Sstevel@tonic-gate #include <sys/file.h>
807c478bd9Sstevel@tonic-gate #include <ctype.h>
817c478bd9Sstevel@tonic-gate #include <pwd.h>
827c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
837c478bd9Sstevel@tonic-gate #include <sys/stat.h>
847c478bd9Sstevel@tonic-gate #include <unistd.h>
857c478bd9Sstevel@tonic-gate #include <sys/types.h>
867c478bd9Sstevel@tonic-gate #include <time.h>
877c478bd9Sstevel@tonic-gate #include <stdarg.h>
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate  * Configurable...
917c478bd9Sstevel@tonic-gate  * BUFOUT should be fairly large
927c478bd9Sstevel@tonic-gate  */
937c478bd9Sstevel@tonic-gate #define	BUFIN			1024	/* maximum length of an input line */
947c478bd9Sstevel@tonic-gate #define	BUFOUT			(BUFIN * 5)
957c478bd9Sstevel@tonic-gate #define	MAXPAGES		10000
967c478bd9Sstevel@tonic-gate #define	REVERSE_OFF		0
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	DEFAULT_PAPER_HEIGHT	11.0
997c478bd9Sstevel@tonic-gate #define	DEFAULT_PAPER_WIDTH	8.50
1007c478bd9Sstevel@tonic-gate #define	DEFAULT_PAGE_HEIGHT	10.0
1017c478bd9Sstevel@tonic-gate #define	DEFAULT_PAGE_WIDTH	7.50
1027c478bd9Sstevel@tonic-gate #define	DEFAULT_LINES_PER_PAGE	66
1037c478bd9Sstevel@tonic-gate #define	DEFAULT_TAB_SIZE	8
1047c478bd9Sstevel@tonic-gate static char	*default_font = "Courier";
1057c478bd9Sstevel@tonic-gate static char	*default_font_bold = "Courier-Bold";
1067c478bd9Sstevel@tonic-gate static char	*default_font_italic = "Courier-Oblique";
1077c478bd9Sstevel@tonic-gate static char	*default_font_bold_italic = "Courier-BoldOblique";
1087c478bd9Sstevel@tonic-gate static char	*select_default_font = "FRN";
1097c478bd9Sstevel@tonic-gate static char	*select_default_font_bold = "FRB";
1107c478bd9Sstevel@tonic-gate static char	*select_default_font_italic = "FIN";
1117c478bd9Sstevel@tonic-gate static char	*select_default_font_bold_italic = "FIB";
1127c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT			select_default_font
1137c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT_BOLD		select_default_font_bold
1147c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT_ITALIC		select_default_font_italic
1157c478bd9Sstevel@tonic-gate #define	DEFAULT_FONT_BOLD_ITALIC	select_default_font_bold_italic
1167c478bd9Sstevel@tonic-gate #define	DEFAULT_CHAR_WIDTH	(.6)
1177c478bd9Sstevel@tonic-gate #define	DEFAULT_SPACES_AFTER_NUMBER	1
1187c478bd9Sstevel@tonic-gate #define	DEFAULT_DESCENDER_FRACTION	0.3
1197c478bd9Sstevel@tonic-gate #define	LWLP			"lwlp"
1207c478bd9Sstevel@tonic-gate #define	CODEREVIEW		"codereview"
1217c478bd9Sstevel@tonic-gate #define	END_C_FUNCTION		'}'
1227c478bd9Sstevel@tonic-gate #define	END_ASM_FUNCTION	"SET_SIZE("
1237c478bd9Sstevel@tonic-gate static char	*banner =
1247c478bd9Sstevel@tonic-gate 	"**********************************************************";
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate  * PostScript command strings
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate #define	LINETO			"lineto"
1307c478bd9Sstevel@tonic-gate #define	NEWPATH			"newpath"
1317c478bd9Sstevel@tonic-gate #define	SETLINEWIDTH		"setlinewidth"
1327c478bd9Sstevel@tonic-gate #define	STROKE			"stroke"
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate  * PostScript command strings defined in the prologue file
1357c478bd9Sstevel@tonic-gate  */
1367c478bd9Sstevel@tonic-gate #define	BACKSPACE		"B"
1377c478bd9Sstevel@tonic-gate #define	MOVETO			"M"	/* x y */
1387c478bd9Sstevel@tonic-gate #define	SHOW			"S"	/* string */
1397c478bd9Sstevel@tonic-gate #define	TAB			"T"	/* spaces */
1407c478bd9Sstevel@tonic-gate #define	ZEROMOVETO		"Z"	/* y */
1417c478bd9Sstevel@tonic-gate #define	SELECT_FONT		"SFT"	/* size font */
1427c478bd9Sstevel@tonic-gate #define	SET_WIDTHS		"SWT"
1437c478bd9Sstevel@tonic-gate #define	START_PAGE		"SPG"	/* angle scale x y */
1447c478bd9Sstevel@tonic-gate #define	END_PAGE		"EPG"
1457c478bd9Sstevel@tonic-gate #define	FLUSH_PAGE		"FPG"	/* ncopies */
1467c478bd9Sstevel@tonic-gate #define	SHADE			"SHD"	/* x0 y0 x1 y1 */
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate  * Conformance requires that no PostScript line exceed 256 characters
1507c478bd9Sstevel@tonic-gate  */
1517c478bd9Sstevel@tonic-gate #define	POINTS_PER_INCH		72
1527c478bd9Sstevel@tonic-gate #define	MAX_OUTPUT_LINE_LENGTH	256
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate #define	START_X			0	/* position of start of each line */
1557c478bd9Sstevel@tonic-gate #define	THREE_HOLE_X		1.0	/* portrait x offset (inches) 3 hole */
1567c478bd9Sstevel@tonic-gate #define	THREE_HOLE_Y		0.5	/* landscape y offset (inches) 3 hole */
1577c478bd9Sstevel@tonic-gate #define	RULE_WIDTH		0.25	/* width in units of paging rules */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate static struct print_state {
1607c478bd9Sstevel@tonic-gate 	int	page_count;
1617c478bd9Sstevel@tonic-gate 	int	logical_page_count;
1627c478bd9Sstevel@tonic-gate 	int	lineno;
1637c478bd9Sstevel@tonic-gate 	long	offset;
1647c478bd9Sstevel@tonic-gate 	float	row;
1657c478bd9Sstevel@tonic-gate 	char	*font;
1667c478bd9Sstevel@tonic-gate }	current, saved;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate struct format_state {
1697c478bd9Sstevel@tonic-gate 	int	numberwidth, linenumber, altlinenumber;
1707c478bd9Sstevel@tonic-gate 	int	makegray;
1717c478bd9Sstevel@tonic-gate 	char	*font;
1727c478bd9Sstevel@tonic-gate };
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate static int	change_seen, dots_inserted, in_change, old_stuff, makegray;
1757c478bd9Sstevel@tonic-gate static int	lines_per_page;
1767c478bd9Sstevel@tonic-gate static int	columns;
1777c478bd9Sstevel@tonic-gate static float	point_size;
1787c478bd9Sstevel@tonic-gate static int	start_x, start_y, end_x;
1797c478bd9Sstevel@tonic-gate static int	landscape, rot_text;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static int	ncopies;
1827c478bd9Sstevel@tonic-gate static int	tabstop;
1837c478bd9Sstevel@tonic-gate static int	reverse;
1847c478bd9Sstevel@tonic-gate static int	elide;
1857c478bd9Sstevel@tonic-gate static int	usetmp;
1867c478bd9Sstevel@tonic-gate static int	dflag, lflag, pflag, vflag, wflag;
1877c478bd9Sstevel@tonic-gate static int	numberwidth, linenumber, altlinenumber;
1887c478bd9Sstevel@tonic-gate static int	boldlength, itlclength, bitclength, graylength;
1897c478bd9Sstevel@tonic-gate static char	*boldstring, *itlcstring, *bitcstring, *graystring;
1907c478bd9Sstevel@tonic-gate #define	HEADER_EXPLICIT	1
1917c478bd9Sstevel@tonic-gate #define	HEADER_IMPLICIT	2
1927c478bd9Sstevel@tonic-gate static int	header = HEADER_IMPLICIT;
1937c478bd9Sstevel@tonic-gate static char	*headerstring;
1947c478bd9Sstevel@tonic-gate static char	*bannerfile;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate static char	bufin[BUFIN];		/* input buffer */
1977c478bd9Sstevel@tonic-gate static char	bufout[BUFOUT];		/* output buffer */
1987c478bd9Sstevel@tonic-gate static long	*page_map;		/* offset of first byte of each page */
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate static char	*username, *hostname, *currentdate;
201*3c2f5c48Sjwadams static char	*comment;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate static void	preamble(void);
2047c478bd9Sstevel@tonic-gate static void	postamble(void);
2057c478bd9Sstevel@tonic-gate static void	setcurrentfont(char *, FILE *);
2067c478bd9Sstevel@tonic-gate static void	savestate(FILE *);
2077c478bd9Sstevel@tonic-gate static void	restorestate(FILE *);
2087c478bd9Sstevel@tonic-gate static void	save_format_state(struct format_state *);
2097c478bd9Sstevel@tonic-gate static void	printfile(FILE *);
2107c478bd9Sstevel@tonic-gate static int	printpage(FILE *, FILE *);
2117c478bd9Sstevel@tonic-gate static int	startpage(FILE *);
2127c478bd9Sstevel@tonic-gate static void	endpage(FILE *);
2137c478bd9Sstevel@tonic-gate static void	copypage(FILE *, long, long);
2147c478bd9Sstevel@tonic-gate static void	process_elide(FILE *);
2157c478bd9Sstevel@tonic-gate static void	setheaderfile(char *);
2167c478bd9Sstevel@tonic-gate static void	restore_format_state(struct format_state *, FILE *);
2177c478bd9Sstevel@tonic-gate static void	flushpage(FILE *);
2187c478bd9Sstevel@tonic-gate static void	setuppage(FILE *);
2197c478bd9Sstevel@tonic-gate static void	reversepages(FILE *);
2207c478bd9Sstevel@tonic-gate static void	proc(char *, FILE *);
2217c478bd9Sstevel@tonic-gate static void	setup(void);
2227c478bd9Sstevel@tonic-gate static int	printbanner(char *, FILE *);
2237c478bd9Sstevel@tonic-gate static char	*fgetline(char *, int, FILE *);
2247c478bd9Sstevel@tonic-gate static void	fatal(char *fmt, ...);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate static char	*prologue;
2277c478bd9Sstevel@tonic-gate static char	*progname;
2287c478bd9Sstevel@tonic-gate static int	iscodereview;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate static char	*default_prologue[] = {
2317c478bd9Sstevel@tonic-gate "%%EndComments\n",
2327c478bd9Sstevel@tonic-gate "%\n",
2337c478bd9Sstevel@tonic-gate "% PostScript Prologue for lwlp LaserWriter Line Printer\n",
2347c478bd9Sstevel@tonic-gate "%\n",
2357c478bd9Sstevel@tonic-gate "/SFT {findfont exch scalefont setfont}bind def\n",
2367c478bd9Sstevel@tonic-gate "/SWT {( ) stringwidth pop dup /W exch def neg /NW exch def}bind def\n",
2377c478bd9Sstevel@tonic-gate "/SPG {/SV save def translate dup scale rotate}bind def\n",
2387c478bd9Sstevel@tonic-gate "/EPG {SV restore}bind def\n",
2397c478bd9Sstevel@tonic-gate "/FPG {/#copies exch def showpage}bind def\n",
2407c478bd9Sstevel@tonic-gate "/B {NW 0 rmoveto}def\n",
2417c478bd9Sstevel@tonic-gate "/M /moveto load def\n",
2427c478bd9Sstevel@tonic-gate "/T {W mul 0 rmoveto}def\n",
2437c478bd9Sstevel@tonic-gate "/S /show load def\n",
2447c478bd9Sstevel@tonic-gate "/Z {0 exch moveto}bind def\n",
2457c478bd9Sstevel@tonic-gate "/SHD {save 5 1 roll			% S x1 y1 x0 y0\n",
2467c478bd9Sstevel@tonic-gate "	2 copy moveto			% S x1 y1 x0 y0\n",
2477c478bd9Sstevel@tonic-gate "	3 index exch lineto		% S x1 y1 x0\n",
2487c478bd9Sstevel@tonic-gate "	3 -1 roll 2 index lineto	% S y1 x0\n",
2497c478bd9Sstevel@tonic-gate "	exch lineto			% S\n",
2507c478bd9Sstevel@tonic-gate "	0.95 setgray fill		% S\n",
2517c478bd9Sstevel@tonic-gate "	restore}def\n",
2527c478bd9Sstevel@tonic-gate "%%EndProlog\n",
2537c478bd9Sstevel@tonic-gate 	NULL
2547c478bd9Sstevel@tonic-gate };
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate struct layout {
2577c478bd9Sstevel@tonic-gate 	float	scale;
2587c478bd9Sstevel@tonic-gate 	int	pages, page_rows, page_cols;
2597c478bd9Sstevel@tonic-gate 	int	rotation;
2607c478bd9Sstevel@tonic-gate };
2617c478bd9Sstevel@tonic-gate static struct layout	*layoutp;
2627c478bd9Sstevel@tonic-gate static struct layout	layout1 = { 1.000000, 1, 1, 1, 0 };
2637c478bd9Sstevel@tonic-gate static struct layout	layout2 = { 0.666666, 2, 2, 1, 90 };
2647c478bd9Sstevel@tonic-gate static struct layout	layout4 = { 0.500000, 4, 2, 2, 0 };
2657c478bd9Sstevel@tonic-gate static struct layout	layout8 = { 0.333333, 8, 4, 2, 90 };
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate static int	box_width, box_height;
2687c478bd9Sstevel@tonic-gate static int	gap_width, gap_height;
2697c478bd9Sstevel@tonic-gate static int	margin_x, margin_y;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate static struct position {
2727c478bd9Sstevel@tonic-gate 	int	base_x;
2737c478bd9Sstevel@tonic-gate 	int	base_y;
2747c478bd9Sstevel@tonic-gate }	positions[8];
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate int
2777c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2787c478bd9Sstevel@tonic-gate {
2797c478bd9Sstevel@tonic-gate 	int	ch, i, j, first_file;
2807c478bd9Sstevel@tonic-gate 	char	*pc;
2817c478bd9Sstevel@tonic-gate 	FILE	*infile;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	if ((pc = strrchr(argv[0], '/')) != NULL)
2847c478bd9Sstevel@tonic-gate 		progname = pc + 1;
2857c478bd9Sstevel@tonic-gate 	else
2867c478bd9Sstevel@tonic-gate 		progname = argv[0];
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	lines_per_page = DEFAULT_LINES_PER_PAGE;
2897c478bd9Sstevel@tonic-gate 	layoutp = &layout1;
2907c478bd9Sstevel@tonic-gate 	tabstop = DEFAULT_TAB_SIZE;
2917c478bd9Sstevel@tonic-gate 	current.page_count = 0;
2927c478bd9Sstevel@tonic-gate 	ncopies = 1;
2937c478bd9Sstevel@tonic-gate 	reverse = REVERSE_OFF;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	/*LINTED*/
2967c478bd9Sstevel@tonic-gate 	if (iscodereview = strncmp(progname, CODEREVIEW,
2977c478bd9Sstevel@tonic-gate 			sizeof (CODEREVIEW) - 1) == 0) {
2987c478bd9Sstevel@tonic-gate 		layoutp = &layout2;
2997c478bd9Sstevel@tonic-gate 		numberwidth = 4;
3007c478bd9Sstevel@tonic-gate 		columns = 85;		/* extra space for numbering */
3017c478bd9Sstevel@tonic-gate 		wflag = -1;
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	while ((ch = getopt(argc, argv,
305*3c2f5c48Sjwadams 			"1248B:c:deG:h:I:l:Ln:P:prt:vw:X:y:")) != -1) {
3067c478bd9Sstevel@tonic-gate 		switch (ch) {
3077c478bd9Sstevel@tonic-gate 		case '1':
3087c478bd9Sstevel@tonic-gate 			layoutp = &layout1;
3097c478bd9Sstevel@tonic-gate 			break;
3107c478bd9Sstevel@tonic-gate 		case '2':
3117c478bd9Sstevel@tonic-gate 			layoutp = &layout2;
3127c478bd9Sstevel@tonic-gate 			break;
3137c478bd9Sstevel@tonic-gate 		case '4':
3147c478bd9Sstevel@tonic-gate 			layoutp = &layout4;
3157c478bd9Sstevel@tonic-gate 			break;
3167c478bd9Sstevel@tonic-gate 		case '8':
3177c478bd9Sstevel@tonic-gate 			layoutp = &layout8;
3187c478bd9Sstevel@tonic-gate 			break;
3197c478bd9Sstevel@tonic-gate 		case 'B':
3207c478bd9Sstevel@tonic-gate 			boldlength = strlen(optarg);
3217c478bd9Sstevel@tonic-gate 			boldstring = malloc((size_t)(boldlength + 1));
3227c478bd9Sstevel@tonic-gate 			(void) strcpy(boldstring, optarg);
3237c478bd9Sstevel@tonic-gate 			break;
3247c478bd9Sstevel@tonic-gate 		case 'c':
3257c478bd9Sstevel@tonic-gate 			ncopies = atof(optarg);
3267c478bd9Sstevel@tonic-gate 			if (ncopies <= 0) {
3277c478bd9Sstevel@tonic-gate 				fatal("number of copies must be > 0");
3287c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
3297c478bd9Sstevel@tonic-gate 			}
3307c478bd9Sstevel@tonic-gate 			break;
3317c478bd9Sstevel@tonic-gate 		case 'd':
3327c478bd9Sstevel@tonic-gate 			dflag = 1;
3337c478bd9Sstevel@tonic-gate 			break;
3347c478bd9Sstevel@tonic-gate 		case 'e':
3357c478bd9Sstevel@tonic-gate 			elide = 1;
3367c478bd9Sstevel@tonic-gate 			break;
3377c478bd9Sstevel@tonic-gate 		case 'G':
3387c478bd9Sstevel@tonic-gate 			graylength = strlen(optarg);
3397c478bd9Sstevel@tonic-gate 			graystring = malloc((size_t)(graylength + 1));
3407c478bd9Sstevel@tonic-gate 			(void) strcpy(graystring, optarg);
3417c478bd9Sstevel@tonic-gate 			break;
3427c478bd9Sstevel@tonic-gate 		case 'h':
3437c478bd9Sstevel@tonic-gate 			header = HEADER_EXPLICIT;
3447c478bd9Sstevel@tonic-gate 			i = strlen(optarg);
3457c478bd9Sstevel@tonic-gate 			headerstring = malloc((size_t)(i + 1));
3467c478bd9Sstevel@tonic-gate 			(void) strcpy(headerstring, optarg);
3477c478bd9Sstevel@tonic-gate 			if (strcmp(headerstring, "-") == 0)
3487c478bd9Sstevel@tonic-gate 				header = HEADER_IMPLICIT;
3497c478bd9Sstevel@tonic-gate 			break;
3507c478bd9Sstevel@tonic-gate 		case 'I':
3517c478bd9Sstevel@tonic-gate 			itlclength = strlen(optarg);
3527c478bd9Sstevel@tonic-gate 			itlcstring = malloc((size_t)(itlclength + 1));
3537c478bd9Sstevel@tonic-gate 			(void) strcpy(itlcstring, optarg);
3547c478bd9Sstevel@tonic-gate 			break;
3557c478bd9Sstevel@tonic-gate 		case 'l':
3567c478bd9Sstevel@tonic-gate 			lines_per_page = atoi(optarg);
3577c478bd9Sstevel@tonic-gate 			if (lines_per_page < 1) {
3587c478bd9Sstevel@tonic-gate 				fatal("invalid number of lines/page");
3597c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
3607c478bd9Sstevel@tonic-gate 			}
3617c478bd9Sstevel@tonic-gate 			lflag = 1;
3627c478bd9Sstevel@tonic-gate 			if (wflag > 0) {
3637c478bd9Sstevel@tonic-gate 				fatal("can't have both -l and -w");
3647c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
3657c478bd9Sstevel@tonic-gate 			}
3667c478bd9Sstevel@tonic-gate 			wflag = 0;
3677c478bd9Sstevel@tonic-gate 			break;
3687c478bd9Sstevel@tonic-gate 		case 'L':
3697c478bd9Sstevel@tonic-gate 			landscape = 1;
3707c478bd9Sstevel@tonic-gate 			break;
3717c478bd9Sstevel@tonic-gate 		case 'm':
3727c478bd9Sstevel@tonic-gate 			break;
3737c478bd9Sstevel@tonic-gate 		case 'n':
3747c478bd9Sstevel@tonic-gate 			numberwidth = atoi(optarg);
3757c478bd9Sstevel@tonic-gate 			if (numberwidth < 2) {
3767c478bd9Sstevel@tonic-gate 				fatal("invalid numbering width");
3777c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
3787c478bd9Sstevel@tonic-gate 			}
3797c478bd9Sstevel@tonic-gate 			break;
3807c478bd9Sstevel@tonic-gate 		case 'P':
3817c478bd9Sstevel@tonic-gate 			prologue = optarg;
3827c478bd9Sstevel@tonic-gate 			break;
3837c478bd9Sstevel@tonic-gate 		case 'p':
3847c478bd9Sstevel@tonic-gate 			pflag = 1;
3857c478bd9Sstevel@tonic-gate 			break;
3867c478bd9Sstevel@tonic-gate 		case 'r':
3877c478bd9Sstevel@tonic-gate 			reverse = !reverse;
3887c478bd9Sstevel@tonic-gate 			break;
3897c478bd9Sstevel@tonic-gate 		case 't':
3907c478bd9Sstevel@tonic-gate 			tabstop = atoi(optarg);
3917c478bd9Sstevel@tonic-gate 			if (tabstop < 1) {
3927c478bd9Sstevel@tonic-gate 				fatal("negative tabstop");
3937c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
3947c478bd9Sstevel@tonic-gate 			}
3957c478bd9Sstevel@tonic-gate 			break;
3967c478bd9Sstevel@tonic-gate 		case 'v':
3977c478bd9Sstevel@tonic-gate 			vflag = 1;
3987c478bd9Sstevel@tonic-gate 			break;
3997c478bd9Sstevel@tonic-gate 		case 'w':
4007c478bd9Sstevel@tonic-gate 			columns = atoi(optarg);
4017c478bd9Sstevel@tonic-gate 			if (columns < 1) {
4027c478bd9Sstevel@tonic-gate 				fatal("invalid number of columns");
4037c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
4047c478bd9Sstevel@tonic-gate 			}
4057c478bd9Sstevel@tonic-gate 			wflag = 1;
4067c478bd9Sstevel@tonic-gate 			if (lflag) {
4077c478bd9Sstevel@tonic-gate 				fatal("can't have both -l and -w");
4087c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
4097c478bd9Sstevel@tonic-gate 			}
4107c478bd9Sstevel@tonic-gate 			break;
4117c478bd9Sstevel@tonic-gate 		case 'X':
4127c478bd9Sstevel@tonic-gate 			bitclength = strlen(optarg);
4137c478bd9Sstevel@tonic-gate 			bitcstring = malloc((size_t)(bitclength + 1));
4147c478bd9Sstevel@tonic-gate 			(void) strcpy(bitcstring, optarg);
4157c478bd9Sstevel@tonic-gate 			break;
416*3c2f5c48Sjwadams 		case 'y':
417*3c2f5c48Sjwadams 			comment = optarg;
418*3c2f5c48Sjwadams 			break;
4197c478bd9Sstevel@tonic-gate 		default:
4207c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
4217c478bd9Sstevel@tonic-gate 					"usage: %s %s\n\t%s\n\t%s\n\t%s\n",
4227c478bd9Sstevel@tonic-gate 					iscodereview ? LWLP : progname,
4237c478bd9Sstevel@tonic-gate 					USAGE1, USAGE2, USAGE3, USAGE4);
4247c478bd9Sstevel@tonic-gate 			if (iscodereview)
4257c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "\t%s [%s flags] %s\n",
4267c478bd9Sstevel@tonic-gate 						CODEREVIEW, LWLP, USAGE6);
4277c478bd9Sstevel@tonic-gate 			exit(1);
4287c478bd9Sstevel@tonic-gate 		}
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	if (elide && !iscodereview) {
4327c478bd9Sstevel@tonic-gate 		fatal("-e option valid only with codereview");
4337c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
4347c478bd9Sstevel@tonic-gate 	}
4357c478bd9Sstevel@tonic-gate 	usetmp = reverse || elide;
4367c478bd9Sstevel@tonic-gate 	/* allocate page_map if we need one */
4377c478bd9Sstevel@tonic-gate 	if (reverse) {
4387c478bd9Sstevel@tonic-gate 		page_map = malloc((size_t)(MAXPAGES * sizeof (long *)));
4397c478bd9Sstevel@tonic-gate 		if (page_map == NULL) {
4407c478bd9Sstevel@tonic-gate 			fatal("unable to allocate memory for page reversal");
4417c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
4427c478bd9Sstevel@tonic-gate 		}
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	/*
4467c478bd9Sstevel@tonic-gate 	 * Check that all files are readable
4477c478bd9Sstevel@tonic-gate 	 * This is so that no output at all is produced if any file is not
4487c478bd9Sstevel@tonic-gate 	 * readable in case the output is being piped to a printer
4497c478bd9Sstevel@tonic-gate 	 */
4507c478bd9Sstevel@tonic-gate 	first_file = optind;
4517c478bd9Sstevel@tonic-gate 	for (j = first_file; j < argc; j++) {
4527c478bd9Sstevel@tonic-gate 		if (access(argv[j], R_OK) == -1 && !(iscodereview &&
4537c478bd9Sstevel@tonic-gate 		    strcmp(argv[j], "-") == 0)) {
4547c478bd9Sstevel@tonic-gate 			fatal("cannot access %s", argv[j]);
4557c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 	if (iscodereview && (first_file + 2) != argc) {
4597c478bd9Sstevel@tonic-gate 		fatal("codereview: need old and new file");
4607c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
4617c478bd9Sstevel@tonic-gate 	}
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	/* compute logical point size, logical dimensions */
4647c478bd9Sstevel@tonic-gate 	if (!landscape) {
4657c478bd9Sstevel@tonic-gate 		rot_text = layoutp->rotation;
4667c478bd9Sstevel@tonic-gate 		start_y = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH;
4677c478bd9Sstevel@tonic-gate 		start_x = START_X;
4687c478bd9Sstevel@tonic-gate 		end_x = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH;
4697c478bd9Sstevel@tonic-gate 		if (wflag) {
4707c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
4717c478bd9Sstevel@tonic-gate 					((columns + 0.5) * DEFAULT_CHAR_WIDTH);
4727c478bd9Sstevel@tonic-gate 			lines_per_page = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
4737c478bd9Sstevel@tonic-gate 					point_size;
4747c478bd9Sstevel@tonic-gate 		} else {
4757c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
4767c478bd9Sstevel@tonic-gate 					(lines_per_page + 0.5);
4777c478bd9Sstevel@tonic-gate 			columns = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
4787c478bd9Sstevel@tonic-gate 					(point_size * DEFAULT_CHAR_WIDTH);
4797c478bd9Sstevel@tonic-gate 		}
4807c478bd9Sstevel@tonic-gate 	} else {
4817c478bd9Sstevel@tonic-gate 		rot_text = 90 - layoutp->rotation;
4827c478bd9Sstevel@tonic-gate 		start_y = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH;
4837c478bd9Sstevel@tonic-gate 		start_x = START_X;
4847c478bd9Sstevel@tonic-gate 		end_x = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH;
4857c478bd9Sstevel@tonic-gate 		if (wflag) {
4867c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
4877c478bd9Sstevel@tonic-gate 					((columns + 0.5) * DEFAULT_CHAR_WIDTH);
4887c478bd9Sstevel@tonic-gate 			lines_per_page = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
4897c478bd9Sstevel@tonic-gate 					point_size;
4907c478bd9Sstevel@tonic-gate 		} else {
4917c478bd9Sstevel@tonic-gate 			point_size = DEFAULT_PAGE_WIDTH * POINTS_PER_INCH /
4927c478bd9Sstevel@tonic-gate 					(lines_per_page + 0.5);
4937c478bd9Sstevel@tonic-gate 			columns = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH /
4947c478bd9Sstevel@tonic-gate 					(point_size * DEFAULT_CHAR_WIDTH);
4957c478bd9Sstevel@tonic-gate 		}
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	box_height = DEFAULT_PAGE_HEIGHT * POINTS_PER_INCH / layoutp->page_rows;
4997c478bd9Sstevel@tonic-gate 	if (layoutp->rotation == 0)
5007c478bd9Sstevel@tonic-gate 		box_width = box_height /
5017c478bd9Sstevel@tonic-gate 				DEFAULT_PAGE_HEIGHT * DEFAULT_PAGE_WIDTH;
5027c478bd9Sstevel@tonic-gate 	else
5037c478bd9Sstevel@tonic-gate 		box_width = box_height *
5047c478bd9Sstevel@tonic-gate 				DEFAULT_PAGE_HEIGHT / DEFAULT_PAGE_WIDTH;
5057c478bd9Sstevel@tonic-gate 	gap_width = DEFAULT_PAPER_WIDTH * POINTS_PER_INCH /
5067c478bd9Sstevel@tonic-gate 			layoutp->page_cols - box_width;
5077c478bd9Sstevel@tonic-gate 	gap_height = DEFAULT_PAPER_HEIGHT * POINTS_PER_INCH /
5087c478bd9Sstevel@tonic-gate 			layoutp->page_rows - box_height;
5097c478bd9Sstevel@tonic-gate 	margin_x = gap_width/2;
5107c478bd9Sstevel@tonic-gate 	margin_y = gap_height/2;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	columns -= numberwidth + DEFAULT_SPACES_AFTER_NUMBER;
5137c478bd9Sstevel@tonic-gate 	if (columns <= 0) {
5147c478bd9Sstevel@tonic-gate 		fatal("numbering width exceeds number of columns");
5157c478bd9Sstevel@tonic-gate 		/* NOT REACHED */
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate 	/* compute physical "lower left corner" of each logical page */
5187c478bd9Sstevel@tonic-gate 	for (j = 0; j < layoutp->pages; j++) {
5197c478bd9Sstevel@tonic-gate 		int	phys_row;		/* 0 is bottom row */
5207c478bd9Sstevel@tonic-gate 		int	phys_col;		/* 0 is left column */
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 		if (landscape == (rot_text == 0)) {
5237c478bd9Sstevel@tonic-gate 			/* logical pages run physically up and down */
5247c478bd9Sstevel@tonic-gate 			phys_row = j % layoutp->page_rows;
5257c478bd9Sstevel@tonic-gate 			phys_col = j / layoutp->page_rows;
5267c478bd9Sstevel@tonic-gate 		} else {
5277c478bd9Sstevel@tonic-gate 			/* logical pages run physically left to right */
5287c478bd9Sstevel@tonic-gate 			phys_row = j / layoutp->page_cols;
5297c478bd9Sstevel@tonic-gate 			phys_col = j % layoutp->page_cols;
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 		if (rot_text == 0) {
5327c478bd9Sstevel@tonic-gate 			/* top physical row is logically first */
5337c478bd9Sstevel@tonic-gate 			phys_row = layoutp->page_rows - 1 - phys_row;
5347c478bd9Sstevel@tonic-gate 		}
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 		positions[j].base_x = margin_x +
5377c478bd9Sstevel@tonic-gate 				phys_col * (box_width + gap_width);
5387c478bd9Sstevel@tonic-gate 		positions[j].base_y = margin_y +
5397c478bd9Sstevel@tonic-gate 				phys_row * (box_height + gap_height);
5407c478bd9Sstevel@tonic-gate 		if (rot_text != 0) {
5417c478bd9Sstevel@tonic-gate 			positions[j].base_x += box_width;
5427c478bd9Sstevel@tonic-gate 		}
5437c478bd9Sstevel@tonic-gate 	}
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	if (vflag) {
5467c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n\n", progname, sccsid);
5477c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Lines/page = %d\n", lines_per_page);
5487c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Columns = %d\n", columns);
5497c478bd9Sstevel@tonic-gate 		for (j = 0; j < layoutp->pages; j++) {
5507c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\tx=%3d, y=%3d\n",
5517c478bd9Sstevel@tonic-gate 					positions[j].base_x,
5527c478bd9Sstevel@tonic-gate 					positions[j].base_y);
5537c478bd9Sstevel@tonic-gate 		}
5547c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "box_width=%3d, box_height=%3d\n",
5557c478bd9Sstevel@tonic-gate 				box_width, box_height);
5567c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "gap_width=%3d, gap_height=%3d\n",
5577c478bd9Sstevel@tonic-gate 				gap_width, gap_height);
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	setup();
5617c478bd9Sstevel@tonic-gate 	preamble();
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	if (iscodereview) {
5647c478bd9Sstevel@tonic-gate 		char	command[BUFSIZ];
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		(void) snprintf(command, BUFSIZ, "diff -b -D %s %s %s",
5677c478bd9Sstevel@tonic-gate 			CODEREVIEW, argv[first_file+1], argv[first_file]);
5687c478bd9Sstevel@tonic-gate 		infile = popen(command, "r");
5697c478bd9Sstevel@tonic-gate 		bannerfile = argv[first_file+1];
5707c478bd9Sstevel@tonic-gate 		if (ungetc(getc(infile), infile) == EOF) {
5717c478bd9Sstevel@tonic-gate 			(void) pclose(infile);
5727c478bd9Sstevel@tonic-gate 			(void) sprintf(command,
5737c478bd9Sstevel@tonic-gate 					"echo No differences encountered");
5747c478bd9Sstevel@tonic-gate 			infile = popen(command, "r");
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate 		setheaderfile(bannerfile);
5777c478bd9Sstevel@tonic-gate 		printfile(infile);
5787c478bd9Sstevel@tonic-gate 		(void) pclose(infile);
5797c478bd9Sstevel@tonic-gate 	} else if (first_file == argc) {	/* no files on command line */
5807c478bd9Sstevel@tonic-gate 		if (vflag)
5817c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\tprinting stdin\n");
5827c478bd9Sstevel@tonic-gate 		setheaderfile("stdin");
5837c478bd9Sstevel@tonic-gate 		printfile(stdin);
5847c478bd9Sstevel@tonic-gate 	} else {
5857c478bd9Sstevel@tonic-gate 		for (i = first_file; i < argc; i++) {
5867c478bd9Sstevel@tonic-gate 			if ((infile = fopen(argv[i], "r")) == (FILE *)NULL) {
5877c478bd9Sstevel@tonic-gate 				fatal("can't open %s for reading", argv[i]);
5887c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
5897c478bd9Sstevel@tonic-gate 			}
5907c478bd9Sstevel@tonic-gate 			if (pflag) {
5917c478bd9Sstevel@tonic-gate 				char	cmdbuf[BUFSIZ];
5927c478bd9Sstevel@tonic-gate 				(void) snprintf(cmdbuf, BUFSIZ, "pr %s",
5937c478bd9Sstevel@tonic-gate 				    argv[i]);
5947c478bd9Sstevel@tonic-gate 				(void) fclose(infile);
5957c478bd9Sstevel@tonic-gate 				infile = popen(cmdbuf, "r");
5967c478bd9Sstevel@tonic-gate 			}
5977c478bd9Sstevel@tonic-gate 			if (vflag)
5987c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "\tprinting %s\n",
5997c478bd9Sstevel@tonic-gate 						argv[i]);
6007c478bd9Sstevel@tonic-gate 			setheaderfile(argv[i]);
6017c478bd9Sstevel@tonic-gate 			printfile(infile);
6027c478bd9Sstevel@tonic-gate 			if (pflag)
6037c478bd9Sstevel@tonic-gate 				(void) pclose(infile);
6047c478bd9Sstevel@tonic-gate 			else
6057c478bd9Sstevel@tonic-gate 				(void) fclose(infile);
6067c478bd9Sstevel@tonic-gate 		}
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	postamble();
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	if (fflush(stdout) == EOF) {
6127c478bd9Sstevel@tonic-gate 		fatal("write error on stdout");
6137c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
6147c478bd9Sstevel@tonic-gate 	}
6157c478bd9Sstevel@tonic-gate 	exit(0);
6167c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
6177c478bd9Sstevel@tonic-gate 	/*LINTED*/
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate  * Initial lines sent to the LaserWriter
6227c478bd9Sstevel@tonic-gate  * Generates the PostScript header and includes the prologue file
6237c478bd9Sstevel@tonic-gate  * There is limited checking for I/O errors here
6247c478bd9Sstevel@tonic-gate  */
6257c478bd9Sstevel@tonic-gate void
6267c478bd9Sstevel@tonic-gate preamble(void)
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate 	(void) printf("%%!PS-Adobe-2.0\n");
6297c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Creator: %s on %s\n", progname, hostname);
6307c478bd9Sstevel@tonic-gate 	(void) printf("%%%%CreationDate: %s\n", currentdate);
6317c478bd9Sstevel@tonic-gate 	(void) printf("%%%%For: %s\n", username);
6327c478bd9Sstevel@tonic-gate 	(void) printf("%%%%DocumentFonts: %s %s %s %s\n",
6337c478bd9Sstevel@tonic-gate 		default_font, default_font_bold,
6347c478bd9Sstevel@tonic-gate 		default_font_italic, default_font_bold_italic);
6357c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Pages: (atend)\n");
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	if (prologue == NULL) {
6387c478bd9Sstevel@tonic-gate 		char	**cpp;
6397c478bd9Sstevel@tonic-gate 		for (cpp = default_prologue; *cpp; cpp++) {
6407c478bd9Sstevel@tonic-gate 			(void) fputs(*cpp, stdout);
6417c478bd9Sstevel@tonic-gate 		}
6427c478bd9Sstevel@tonic-gate 	} else {
6437c478bd9Sstevel@tonic-gate 		FILE	*fp;
6447c478bd9Sstevel@tonic-gate 		if ((fp = fopen(prologue, "r")) == NULL) {
6457c478bd9Sstevel@tonic-gate 			fatal("can't open prologue file %s", prologue);
6467c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
6477c478bd9Sstevel@tonic-gate 		}
6487c478bd9Sstevel@tonic-gate 		while (fgets(bufin, sizeof (bufin), fp) != NULL)
6497c478bd9Sstevel@tonic-gate 			(void) fputs(bufin, stdout);
6507c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
6517c478bd9Sstevel@tonic-gate 	}
6527c478bd9Sstevel@tonic-gate 	if (ferror(stdout) || fflush(stdout) == EOF) {
6537c478bd9Sstevel@tonic-gate 		fatal("write error on stdout");
6547c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT,
6587c478bd9Sstevel@tonic-gate 			point_size, default_font, SELECT_FONT);
6597c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT_BOLD,
6607c478bd9Sstevel@tonic-gate 			point_size, default_font_bold, SELECT_FONT);
6617c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT_ITALIC,
6627c478bd9Sstevel@tonic-gate 			point_size, default_font_italic, SELECT_FONT);
6637c478bd9Sstevel@tonic-gate 	(void) printf("/%s {%f /%s %s}bind def\n", DEFAULT_FONT_BOLD_ITALIC,
6647c478bd9Sstevel@tonic-gate 			point_size, default_font_bold_italic, SELECT_FONT);
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate void
6687c478bd9Sstevel@tonic-gate postamble(void)
6697c478bd9Sstevel@tonic-gate {
6707c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Trailer\n");
6717c478bd9Sstevel@tonic-gate 	(void) printf("%%%%Pages: %d\n", current.page_count);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate int
6757c478bd9Sstevel@tonic-gate printbanner(char *filename, FILE *outfile)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	char		buffer[BUFSIZ];
6787c478bd9Sstevel@tonic-gate 	struct stat	statbuf;
6797c478bd9Sstevel@tonic-gate 	struct format_state	format_state;
6807c478bd9Sstevel@tonic-gate 	int		nlines = 0;
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	/* we've already verified readability */
6837c478bd9Sstevel@tonic-gate 	(void) stat(filename, &statbuf);
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	save_format_state(&format_state);
6867c478bd9Sstevel@tonic-gate 	numberwidth = 0;
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	setcurrentfont(DEFAULT_FONT_BOLD_ITALIC, outfile);
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	current.row -= point_size;
6917c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row, MOVETO);
6927c478bd9Sstevel@tonic-gate 	proc(banner, outfile);
6937c478bd9Sstevel@tonic-gate 	nlines++;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	current.row -= point_size;
6967c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row, MOVETO);
6977c478bd9Sstevel@tonic-gate 	(void) snprintf(buffer, BUFSIZ, "%8ld %.24s", statbuf.st_size,
6987c478bd9Sstevel@tonic-gate 	    ctime(&statbuf.st_mtime));
6997c478bd9Sstevel@tonic-gate 	proc(buffer, outfile);
7007c478bd9Sstevel@tonic-gate 	nlines++;
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	do {
7037c478bd9Sstevel@tonic-gate 		current.row -= point_size;
7047c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row,
7057c478bd9Sstevel@tonic-gate 		    MOVETO);
7067c478bd9Sstevel@tonic-gate 		filename += sprintf(buffer, "%.*s", columns, filename);
7077c478bd9Sstevel@tonic-gate 		proc(buffer, outfile);
7087c478bd9Sstevel@tonic-gate 		nlines++;
7097c478bd9Sstevel@tonic-gate 	} while (strlen(filename) != 0);
7107c478bd9Sstevel@tonic-gate 
711*3c2f5c48Sjwadams 	if (comment != NULL && comment[0] != 0) {
712*3c2f5c48Sjwadams 		const char *cur = comment;
713*3c2f5c48Sjwadams 		const char *endl;
714*3c2f5c48Sjwadams 		int len;
715*3c2f5c48Sjwadams 
716*3c2f5c48Sjwadams 		while (*cur != 0) {
717*3c2f5c48Sjwadams 			current.row -= point_size;
718*3c2f5c48Sjwadams 			(void) fprintf(outfile, "%d %.2f %s\n", start_x,
719*3c2f5c48Sjwadams 			    current.row, MOVETO);
720*3c2f5c48Sjwadams 
721*3c2f5c48Sjwadams 			endl = strchr(cur, '\n');
722*3c2f5c48Sjwadams 			if (endl == NULL)
723*3c2f5c48Sjwadams 				endl = cur + strlen(cur);
724*3c2f5c48Sjwadams 
725*3c2f5c48Sjwadams 			/* truncate to columns */
726*3c2f5c48Sjwadams 			len = endl - cur;
727*3c2f5c48Sjwadams 			if (len > columns)
728*3c2f5c48Sjwadams 				len = columns;
729*3c2f5c48Sjwadams 			(void) sprintf(buffer, "%.*s", len, cur);
730*3c2f5c48Sjwadams 			proc(buffer, outfile);
731*3c2f5c48Sjwadams 			nlines++;
732*3c2f5c48Sjwadams 
733*3c2f5c48Sjwadams 			if (*endl == 0)
734*3c2f5c48Sjwadams 				break;
735*3c2f5c48Sjwadams 			cur = endl + 1;
736*3c2f5c48Sjwadams 		}
737*3c2f5c48Sjwadams 	}
738*3c2f5c48Sjwadams 
7397c478bd9Sstevel@tonic-gate 	current.row -= point_size;
7407c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row, MOVETO);
7417c478bd9Sstevel@tonic-gate 	proc(banner, outfile);
7427c478bd9Sstevel@tonic-gate 	nlines++;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	restore_format_state(&format_state, outfile);
7457c478bd9Sstevel@tonic-gate 	savestate(outfile);
7467c478bd9Sstevel@tonic-gate 	return (nlines);
7477c478bd9Sstevel@tonic-gate }
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate void
7507c478bd9Sstevel@tonic-gate setcurrentfont(char *newfont, FILE *outfile)
7517c478bd9Sstevel@tonic-gate {
7527c478bd9Sstevel@tonic-gate 	if (current.font != newfont) {
7537c478bd9Sstevel@tonic-gate 		if (newfont)
7547c478bd9Sstevel@tonic-gate 			current.font = newfont;
7557c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%s\n", current.font);
7567c478bd9Sstevel@tonic-gate 	}
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate void
7607c478bd9Sstevel@tonic-gate savestate(FILE *f)
7617c478bd9Sstevel@tonic-gate {
7627c478bd9Sstevel@tonic-gate 	current.offset = ftell(f);
7637c478bd9Sstevel@tonic-gate 	saved = current;
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate void
7677c478bd9Sstevel@tonic-gate restorestate(FILE *f)
7687c478bd9Sstevel@tonic-gate {
7697c478bd9Sstevel@tonic-gate 	char	*font;
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	font = current.font;
7727c478bd9Sstevel@tonic-gate 	(void) fseek(f, saved.offset, 0);
7737c478bd9Sstevel@tonic-gate 	current = saved;
7747c478bd9Sstevel@tonic-gate 	setcurrentfont(font, f);
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate void
7787c478bd9Sstevel@tonic-gate save_format_state(struct format_state *fs)
7797c478bd9Sstevel@tonic-gate {
7807c478bd9Sstevel@tonic-gate 	fs->numberwidth = numberwidth;
7817c478bd9Sstevel@tonic-gate 	fs->linenumber = linenumber;
7827c478bd9Sstevel@tonic-gate 	fs->altlinenumber = altlinenumber;
7837c478bd9Sstevel@tonic-gate 	fs->makegray = makegray;
7847c478bd9Sstevel@tonic-gate 	fs->font = current.font;
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate void
7887c478bd9Sstevel@tonic-gate restore_format_state(struct format_state *fs, FILE *outfile)
7897c478bd9Sstevel@tonic-gate {
7907c478bd9Sstevel@tonic-gate 	numberwidth = fs->numberwidth;
7917c478bd9Sstevel@tonic-gate 	linenumber = fs->linenumber;
7927c478bd9Sstevel@tonic-gate 	altlinenumber = fs->altlinenumber;
7937c478bd9Sstevel@tonic-gate 	makegray = fs->makegray;
7947c478bd9Sstevel@tonic-gate 	setcurrentfont(fs->font, outfile);
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate /*
7987c478bd9Sstevel@tonic-gate  * Print a file
7997c478bd9Sstevel@tonic-gate  *
8007c478bd9Sstevel@tonic-gate  * The input stream may be stdin, a file, or a pipe
8017c478bd9Sstevel@tonic-gate  */
8027c478bd9Sstevel@tonic-gate void
8037c478bd9Sstevel@tonic-gate printfile(FILE *infile)
8047c478bd9Sstevel@tonic-gate {
8057c478bd9Sstevel@tonic-gate 	int	eof;
8067c478bd9Sstevel@tonic-gate 	char	*p;
8077c478bd9Sstevel@tonic-gate 	FILE	*outfile;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	if (reverse)
8107c478bd9Sstevel@tonic-gate 		page_map[0] = 0L;
8117c478bd9Sstevel@tonic-gate 	if (usetmp) {
8127c478bd9Sstevel@tonic-gate 		(void) snprintf(bufin, BUFIN, "/tmp/%sXXXXXX", progname);
8137c478bd9Sstevel@tonic-gate 		p = mktemp(bufin);
8147c478bd9Sstevel@tonic-gate 		if ((outfile = fopen(p, "w+")) == NULL) {
8157c478bd9Sstevel@tonic-gate 			fatal("can't open temporary file %s", p);
8167c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
8177c478bd9Sstevel@tonic-gate 		}
8187c478bd9Sstevel@tonic-gate 		if (!dflag)
8197c478bd9Sstevel@tonic-gate 			(void) unlink(p);
8207c478bd9Sstevel@tonic-gate 		else
8217c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "will not unlink %s\n", p);
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 	else
8247c478bd9Sstevel@tonic-gate 		outfile = stdout;
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	setcurrentfont(DEFAULT_FONT, outfile);
8277c478bd9Sstevel@tonic-gate 	change_seen = 0;
8287c478bd9Sstevel@tonic-gate 	dots_inserted = 0;
8297c478bd9Sstevel@tonic-gate 	in_change = 0;
8307c478bd9Sstevel@tonic-gate 	makegray = 0;
8317c478bd9Sstevel@tonic-gate 	linenumber = 0;
8327c478bd9Sstevel@tonic-gate 	altlinenumber = 0;
8337c478bd9Sstevel@tonic-gate 	current.logical_page_count = 0;
8347c478bd9Sstevel@tonic-gate 	do {
8357c478bd9Sstevel@tonic-gate 		current.row = start_y;
8367c478bd9Sstevel@tonic-gate 		eof = printpage(infile, outfile);
8377c478bd9Sstevel@tonic-gate 	} while (!eof);
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	if (((int)current.row) != start_y)
8407c478bd9Sstevel@tonic-gate 		endpage(outfile);
8417c478bd9Sstevel@tonic-gate 	if ((current.logical_page_count % layoutp->pages) != 0)
8427c478bd9Sstevel@tonic-gate 		flushpage(outfile);
8437c478bd9Sstevel@tonic-gate 	if (vflag)
8447c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\n");
8457c478bd9Sstevel@tonic-gate 	if (fflush(outfile) == EOF) {
8467c478bd9Sstevel@tonic-gate 		fatal("write error while flushing output");
8477c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
8487c478bd9Sstevel@tonic-gate 	}
8497c478bd9Sstevel@tonic-gate 	if (usetmp) {
8507c478bd9Sstevel@tonic-gate 		if (reverse)
8517c478bd9Sstevel@tonic-gate 			reversepages(outfile);
8527c478bd9Sstevel@tonic-gate 		else
8537c478bd9Sstevel@tonic-gate 			copypage(outfile, 0L, current.offset);
8547c478bd9Sstevel@tonic-gate 		(void) fclose(outfile);
8557c478bd9Sstevel@tonic-gate 	}
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate void
8597c478bd9Sstevel@tonic-gate process_elide(FILE *outfile)
8607c478bd9Sstevel@tonic-gate {
8617c478bd9Sstevel@tonic-gate 	if (!change_seen && !in_change) {
8627c478bd9Sstevel@tonic-gate 		/* don't include function in output */
8637c478bd9Sstevel@tonic-gate 		restorestate(outfile);
8647c478bd9Sstevel@tonic-gate 		if (!dots_inserted) {
8657c478bd9Sstevel@tonic-gate 			struct format_state	format_state;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 			save_format_state(&format_state);
8687c478bd9Sstevel@tonic-gate 			numberwidth = 0;
8697c478bd9Sstevel@tonic-gate 			current.lineno++;
8707c478bd9Sstevel@tonic-gate 			current.row -= point_size;
8717c478bd9Sstevel@tonic-gate 			setcurrentfont(DEFAULT_FONT_BOLD_ITALIC,
8727c478bd9Sstevel@tonic-gate 				outfile);
8737c478bd9Sstevel@tonic-gate 			proc("______unchanged_portion_omitted_",
8747c478bd9Sstevel@tonic-gate 				outfile);
8757c478bd9Sstevel@tonic-gate 			restore_format_state(&format_state,
8767c478bd9Sstevel@tonic-gate 				outfile);
8777c478bd9Sstevel@tonic-gate 			savestate(outfile);
8787c478bd9Sstevel@tonic-gate 			dots_inserted = 1;
8797c478bd9Sstevel@tonic-gate 		}
8807c478bd9Sstevel@tonic-gate 	} else {
8817c478bd9Sstevel@tonic-gate 		savestate(outfile);
8827c478bd9Sstevel@tonic-gate 		change_seen = in_change;
8837c478bd9Sstevel@tonic-gate 		dots_inserted = 0;
8847c478bd9Sstevel@tonic-gate 	}
8857c478bd9Sstevel@tonic-gate }
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate /*
8887c478bd9Sstevel@tonic-gate  * Process the next page
8897c478bd9Sstevel@tonic-gate  * Return 1 on EOF, 0 otherwise
8907c478bd9Sstevel@tonic-gate  */
8917c478bd9Sstevel@tonic-gate int
8927c478bd9Sstevel@tonic-gate printpage(FILE *infile, FILE *outfile)
8937c478bd9Sstevel@tonic-gate {
8947c478bd9Sstevel@tonic-gate 	int	tmplinenumber;
8957c478bd9Sstevel@tonic-gate 	char	command[BUFSIZ], flag[BUFSIZ];
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	if (ungetc(getc(infile), infile) == EOF)
8987c478bd9Sstevel@tonic-gate 		return (1);
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	current.lineno = 0;
9017c478bd9Sstevel@tonic-gate 	current.lineno += startpage(outfile);
9027c478bd9Sstevel@tonic-gate 	if (bannerfile) {
9037c478bd9Sstevel@tonic-gate 		current.lineno += printbanner(bannerfile, outfile);
9047c478bd9Sstevel@tonic-gate 		bannerfile = NULL;
9057c478bd9Sstevel@tonic-gate 	}
9067c478bd9Sstevel@tonic-gate 	for (; current.lineno < lines_per_page; ) {
9077c478bd9Sstevel@tonic-gate 		if (fgetline(bufin, sizeof (bufin), infile) == (char *)NULL) {
9087c478bd9Sstevel@tonic-gate 			if (elide)
9097c478bd9Sstevel@tonic-gate 				process_elide(outfile);
9107c478bd9Sstevel@tonic-gate 			return (1);
9117c478bd9Sstevel@tonic-gate 		}
9127c478bd9Sstevel@tonic-gate 		/*
9137c478bd9Sstevel@tonic-gate 		 * Allow C comment delimiters around flag; only really applies
9147c478bd9Sstevel@tonic-gate 		 * to #else and #endif, but we don't expect to see C comments
9157c478bd9Sstevel@tonic-gate 		 * around flag for #if. Also accept flag with no C comment
9167c478bd9Sstevel@tonic-gate 		 * delimiters.
9177c478bd9Sstevel@tonic-gate 		 */
9187c478bd9Sstevel@tonic-gate 		if (iscodereview &&
9197c478bd9Sstevel@tonic-gate 		    (sscanf(bufin, "#%32s /* %80s */", command, flag) == 2 ||
9207c478bd9Sstevel@tonic-gate 		    sscanf(bufin, "#%32s %80s", command, flag) == 2) &&
9217c478bd9Sstevel@tonic-gate 		    strcmp(flag, CODEREVIEW) == 0) {
9227c478bd9Sstevel@tonic-gate 			if (strcmp(command, "ifdef") == 0) {
9237c478bd9Sstevel@tonic-gate 				change_seen = 1;
9247c478bd9Sstevel@tonic-gate 				in_change = 1;
9257c478bd9Sstevel@tonic-gate 				makegray = 1;
9267c478bd9Sstevel@tonic-gate 				old_stuff = 1;
9277c478bd9Sstevel@tonic-gate 				tmplinenumber = linenumber;
9287c478bd9Sstevel@tonic-gate 				linenumber = altlinenumber;
9297c478bd9Sstevel@tonic-gate 				altlinenumber = tmplinenumber;
9307c478bd9Sstevel@tonic-gate 				setcurrentfont(DEFAULT_FONT_ITALIC, outfile);
9317c478bd9Sstevel@tonic-gate 			} else if (strcmp(command, "ifndef") == 0) {
9327c478bd9Sstevel@tonic-gate 				change_seen = 1;
9337c478bd9Sstevel@tonic-gate 				in_change = 1;
9347c478bd9Sstevel@tonic-gate 				makegray = 1;
9357c478bd9Sstevel@tonic-gate 				old_stuff = 0;
9367c478bd9Sstevel@tonic-gate 				setcurrentfont(DEFAULT_FONT_BOLD, outfile);
9377c478bd9Sstevel@tonic-gate 			} else if (strcmp(command, "else") == 0) {
9387c478bd9Sstevel@tonic-gate 				makegray = 1;
9397c478bd9Sstevel@tonic-gate 				old_stuff = !old_stuff;
9407c478bd9Sstevel@tonic-gate 				tmplinenumber = linenumber;
9417c478bd9Sstevel@tonic-gate 				linenumber = altlinenumber;
9427c478bd9Sstevel@tonic-gate 				altlinenumber = tmplinenumber;
9437c478bd9Sstevel@tonic-gate 				if (!old_stuff)
9447c478bd9Sstevel@tonic-gate 					setcurrentfont(DEFAULT_FONT_BOLD,
9457c478bd9Sstevel@tonic-gate 							outfile);
9467c478bd9Sstevel@tonic-gate 				else
9477c478bd9Sstevel@tonic-gate 					setcurrentfont(DEFAULT_FONT_ITALIC,
9487c478bd9Sstevel@tonic-gate 							outfile);
9497c478bd9Sstevel@tonic-gate 			} else /* if (strcmp(command, "endif") == 0) */ {
9507c478bd9Sstevel@tonic-gate 				in_change = 0;
9517c478bd9Sstevel@tonic-gate 				makegray = 0;
9527c478bd9Sstevel@tonic-gate 				savestate(outfile);
9537c478bd9Sstevel@tonic-gate 				setcurrentfont(DEFAULT_FONT, outfile);
9547c478bd9Sstevel@tonic-gate 				if (old_stuff) {
9557c478bd9Sstevel@tonic-gate 					tmplinenumber = linenumber;
9567c478bd9Sstevel@tonic-gate 					linenumber = altlinenumber;
9577c478bd9Sstevel@tonic-gate 					altlinenumber = tmplinenumber;
9587c478bd9Sstevel@tonic-gate 				}
9597c478bd9Sstevel@tonic-gate 			}
9607c478bd9Sstevel@tonic-gate 			continue;
9617c478bd9Sstevel@tonic-gate 		}
9627c478bd9Sstevel@tonic-gate 		current.lineno++;
9637c478bd9Sstevel@tonic-gate 		current.row -= point_size;
9647c478bd9Sstevel@tonic-gate 		if (bufin[0] == '\f')
9657c478bd9Sstevel@tonic-gate 			break;
9667c478bd9Sstevel@tonic-gate 		proc(bufin, outfile);
9677c478bd9Sstevel@tonic-gate 		if (elide && (bufin[0] == END_C_FUNCTION ||
9687c478bd9Sstevel@tonic-gate 		    (strstr(bufin, END_ASM_FUNCTION) != NULL)))
9697c478bd9Sstevel@tonic-gate 			process_elide(outfile);
9707c478bd9Sstevel@tonic-gate 	}
9717c478bd9Sstevel@tonic-gate 	endpage(outfile);
9727c478bd9Sstevel@tonic-gate 	return (0);
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate /*
9767c478bd9Sstevel@tonic-gate  * Start a new page
9777c478bd9Sstevel@tonic-gate  */
9787c478bd9Sstevel@tonic-gate int
9797c478bd9Sstevel@tonic-gate startpage(FILE *outfile)
9807c478bd9Sstevel@tonic-gate {
9817c478bd9Sstevel@tonic-gate 	int	logical_page, lines, buflen;
9827c478bd9Sstevel@tonic-gate 	struct format_state	format_state;
9837c478bd9Sstevel@tonic-gate 	char	buf[8];
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	logical_page = current.logical_page_count % layoutp->pages;
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	if (logical_page == 0)
9887c478bd9Sstevel@tonic-gate 		setuppage(outfile);
9897c478bd9Sstevel@tonic-gate 	else
9907c478bd9Sstevel@tonic-gate 		setcurrentfont((char *)NULL, outfile);
9917c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%s ", SET_WIDTHS);
9927c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %f %d %d %s\n",
9937c478bd9Sstevel@tonic-gate 			rot_text, layoutp->scale,
9947c478bd9Sstevel@tonic-gate 			positions[logical_page].base_x,
9957c478bd9Sstevel@tonic-gate 			positions[logical_page].base_y,
9967c478bd9Sstevel@tonic-gate 			START_PAGE);
9977c478bd9Sstevel@tonic-gate 	lines = 0;
9987c478bd9Sstevel@tonic-gate 	if (header) {
9997c478bd9Sstevel@tonic-gate 		save_format_state(&format_state);
10007c478bd9Sstevel@tonic-gate 		setcurrentfont(DEFAULT_FONT_BOLD, outfile);
10017c478bd9Sstevel@tonic-gate 		numberwidth = 0;
10027c478bd9Sstevel@tonic-gate 		makegray = 0;
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 		current.row -= point_size;
10057c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s\n", start_x, current.row,
10067c478bd9Sstevel@tonic-gate 				MOVETO);
10077c478bd9Sstevel@tonic-gate 		proc(headerstring, outfile);
10087c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, 8, "%d", current.logical_page_count + 1);
10097c478bd9Sstevel@tonic-gate 		buflen = strlen(buf);
10107c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s (%s)%s\n",
10117c478bd9Sstevel@tonic-gate 				(int)(end_x - (buflen + 0.5) *
10127c478bd9Sstevel@tonic-gate 				    DEFAULT_CHAR_WIDTH * point_size),
10137c478bd9Sstevel@tonic-gate 				current.row, MOVETO, buf, SHOW);
10147c478bd9Sstevel@tonic-gate 		current.row -= point_size;
10157c478bd9Sstevel@tonic-gate 		restore_format_state(&format_state, outfile);
10167c478bd9Sstevel@tonic-gate 		lines = 2;
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate 	return (lines);
10197c478bd9Sstevel@tonic-gate }
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate void
10227c478bd9Sstevel@tonic-gate setheaderfile(char *filename)
10237c478bd9Sstevel@tonic-gate {
10247c478bd9Sstevel@tonic-gate 	if (header == HEADER_IMPLICIT)
10257c478bd9Sstevel@tonic-gate 		headerstring = filename;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate /*
10297c478bd9Sstevel@tonic-gate  * Setup page
10307c478bd9Sstevel@tonic-gate  */
10317c478bd9Sstevel@tonic-gate void
10327c478bd9Sstevel@tonic-gate setuppage(FILE *outfile)
10337c478bd9Sstevel@tonic-gate {
10347c478bd9Sstevel@tonic-gate 	int	i, ilimit;
10357c478bd9Sstevel@tonic-gate 	int	begin, end, place;
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%%%%Page: ? %d\n", current.page_count + 1);
10387c478bd9Sstevel@tonic-gate 	setcurrentfont((char *)NULL, outfile);
10397c478bd9Sstevel@tonic-gate 	if (layoutp->pages == 1)
10407c478bd9Sstevel@tonic-gate 		return;
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%f %s %s\n",
10437c478bd9Sstevel@tonic-gate 			RULE_WIDTH, SETLINEWIDTH, NEWPATH);
10447c478bd9Sstevel@tonic-gate 	begin = 0; end = DEFAULT_PAPER_WIDTH * POINTS_PER_INCH;
10457c478bd9Sstevel@tonic-gate 	for (i = 1, ilimit = layoutp->page_rows; i < ilimit; i++) {
10467c478bd9Sstevel@tonic-gate 		place = margin_y - gap_height/2 + i * (box_height+gap_height);
10477c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s ", begin, place, MOVETO);
10487c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s\n", end, place, LINETO);
10497c478bd9Sstevel@tonic-gate 	}
10507c478bd9Sstevel@tonic-gate 	begin = 0; end = DEFAULT_PAPER_HEIGHT * POINTS_PER_INCH;
10517c478bd9Sstevel@tonic-gate 	for (i = 1, ilimit = layoutp->page_cols; i < ilimit; i++) {
10527c478bd9Sstevel@tonic-gate 		place = margin_x - gap_width/2 + i * (box_width+gap_width);
10537c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s ", place, begin, MOVETO);
10547c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %d %s\n", place, end, LINETO);
10557c478bd9Sstevel@tonic-gate 	}
10567c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%s\n", STROKE);
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate /*
10607c478bd9Sstevel@tonic-gate  * Terminate the logical page and indicate the start of the next
10617c478bd9Sstevel@tonic-gate  */
10627c478bd9Sstevel@tonic-gate void
10637c478bd9Sstevel@tonic-gate endpage(FILE *outfile)
10647c478bd9Sstevel@tonic-gate {
10657c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%s\n", END_PAGE);
10667c478bd9Sstevel@tonic-gate 	current.logical_page_count++;
10677c478bd9Sstevel@tonic-gate 	if (vflag)
10687c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "x");
10697c478bd9Sstevel@tonic-gate 	if ((current.logical_page_count % layoutp->pages) == 0)
10707c478bd9Sstevel@tonic-gate 		flushpage(outfile);
10717c478bd9Sstevel@tonic-gate }
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate /*
10747c478bd9Sstevel@tonic-gate  * Flush the physical page
10757c478bd9Sstevel@tonic-gate  * Record the start of the next page
10767c478bd9Sstevel@tonic-gate  */
10777c478bd9Sstevel@tonic-gate void
10787c478bd9Sstevel@tonic-gate flushpage(FILE *outfile)
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate 	(void) fprintf(outfile, "%d %s\n", ncopies, FLUSH_PAGE);
10817c478bd9Sstevel@tonic-gate 	current.page_count++;
10827c478bd9Sstevel@tonic-gate 	current.offset = ftell(outfile);
10837c478bd9Sstevel@tonic-gate 	if (reverse) {
10847c478bd9Sstevel@tonic-gate 		if (current.page_count >= MAXPAGES) {
10857c478bd9Sstevel@tonic-gate 			fatal("page reversal limit (%d) reached", MAXPAGES);
10867c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
10877c478bd9Sstevel@tonic-gate 		}
10887c478bd9Sstevel@tonic-gate 		page_map[current.page_count] = current.offset;
10897c478bd9Sstevel@tonic-gate 	}
10907c478bd9Sstevel@tonic-gate 	if (vflag)
10917c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "|");
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate /*
10957c478bd9Sstevel@tonic-gate  * reverse the order of pages
10967c478bd9Sstevel@tonic-gate  */
10977c478bd9Sstevel@tonic-gate void
10987c478bd9Sstevel@tonic-gate reversepages(FILE *outfile)
10997c478bd9Sstevel@tonic-gate {
11007c478bd9Sstevel@tonic-gate 	int	i;
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	if (vflag)
11037c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\nreversing %d page%s\n",
11047c478bd9Sstevel@tonic-gate 				current.page_count,
11057c478bd9Sstevel@tonic-gate 				current.page_count > 1 ? "s" : "");
11067c478bd9Sstevel@tonic-gate 	for (i = current.page_count - 1; i >= 0; i--) {
11077c478bd9Sstevel@tonic-gate 		copypage(outfile, page_map[i], page_map[i+1]);
11087c478bd9Sstevel@tonic-gate 	}
11097c478bd9Sstevel@tonic-gate }
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate /*
11127c478bd9Sstevel@tonic-gate  * copy a page (or more) from tempfile to stdout
11137c478bd9Sstevel@tonic-gate  */
11147c478bd9Sstevel@tonic-gate void
11157c478bd9Sstevel@tonic-gate copypage(FILE *outfile, long off_beg, long off_end)
11167c478bd9Sstevel@tonic-gate {
11177c478bd9Sstevel@tonic-gate 	int	bytecount, nbytes;
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	if (fseek(outfile, off_beg, 0) == -1L) {
11207c478bd9Sstevel@tonic-gate 		fatal("temporary file seek error");
11217c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate 	nbytes = off_end - off_beg;
11247c478bd9Sstevel@tonic-gate 	while (nbytes > 0) {
11257c478bd9Sstevel@tonic-gate 		bytecount = nbytes;
11267c478bd9Sstevel@tonic-gate 		if (bytecount > sizeof (bufout))
11277c478bd9Sstevel@tonic-gate 			bytecount = sizeof (bufout);
11287c478bd9Sstevel@tonic-gate 		bytecount = fread(bufout, 1, bytecount, outfile);
11297c478bd9Sstevel@tonic-gate 		if (bytecount <= 0) {
11307c478bd9Sstevel@tonic-gate 			fatal("temporary file read error");
11317c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
11327c478bd9Sstevel@tonic-gate 		}
11337c478bd9Sstevel@tonic-gate 		if (fwrite(bufout, 1, bytecount, stdout) != bytecount) {
11347c478bd9Sstevel@tonic-gate 			fatal("write error during page copy");
11357c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
11367c478bd9Sstevel@tonic-gate 		}
11377c478bd9Sstevel@tonic-gate 		nbytes -= bytecount;
11387c478bd9Sstevel@tonic-gate 	}
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate /*
11427c478bd9Sstevel@tonic-gate  * Process a line of input, escaping characters when necessary and handling
11437c478bd9Sstevel@tonic-gate  * tabs
11447c478bd9Sstevel@tonic-gate  *
11457c478bd9Sstevel@tonic-gate  * The output is improved somewhat by coalescing consecutive tabs and
11467c478bd9Sstevel@tonic-gate  * backspaces and eliminating tabs at the end of a line
11477c478bd9Sstevel@tonic-gate  *
11487c478bd9Sstevel@tonic-gate  * Overprinting (presumably most often used in underlining) can be far from
11497c478bd9Sstevel@tonic-gate  * optimal; in particular the way nroff underlines by sequences like
11507c478bd9Sstevel@tonic-gate  * "_\ba_\bb_\bc" creates a large volume of PostScript.  This isn't too
11517c478bd9Sstevel@tonic-gate  * serious since a lot of nroff underlining is unlikely.
11527c478bd9Sstevel@tonic-gate  *
11537c478bd9Sstevel@tonic-gate  * Since a newline is generated for each call there will be more
11547c478bd9Sstevel@tonic-gate  * newlines in the output than is necessary
11557c478bd9Sstevel@tonic-gate  */
11567c478bd9Sstevel@tonic-gate void
11577c478bd9Sstevel@tonic-gate proc(char *in, FILE *outfile)
11587c478bd9Sstevel@tonic-gate {
11597c478bd9Sstevel@tonic-gate 	int	i;
11607c478bd9Sstevel@tonic-gate 	char	*last, *p, *q;
11617c478bd9Sstevel@tonic-gate 	int	currentp, instr, tabc, tabto, grayed;
11627c478bd9Sstevel@tonic-gate 	char	*altfont;
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	currentp = 0;
11657c478bd9Sstevel@tonic-gate 	instr = 0;
11667c478bd9Sstevel@tonic-gate 	tabto = 0;
11677c478bd9Sstevel@tonic-gate 	if (iscodereview) {
11687c478bd9Sstevel@tonic-gate 		grayed = makegray;
11697c478bd9Sstevel@tonic-gate 		altfont = current.font;
11707c478bd9Sstevel@tonic-gate 	} else {
11717c478bd9Sstevel@tonic-gate 		grayed = 0;
11727c478bd9Sstevel@tonic-gate 		altfont = DEFAULT_FONT;
11737c478bd9Sstevel@tonic-gate 	}
11747c478bd9Sstevel@tonic-gate 	/* subtract slop factor */
11757c478bd9Sstevel@tonic-gate 	last = bufout + MAX_OUTPUT_LINE_LENGTH - 20;
11767c478bd9Sstevel@tonic-gate 	for (;;) { /* check for any special line treatment */
11777c478bd9Sstevel@tonic-gate 		if (graylength && strncmp(in, graystring, graylength) == 0) {
11787c478bd9Sstevel@tonic-gate 			grayed++;
11797c478bd9Sstevel@tonic-gate 			in += graylength;
11807c478bd9Sstevel@tonic-gate 		} else if (boldlength &&
11817c478bd9Sstevel@tonic-gate 				strncmp(in, boldstring, boldlength) == 0) {
11827c478bd9Sstevel@tonic-gate 			altfont = DEFAULT_FONT_BOLD;
11837c478bd9Sstevel@tonic-gate 			in += boldlength;
11847c478bd9Sstevel@tonic-gate 		} else if (itlclength &&
11857c478bd9Sstevel@tonic-gate 				strncmp(in, itlcstring, itlclength) == 0) {
11867c478bd9Sstevel@tonic-gate 			altfont = DEFAULT_FONT_ITALIC;
11877c478bd9Sstevel@tonic-gate 			in += itlclength;
11887c478bd9Sstevel@tonic-gate 		} else if (bitclength &&
11897c478bd9Sstevel@tonic-gate 				strncmp(in, bitcstring, bitclength) == 0) {
11907c478bd9Sstevel@tonic-gate 			altfont = DEFAULT_FONT_BOLD_ITALIC;
11917c478bd9Sstevel@tonic-gate 			in += bitclength;
11927c478bd9Sstevel@tonic-gate 		} else
11937c478bd9Sstevel@tonic-gate 			break;
11947c478bd9Sstevel@tonic-gate 	}
11957c478bd9Sstevel@tonic-gate 	if (grayed) {
11967c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %d %.2f %s\n",
11977c478bd9Sstevel@tonic-gate 			start_x, current.row -
11987c478bd9Sstevel@tonic-gate 				DEFAULT_DESCENDER_FRACTION * point_size,
11997c478bd9Sstevel@tonic-gate 			end_x, current.row +
12007c478bd9Sstevel@tonic-gate 				(1.0 - DEFAULT_DESCENDER_FRACTION) * point_size,
12017c478bd9Sstevel@tonic-gate 			SHADE);
12027c478bd9Sstevel@tonic-gate 	}
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	linenumber++;
12057c478bd9Sstevel@tonic-gate 	if (!in_change)
12067c478bd9Sstevel@tonic-gate 		altlinenumber++;
12077c478bd9Sstevel@tonic-gate 	if (*in == '\0')
12087c478bd9Sstevel@tonic-gate 		return;
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	if (start_x != 0) {
12117c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %.2f %s\n",
12127c478bd9Sstevel@tonic-gate 				start_x, current.row, MOVETO);
12137c478bd9Sstevel@tonic-gate 	}
12147c478bd9Sstevel@tonic-gate 	else
12157c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%.2f %s\n",
12167c478bd9Sstevel@tonic-gate 				current.row, ZEROMOVETO);
12177c478bd9Sstevel@tonic-gate 	if (numberwidth) {
12187c478bd9Sstevel@tonic-gate 		setcurrentfont(DEFAULT_FONT, outfile);
12197c478bd9Sstevel@tonic-gate 		(void) sprintf(bufout, "%*d", numberwidth, linenumber);
12207c478bd9Sstevel@tonic-gate 		for (q = bufout, i = 0; *q == ' '; q++, i++)
12217c478bd9Sstevel@tonic-gate 			;
12227c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%d %s (%s)%s %d %s ",
12237c478bd9Sstevel@tonic-gate 			i, TAB, q, SHOW, DEFAULT_SPACES_AFTER_NUMBER, TAB);
12247c478bd9Sstevel@tonic-gate 	}
12257c478bd9Sstevel@tonic-gate 	setcurrentfont(altfont, outfile);
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 	q = bufout;
12287c478bd9Sstevel@tonic-gate 	*q = '\0';
12297c478bd9Sstevel@tonic-gate 	for (p = in; *p != '\0'; p++) {
12307c478bd9Sstevel@tonic-gate 		switch (*p) {
12317c478bd9Sstevel@tonic-gate 		case '\t':
12327c478bd9Sstevel@tonic-gate 			/*
12337c478bd9Sstevel@tonic-gate 			 * Count the number of tabs that immediately follow
12347c478bd9Sstevel@tonic-gate 			 * the one we're looking at
12357c478bd9Sstevel@tonic-gate 			 */
12367c478bd9Sstevel@tonic-gate 			tabc = 0;
12377c478bd9Sstevel@tonic-gate 			while (*(p + 1) == '\t') {
12387c478bd9Sstevel@tonic-gate 				p++;
12397c478bd9Sstevel@tonic-gate 				tabc++;
12407c478bd9Sstevel@tonic-gate 			}
12417c478bd9Sstevel@tonic-gate 			if (currentp > 0) {	/* not beginning of line */
12427c478bd9Sstevel@tonic-gate 				i = tabstop - (currentp % tabstop) +
12437c478bd9Sstevel@tonic-gate 						tabc * tabstop;
12447c478bd9Sstevel@tonic-gate 				if (instr) {
12457c478bd9Sstevel@tonic-gate 					(void) snprintf(q,
12467c478bd9Sstevel@tonic-gate 					    BUFOUT - (q - bufout), ")%s ",
12477c478bd9Sstevel@tonic-gate 					    SHOW);
12487c478bd9Sstevel@tonic-gate 					q += strlen(q);
12497c478bd9Sstevel@tonic-gate 					instr = 0;
12507c478bd9Sstevel@tonic-gate 				}
12517c478bd9Sstevel@tonic-gate 			}
12527c478bd9Sstevel@tonic-gate 			else
12537c478bd9Sstevel@tonic-gate 				i = (tabc + 1) * tabstop;
12547c478bd9Sstevel@tonic-gate 			tabto += i;
12557c478bd9Sstevel@tonic-gate 			currentp += i;
12567c478bd9Sstevel@tonic-gate 			break;
12577c478bd9Sstevel@tonic-gate 		case '\b':
12587c478bd9Sstevel@tonic-gate 			/* backspacing over tabs doesn't work... */
12597c478bd9Sstevel@tonic-gate 			if (tabto != 0) {
12607c478bd9Sstevel@tonic-gate 				fatal("attempt to backspace over a tab");
12617c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
12627c478bd9Sstevel@tonic-gate 			}
12637c478bd9Sstevel@tonic-gate 			p++;
12647c478bd9Sstevel@tonic-gate 			for (i = 1; *p == '\b'; p++)
12657c478bd9Sstevel@tonic-gate 				i++;
12667c478bd9Sstevel@tonic-gate 			p--;
12677c478bd9Sstevel@tonic-gate 			if (currentp - i < 0) {
12687c478bd9Sstevel@tonic-gate 				fatal("too many backspaces");
12697c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
12707c478bd9Sstevel@tonic-gate 			}
12717c478bd9Sstevel@tonic-gate 			if (instr) {
12727c478bd9Sstevel@tonic-gate 				*q = '\0';
12737c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n",
12747c478bd9Sstevel@tonic-gate 						bufout, SHOW);
12757c478bd9Sstevel@tonic-gate 			}
12767c478bd9Sstevel@tonic-gate 			instr = 0;
12777c478bd9Sstevel@tonic-gate 			if (currentp >= columns)
12787c478bd9Sstevel@tonic-gate 				i -= currentp-columns;
12797c478bd9Sstevel@tonic-gate 			if (i <= 0) {
12807c478bd9Sstevel@tonic-gate 				/* backspace in truncated line */
12817c478bd9Sstevel@tonic-gate 				bufout[0] = '\0';
12827c478bd9Sstevel@tonic-gate 			} else if (i == 1) {
12837c478bd9Sstevel@tonic-gate 				/* frequent case gets special attention */
12847c478bd9Sstevel@tonic-gate 				(void) snprintf(bufout, BUFOUT, "%s ",
12857c478bd9Sstevel@tonic-gate 				    BACKSPACE);
12867c478bd9Sstevel@tonic-gate 			} else
12877c478bd9Sstevel@tonic-gate 				(void) snprintf(bufout, BUFOUT, "-%d %s ", i,
12887c478bd9Sstevel@tonic-gate 				    TAB);
12897c478bd9Sstevel@tonic-gate 			q = bufout + strlen(bufout);
12907c478bd9Sstevel@tonic-gate 			currentp -= i;
12917c478bd9Sstevel@tonic-gate 			break;
12927c478bd9Sstevel@tonic-gate 		case '\f':
12937c478bd9Sstevel@tonic-gate 			tabto = 0;		/* optimizes */
12947c478bd9Sstevel@tonic-gate 			*q = '\0';
12957c478bd9Sstevel@tonic-gate 			if (instr)
12967c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n",
12977c478bd9Sstevel@tonic-gate 						bufout, SHOW);
12987c478bd9Sstevel@tonic-gate 			else
12997c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s\n", bufout);
13007c478bd9Sstevel@tonic-gate 			endpage(outfile);
13017c478bd9Sstevel@tonic-gate 			(void) startpage(outfile);
13027c478bd9Sstevel@tonic-gate 			current.row = start_y;
13037c478bd9Sstevel@tonic-gate 			(void) fprintf(outfile, "%d %.2f %s\n",
13047c478bd9Sstevel@tonic-gate 					start_x, current.row, MOVETO);
13057c478bd9Sstevel@tonic-gate 			if (numberwidth)
13067c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%d %s\n", numberwidth +
13077c478bd9Sstevel@tonic-gate 					DEFAULT_SPACES_AFTER_NUMBER, TAB);
13087c478bd9Sstevel@tonic-gate 			q = bufout;
13097c478bd9Sstevel@tonic-gate 			currentp = 0;
13107c478bd9Sstevel@tonic-gate 			instr = 0;
13117c478bd9Sstevel@tonic-gate 			break;
13127c478bd9Sstevel@tonic-gate 		case '\r':
13137c478bd9Sstevel@tonic-gate 			tabto = 0;		/* optimizes */
13147c478bd9Sstevel@tonic-gate 			if (instr) {
13157c478bd9Sstevel@tonic-gate 				*q = '\0';
13167c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n",
13177c478bd9Sstevel@tonic-gate 						bufout, SHOW);
13187c478bd9Sstevel@tonic-gate 				instr = 0;
13197c478bd9Sstevel@tonic-gate 				q = bufout;
13207c478bd9Sstevel@tonic-gate 			}
13217c478bd9Sstevel@tonic-gate 			(void) fprintf(outfile, "%d %.2f %s\n",
13227c478bd9Sstevel@tonic-gate 					start_x, current.row, MOVETO);
13237c478bd9Sstevel@tonic-gate 			if (numberwidth)
13247c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%d %s\n", numberwidth +
13257c478bd9Sstevel@tonic-gate 					DEFAULT_SPACES_AFTER_NUMBER, TAB);
13267c478bd9Sstevel@tonic-gate 			currentp = 0;
13277c478bd9Sstevel@tonic-gate 			break;
13287c478bd9Sstevel@tonic-gate 		case '\\':
13297c478bd9Sstevel@tonic-gate 		case '(':
13307c478bd9Sstevel@tonic-gate 		case ')':
13317c478bd9Sstevel@tonic-gate 			if (currentp < columns) {
13327c478bd9Sstevel@tonic-gate 				if (!instr) {
13337c478bd9Sstevel@tonic-gate 					if (tabto) {
13347c478bd9Sstevel@tonic-gate 						(void) snprintf(q,
13357c478bd9Sstevel@tonic-gate 						    BUFOUT - (q - bufout),
13367c478bd9Sstevel@tonic-gate 						    "%d %s ", tabto, TAB);
13377c478bd9Sstevel@tonic-gate 						q += strlen(q);
13387c478bd9Sstevel@tonic-gate 						tabto = 0;
13397c478bd9Sstevel@tonic-gate 					}
13407c478bd9Sstevel@tonic-gate 					*q++ = '(';
13417c478bd9Sstevel@tonic-gate 					instr = 1;
13427c478bd9Sstevel@tonic-gate 				}
13437c478bd9Sstevel@tonic-gate 				*q++ = '\\';
13447c478bd9Sstevel@tonic-gate 				*q++ = *p;
13457c478bd9Sstevel@tonic-gate 			}
13467c478bd9Sstevel@tonic-gate 			currentp++;
13477c478bd9Sstevel@tonic-gate 			break;
13487c478bd9Sstevel@tonic-gate 		default: {
13497c478bd9Sstevel@tonic-gate 			/*
13507c478bd9Sstevel@tonic-gate 			 * According to the PostScript Language Manual,
13517c478bd9Sstevel@tonic-gate 			 * PostScript files can contain only "the printable
13527c478bd9Sstevel@tonic-gate 			 * subset of the ASCII character set (plus the
13537c478bd9Sstevel@tonic-gate 			 * newline marker)".
13547c478bd9Sstevel@tonic-gate 			 */
13557c478bd9Sstevel@tonic-gate 			char	pchar;
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 			pchar = *p;
13587c478bd9Sstevel@tonic-gate 			if (currentp < columns) {
13597c478bd9Sstevel@tonic-gate 				if (!instr) {
13607c478bd9Sstevel@tonic-gate 					if (tabto) {
13617c478bd9Sstevel@tonic-gate 						(void) snprintf(q,
13627c478bd9Sstevel@tonic-gate 						    BUFOUT - (q - bufout),
13637c478bd9Sstevel@tonic-gate 						    "%d %s ", tabto, TAB);
13647c478bd9Sstevel@tonic-gate 						q += strlen(q);
13657c478bd9Sstevel@tonic-gate 						tabto = 0;
13667c478bd9Sstevel@tonic-gate 					}
13677c478bd9Sstevel@tonic-gate 					*q++ = '(';
13687c478bd9Sstevel@tonic-gate 					instr = 1;
13697c478bd9Sstevel@tonic-gate 				}
13707c478bd9Sstevel@tonic-gate 				if (!isascii(pchar) || !isprint(pchar)) {
13717c478bd9Sstevel@tonic-gate 					if (iscntrl(pchar)) {
13727c478bd9Sstevel@tonic-gate 						if (pchar == '\177')
13737c478bd9Sstevel@tonic-gate 							pchar = '_';
13747c478bd9Sstevel@tonic-gate 						else
13757c478bd9Sstevel@tonic-gate 							pchar += '@';
13767c478bd9Sstevel@tonic-gate 						*q++ = '^';
13777c478bd9Sstevel@tonic-gate 					} else {
13787c478bd9Sstevel@tonic-gate 						*q++ = '\\';
13797c478bd9Sstevel@tonic-gate 						*q++ = '0' + ((pchar>>6) & 7);
13807c478bd9Sstevel@tonic-gate 						*q++ = '0' + ((pchar>>3) & 7);
13817c478bd9Sstevel@tonic-gate 						pchar = '0' + (pchar & 7);
13827c478bd9Sstevel@tonic-gate 					}
13837c478bd9Sstevel@tonic-gate 				}
13847c478bd9Sstevel@tonic-gate 				*q++ = pchar;
13857c478bd9Sstevel@tonic-gate 			}
13867c478bd9Sstevel@tonic-gate 			currentp++;
13877c478bd9Sstevel@tonic-gate 			break;
13887c478bd9Sstevel@tonic-gate 			}
13897c478bd9Sstevel@tonic-gate 		}
13907c478bd9Sstevel@tonic-gate 		if (q >= last) {
13917c478bd9Sstevel@tonic-gate 			*q = '\0';
13927c478bd9Sstevel@tonic-gate 			if (instr)
13937c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s)%s\n", bufout,
13947c478bd9Sstevel@tonic-gate 				    SHOW);
13957c478bd9Sstevel@tonic-gate 			else
13967c478bd9Sstevel@tonic-gate 				(void) fprintf(outfile, "%s\n", bufout);
13977c478bd9Sstevel@tonic-gate 			q = bufout;
13987c478bd9Sstevel@tonic-gate 			instr = 0;
13997c478bd9Sstevel@tonic-gate 		}
14007c478bd9Sstevel@tonic-gate 	}
14017c478bd9Sstevel@tonic-gate 	if (instr) {
14027c478bd9Sstevel@tonic-gate 		(void) snprintf(q, BUFOUT - (q - bufout), ")%s", SHOW);
14037c478bd9Sstevel@tonic-gate 		q += strlen(q);
14047c478bd9Sstevel@tonic-gate 	}
14057c478bd9Sstevel@tonic-gate 	else
14067c478bd9Sstevel@tonic-gate 		*q = '\0';
14077c478bd9Sstevel@tonic-gate 	if (q >= last) {
14087c478bd9Sstevel@tonic-gate 		fatal("bufout overflow");
14097c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
14107c478bd9Sstevel@tonic-gate 	}
14117c478bd9Sstevel@tonic-gate 	if (bufout[0] != '\0')
14127c478bd9Sstevel@tonic-gate 		(void) fprintf(outfile, "%s\n", bufout);
14137c478bd9Sstevel@tonic-gate }
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate /*
14167c478bd9Sstevel@tonic-gate  * Initialize globals:
14177c478bd9Sstevel@tonic-gate  *	username - login name of user
14187c478bd9Sstevel@tonic-gate  *	hostname - name of machine on which lwlp is run
14197c478bd9Sstevel@tonic-gate  *	currentdate - what it says
14207c478bd9Sstevel@tonic-gate  * Possible system dependencies here...
14217c478bd9Sstevel@tonic-gate  */
14227c478bd9Sstevel@tonic-gate void
14237c478bd9Sstevel@tonic-gate setup(void)
14247c478bd9Sstevel@tonic-gate {
14257c478bd9Sstevel@tonic-gate 	int	len;
14267c478bd9Sstevel@tonic-gate 	char	*p;
14277c478bd9Sstevel@tonic-gate 	long	t;
14287c478bd9Sstevel@tonic-gate 	struct utsname	utsname;
14297c478bd9Sstevel@tonic-gate 	struct passwd	*pw;
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate 	if ((p = getlogin()) == (char *)NULL) {
14327c478bd9Sstevel@tonic-gate 		if ((pw = getpwuid(getuid())) == (struct passwd *)NULL)
14337c478bd9Sstevel@tonic-gate 			p = "Whoknows";
14347c478bd9Sstevel@tonic-gate 		else
14357c478bd9Sstevel@tonic-gate 			p = pw->pw_name;
14367c478bd9Sstevel@tonic-gate 		endpwent();
14377c478bd9Sstevel@tonic-gate 	}
14387c478bd9Sstevel@tonic-gate 	username = strdup(p);
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 	(void) uname(&utsname);
14417c478bd9Sstevel@tonic-gate 	hostname = strdup(utsname.nodename);
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	t = time((long *)0);
14447c478bd9Sstevel@tonic-gate 	p = ctime(&t);
14457c478bd9Sstevel@tonic-gate 	len = strlen(p);
14467c478bd9Sstevel@tonic-gate 	*(p + len - 1) = '\0';		/* zap the newline character */
14477c478bd9Sstevel@tonic-gate 	currentdate = strdup(p);
14487c478bd9Sstevel@tonic-gate 	current.font = DEFAULT_FONT;
14497c478bd9Sstevel@tonic-gate }
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate /*
14527c478bd9Sstevel@tonic-gate  * Special version of fgets
14537c478bd9Sstevel@tonic-gate  * Read until a formfeed, newline, or overflow
14547c478bd9Sstevel@tonic-gate  * If a formfeed is the first character, return it immediately
14557c478bd9Sstevel@tonic-gate  * If a formfeed is found after the first character, replace it by a newline
14567c478bd9Sstevel@tonic-gate  * and push the formfeed back onto the input stream
14577c478bd9Sstevel@tonic-gate  * A special case is a formfeed followed by a newline in which case the
14587c478bd9Sstevel@tonic-gate  * newline is ignored
14597c478bd9Sstevel@tonic-gate  * The input buffer will be null-terminated and will *not* end with a newline
14607c478bd9Sstevel@tonic-gate  * The buffer size n includes the null
14617c478bd9Sstevel@tonic-gate  */
14627c478bd9Sstevel@tonic-gate char *
14637c478bd9Sstevel@tonic-gate fgetline(char *s, int n, FILE *iop)
14647c478bd9Sstevel@tonic-gate {
14657c478bd9Sstevel@tonic-gate 	int	ch;
14667c478bd9Sstevel@tonic-gate 	char	*cs;
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 	if (n < 2) {
14697c478bd9Sstevel@tonic-gate 		fatal("fgetline called with bad buffer size!?");
14707c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
14717c478bd9Sstevel@tonic-gate 	}
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	cs = s;
14747c478bd9Sstevel@tonic-gate 	n--;				/* the null */
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 	/*
14777c478bd9Sstevel@tonic-gate 	 * Check out the special cases
14787c478bd9Sstevel@tonic-gate 	 */
14797c478bd9Sstevel@tonic-gate 	if ((ch = getc(iop)) == EOF)
14807c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
14817c478bd9Sstevel@tonic-gate 	if (ch == '\f') {
14827c478bd9Sstevel@tonic-gate 		if ((ch = getc(iop)) != '\n') {
14837c478bd9Sstevel@tonic-gate 			/*
14847c478bd9Sstevel@tonic-gate 			 * If EOF was just read it will be noticed
14857c478bd9Sstevel@tonic-gate 			 * next time through
14867c478bd9Sstevel@tonic-gate 			 */
14877c478bd9Sstevel@tonic-gate 			if (ungetc(ch, iop) == EOF && !feof(iop)) {
14887c478bd9Sstevel@tonic-gate 				/*
14897c478bd9Sstevel@tonic-gate 				 * Shouldn't happen since a getc()
14907c478bd9Sstevel@tonic-gate 				 * was just done
14917c478bd9Sstevel@tonic-gate 				 */
14927c478bd9Sstevel@tonic-gate 				fatal("fgetline - ungetc failed");
14937c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
14947c478bd9Sstevel@tonic-gate 			}
14957c478bd9Sstevel@tonic-gate 		}
14967c478bd9Sstevel@tonic-gate 		*cs++ = '\f';
14977c478bd9Sstevel@tonic-gate 		*cs = '\0';
14987c478bd9Sstevel@tonic-gate 		return (s);
14997c478bd9Sstevel@tonic-gate 	}
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	/*
15027c478bd9Sstevel@tonic-gate 	 * Check for "weird" input characters is made in proc()
15037c478bd9Sstevel@tonic-gate 	 */
15047c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
15057c478bd9Sstevel@tonic-gate 		if (ch == '\f' || ch == '\n')
15067c478bd9Sstevel@tonic-gate 			break;
15077c478bd9Sstevel@tonic-gate 		*cs++ = ch;
15087c478bd9Sstevel@tonic-gate 		if ((ch = getc(iop)) == EOF)
15097c478bd9Sstevel@tonic-gate 			break;
15107c478bd9Sstevel@tonic-gate 	}
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	if (ch == EOF && cs == s)		/* Nothing was read */
15137c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
15147c478bd9Sstevel@tonic-gate 	if (ch == '\f') {
15157c478bd9Sstevel@tonic-gate 		if (ungetc(ch, iop) == EOF)
15167c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fgetline - can't ungetc??\n");
15177c478bd9Sstevel@tonic-gate 	} else if (ch != '\n' && ch != EOF) {
15187c478bd9Sstevel@tonic-gate 		fatal("fgetline - input line too long");
15197c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
15207c478bd9Sstevel@tonic-gate 	}
15217c478bd9Sstevel@tonic-gate 	*cs = '\0';
15227c478bd9Sstevel@tonic-gate 	return (s);
15237c478bd9Sstevel@tonic-gate }
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
15267c478bd9Sstevel@tonic-gate void
15277c478bd9Sstevel@tonic-gate fatal(char *fmt, ...)
15287c478bd9Sstevel@tonic-gate {
15297c478bd9Sstevel@tonic-gate 	va_list ap;
15307c478bd9Sstevel@tonic-gate 
15317c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", progname);
15327c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
15337c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, ap);
15347c478bd9Sstevel@tonic-gate 	va_end(ap);
15357c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
15367c478bd9Sstevel@tonic-gate 	exit(1);
15377c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
15387c478bd9Sstevel@tonic-gate }
1539