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