xref: /csrg-svn/local/transcript/src/psgrind.c (revision 32172)
1*32172Sedward /*	@(#)psgrind.c	1.1 09/15/87	*/
2*32172Sedward /*
3*32172Sedward  *  psgrind - quick hack to grind C source files directly into
4*32172Sedward  *  PostScript.
5*32172Sedward  *
6*32172Sedward  *  John Coker
7*32172Sedward  *  University of California, Berkeley
8*32172Sedward  *
9*32172Sedward  *  The basis for this program is the enscript utility provided
10*32172Sedward  *  by TranScript to driver the Apple LaserWriter printer.  This
11*32172Sedward  *  code was taken and mangled without permission of any kind;
12*32172Sedward  *  don't tell anyone.  -john
13*32172Sedward  */
14*32172Sedward 
15*32172Sedward #define POSTSCRIPTPRINTER "gp"
16*32172Sedward 
17*32172Sedward #define HEADERFONT	"Helvetica-Bold"
18*32172Sedward #define BODYFONT 	"Helvetica"
19*32172Sedward #define KWORDFONT 	"Helvetica-Bold"
20*32172Sedward #define COMMENTFONT	"Helvetica-Oblique"
21*32172Sedward #define LITERALFONT  	"Courier"
22*32172Sedward 
23*32172Sedward #ifndef PSGRINDPRO
24*32172Sedward #define PSGRINDPRO	"/psgrind.pro"
25*32172Sedward #endif !PSGRINDPRO
26*32172Sedward 
27*32172Sedward #ifndef PSGRINDTEMP
28*32172Sedward #define PSGRINDTEMP	"/GRXXXXXX"
29*32172Sedward #endif !PSGRINDTEMP
30*32172Sedward 
31*32172Sedward #define UperInch 1440
32*32172Sedward #define PtsPerInch 72
33*32172Sedward #define UperPt 20
34*32172Sedward #define TruePageWidth  (UperInch*17/2)
35*32172Sedward #define PageWidth  (UperInch*(8*17-3)/4)
36*32172Sedward #define PageLength (UperInch*(8*11-3)/8)
37*32172Sedward #define TruePageLength (UperInch*11)
38*32172Sedward 
39*32172Sedward #include <stdio.h>
40*32172Sedward #include <ctype.h>
41*32172Sedward #include <strings.h>
42*32172Sedward #include <pwd.h>
43*32172Sedward #include <sys/types.h>
44*32172Sedward #include <sys/stat.h>
45*32172Sedward #include "transcript.h"
46*32172Sedward 
47*32172Sedward #define LPR "lpr"
48*32172Sedward #define REVERSE "psrev"
49*32172Sedward 
50*32172Sedward #define MAXBAD 20	/* number of bad chars to pass before complaint */
51*32172Sedward 
52*32172Sedward private struct stat S;
53*32172Sedward char   *ctime ();
54*32172Sedward char   *getenv ();
55*32172Sedward char   *rindex ();
56*32172Sedward 
57*32172Sedward #define FSIZEMAX 256		/* number of chars per font */
58*32172Sedward 
59*32172Sedward /* the layout of a font information block */
60*32172Sedward struct font {
61*32172Sedward     char    name[100];		/* PostScript font name */
62*32172Sedward     int     dsize;		/* size */
63*32172Sedward     int     Xwid[FSIZEMAX];	/* X widths for each character */
64*32172Sedward };
65*32172Sedward 
66*32172Sedward private struct font fonts[16];		/* 16 possible fonts at one time */
67*32172Sedward private int nf = 0;			/* number of fonts known about */
68*32172Sedward 
69*32172Sedward private int HeaderFont = -1;		/* handle for header font */
70*32172Sedward private int BodyFont = -1;		/* handle for body font */
71*32172Sedward private int KwordFont = -1;		/* handle for keyword font */
72*32172Sedward private int LiteralFont = -1;		/* handle for literal font */
73*32172Sedward private int CommentFont = -1;		/* handle for comment font */
74*32172Sedward 
75*32172Sedward private int TabWidth = TruePageWidth / 10;	/* width of a tab */
76*32172Sedward private int BSWidth;				/* width of a backspace */
77*32172Sedward 
78*32172Sedward private int UperLine = UperInch / 7;
79*32172Sedward private int UperHLine = UperInch / 7;
80*32172Sedward 
81*32172Sedward private char *prog;		/* program name argv[0] */
82*32172Sedward private char TempName[100];	/* name of temporary PostScript file */
83*32172Sedward private char OutName[256] = 0;	/* filename for disk output */
84*32172Sedward private int PipeOut = 0;	/* true if output to stdout (-p -) */
85*32172Sedward private int ListOmitted = 0;	/* list omitted chars on the tty */
86*32172Sedward private int LPTsimulate = 0;	/* true if an lpt should be simulated */
87*32172Sedward private int LinesLeft = 64;	/* lines left on page when in LPT mode */
88*32172Sedward private int LineNo;		/* line number in current file */
89*32172Sedward private int SeenText = 1;	/* true if seen some text on this page */
90*32172Sedward private int OutOnly = 0;	/* true if PS file only wanted */
91*32172Sedward private int Rotated = 0;	/* true if the page is to be rotated */
92*32172Sedward private int Reverse = 0;	/* output should be piped to psrev */
93*32172Sedward private char *PageSpec = 0;	/* ditto */
94*32172Sedward private int PreFeed = 0;	/* true if prefeed should be enabled */
95*32172Sedward private int TwoColumn = 0;	/* true of if in two-column mode */
96*32172Sedward private int FirstCol = 1;	/* true if we're printing column 1 */
97*32172Sedward private int NoTitle = 0;	/* true if title line is to be suppressed */
98*32172Sedward private int Cvted = 0;		/* true if converted a file to PS format */
99*32172Sedward 
100*32172Sedward private int IgnoreGarbage = 0;	/* true if garbage should be ignored */
101*32172Sedward private int SeenFile = 0;	/* true if a file has been processed */
102*32172Sedward private int SeenFont = 0;	/* true if we've seen a font request */
103*32172Sedward private int ScannedFonts = 0;	/* true if we've scanned the font file */
104*32172Sedward private char *FileName = 0;	/* name of file currently being PSed */
105*32172Sedward private char *FileDate = 0;	/* last mod date of file being PSed */
106*32172Sedward private char DateStr[27];	/* thanks, but no thanks ctime! */
107*32172Sedward 
108*32172Sedward private char *spoolJobClass = 0;
109*32172Sedward private char *spoolJobName = 0;
110*32172Sedward private char *PrinterName = 0;
111*32172Sedward private int spoolNotify = 0;
112*32172Sedward private int spoolNoBurst = 0;
113*32172Sedward private int spoolCopies = 1;
114*32172Sedward 
115*32172Sedward private char tempstr[256];	/* various path names */
116*32172Sedward 
117*32172Sedward private int CurFont;		/* current Font */
118*32172Sedward private int LastFont;		/* previous Font */
119*32172Sedward 
120*32172Sedward private int cX, cY;		/* current page positions */
121*32172Sedward private int dX, dY;		/* desired page positions */
122*32172Sedward private int lX, lY;		/* page positions of the start of the line */
123*32172Sedward private int crX, crY;		/* X and Y increments to apply to CR's */
124*32172Sedward 
125*32172Sedward #define None	0
126*32172Sedward #define RelX	1
127*32172Sedward #define	RelY	2
128*32172Sedward #define RelXY	3
129*32172Sedward #define AbsX	4
130*32172Sedward #define AbsY	8
131*32172Sedward #define AbsXY	12
132*32172Sedward 
133*32172Sedward private int movepending;	/* moveto pending coords on stack */
134*32172Sedward private int showpending;	/* number of characters waiting to be shown */
135*32172Sedward private char *UsersHeader = 0;	/* user specified heading */
136*32172Sedward private char *Header = 0;	/* generated header (usually FileName) */
137*32172Sedward private int Page = 0;		/* current page number */
138*32172Sedward private int TotalPages = 0;	/* total number of pages printed */
139*32172Sedward private int TruncChars = 0;	/* number of characters truncated */
140*32172Sedward private int UndefChars = 0;	/* number of characters skipped because
141*32172Sedward 				   they weren't defined in some font */
142*32172Sedward private int BadChars   = 0;	/* number of bad characters seen so far */
143*32172Sedward 
144*32172Sedward private FILE *OutFile = 0;	/* output ps file */
145*32172Sedward 
146*32172Sedward /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */
147*32172Sedward private decodefont (name, f)
148*32172Sedward register char  *name;
149*32172Sedward register struct font *f; {
150*32172Sedward     register char *d, *p;
151*32172Sedward 
152*32172Sedward     SeenFont++;
153*32172Sedward     if (ScannedFonts) {
154*32172Sedward 	fprintf(stderr,"Fonts must be specified before any files are processed\n");
155*32172Sedward 	exit(1);
156*32172Sedward     }
157*32172Sedward     p = name;
158*32172Sedward     d = f->name;
159*32172Sedward     while (isascii(*p) && (isalpha(*p) || (*p == '-'))) {*d++ = *p++;}
160*32172Sedward     *d++ = '\0';
161*32172Sedward     if (isascii(*p) && isdigit(*p)) {
162*32172Sedward 	f->dsize = 0;
163*32172Sedward 	do
164*32172Sedward 	    f->dsize = f->dsize * 10 + *p++ - '0';
165*32172Sedward 	while ('0' <= *p && *p <= '9');
166*32172Sedward     }
167*32172Sedward     if (*p || !f->dsize || !f->name[0]) {
168*32172Sedward 	fprintf (stderr, "Poorly formed font name: \"%s\"\n", name);
169*32172Sedward 	exit (1);
170*32172Sedward     }
171*32172Sedward }
172*32172Sedward 
173*32172Sedward 
174*32172Sedward #define NOTDEF 0x8000
175*32172Sedward #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--)
176*32172Sedward 
177*32172Sedward /* Scan the font metrics directory looking for entries that match the
178*32172Sedward  * entries in ``fonts''.  For entries
179*32172Sedward  * that are found the data in the font description is filled in,
180*32172Sedward  * if any are missing, it dies horribly.
181*32172Sedward  */
182*32172Sedward private ScanFont () {
183*32172Sedward     register struct font   *f;
184*32172Sedward     register FILE *FontData;		/* afm file */
185*32172Sedward     char    *c;
186*32172Sedward     int     ccode, cwidth, inChars;
187*32172Sedward     char   *MetricsDir = (char *) getenv ("METRICS");
188*32172Sedward     char    FontFile[512];		/* afm file name */
189*32172Sedward     char    afmbuf[BUFSIZ];
190*32172Sedward 
191*32172Sedward     if (MetricsDir == 0)
192*32172Sedward 	MetricsDir = LibDir;
193*32172Sedward 
194*32172Sedward     if (!SeenFont & Rotated & TwoColumn) {
195*32172Sedward 	fonts[HeaderFont].dsize = 10;
196*32172Sedward 	fonts[BodyFont].dsize = 7;
197*32172Sedward 	fonts[KwordFont].dsize = 7;
198*32172Sedward 	fonts[LiteralFont].dsize = 8;
199*32172Sedward 	fonts[CommentFont].dsize = 7;
200*32172Sedward     }
201*32172Sedward 
202*32172Sedward     /* loop through fonts, find and read metric entry in dir */
203*32172Sedward     ForAllFonts (f) {
204*32172Sedward 	mstrcat(FontFile, MetricsDir, "/", sizeof FontFile);
205*32172Sedward 	mstrcat(FontFile, FontFile, f->name, sizeof FontFile);
206*32172Sedward 	mstrcat(FontFile, FontFile, ".afm", sizeof FontFile);
207*32172Sedward 	if ((FontData = fopen(FontFile,"r")) == NULL){
208*32172Sedward 	    fprintf(stderr,"Can't open font metrics file %s\n",FontFile);
209*32172Sedward 	    exit(1);
210*32172Sedward 	}
211*32172Sedward 	/* read the .afm file to get the widths */
212*32172Sedward 	for (ccode = 0; ccode < FSIZEMAX; ccode++) f->Xwid[ccode] = NOTDEF;
213*32172Sedward 
214*32172Sedward 	inChars = 0;
215*32172Sedward 	while(fgets(afmbuf, sizeof afmbuf, FontData) != NULL) {
216*32172Sedward 	    /* strip off newline */
217*32172Sedward 	    if ((c = index(afmbuf, '\n')) == 0) {
218*32172Sedward 		fprintf(stderr, "AFM file %s line too long %s\n", FontFile, afmbuf);
219*32172Sedward 		exit(1);
220*32172Sedward 	    }
221*32172Sedward 	    *c = '\0';
222*32172Sedward 	    if (*afmbuf == '\0') continue;
223*32172Sedward 	    if (strcmp(afmbuf, "StartCharMetrics") == 0) {
224*32172Sedward 		inChars++;
225*32172Sedward 		continue;
226*32172Sedward 	    }
227*32172Sedward 	    if (strcmp(afmbuf, "EndCharMetrics") == 0) break;
228*32172Sedward 	    if (inChars == 1) {
229*32172Sedward 		if (sscanf(afmbuf, "C %d ; WX %d ;",&ccode,&cwidth) != 2) {
230*32172Sedward 		    fprintf(stderr,"Trouble with AFM file %s\n",FontFile);
231*32172Sedward 		    exit(1);
232*32172Sedward 		}
233*32172Sedward 		/* get out once we see an unencoded char */
234*32172Sedward 		if (ccode == -1) break;
235*32172Sedward 		if (ccode > 255) continue;
236*32172Sedward 		f->Xwid[ccode] = (cwidth * f->dsize * UperPt) / 1000;
237*32172Sedward 		continue;
238*32172Sedward 	    }
239*32172Sedward 	}
240*32172Sedward     fclose (FontData);
241*32172Sedward     }
242*32172Sedward 
243*32172Sedward     TabWidth = fonts[BodyFont].Xwid['0'] * 8; /* 8 * figure width */
244*32172Sedward     BSWidth = fonts[BodyFont].Xwid[' ']; /* space width */
245*32172Sedward 
246*32172Sedward     UperLine = (fonts[BodyFont].dsize + 1) * UperPt;
247*32172Sedward 
248*32172Sedward     if (LPTsimulate)
249*32172Sedward 	UperHLine = UperLine;
250*32172Sedward     else
251*32172Sedward 	UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt;
252*32172Sedward 
253*32172Sedward     crX = 0;
254*32172Sedward     crY = -UperLine;
255*32172Sedward }
256*32172Sedward 
257*32172Sedward /* Return a font number for the font with the indicated name
258*32172Sedward  * and size.  Adds info to the font list for the eventual search.
259*32172Sedward  */
260*32172Sedward private DefineFont (name, size)
261*32172Sedward char   *name; {
262*32172Sedward     register struct font   *p;
263*32172Sedward     p = &fonts[nf];
264*32172Sedward     strcpy (p->name, name);
265*32172Sedward     p->dsize = size;
266*32172Sedward     return (nf++);
267*32172Sedward }
268*32172Sedward 
269*32172Sedward /* add a shown character to the PS file */
270*32172Sedward private OUTputc (c)
271*32172Sedward unsigned char    c; {
272*32172Sedward     if (showpending == 0) {putc('(', OutFile); showpending++;}
273*32172Sedward     if (c == '\\' || c=='(' || c == ')') putc('\\', OutFile);
274*32172Sedward     if ((c > 0176) || (c < 040)) {
275*32172Sedward 	putc('\\',OutFile);
276*32172Sedward 	putc((c >> 6) +'0',OutFile);
277*32172Sedward 	putc(((c >> 3) & 07)+'0', OutFile);
278*32172Sedward 	putc((c & 07)+'0',OutFile);
279*32172Sedward     }
280*32172Sedward     else putc (c, OutFile);
281*32172Sedward }
282*32172Sedward 
283*32172Sedward /* Set the current font */
284*32172Sedward private SetFont (f) {
285*32172Sedward     FlushShow();
286*32172Sedward     LastFont = CurFont;
287*32172Sedward     fprintf(OutFile, "%d F\n", CurFont = f);
288*32172Sedward }
289*32172Sedward 
290*32172Sedward /* Reset to previous font */
291*32172Sedward private PrevFont () {
292*32172Sedward     int	temp;
293*32172Sedward 
294*32172Sedward     FlushShow();
295*32172Sedward     temp = CurFont;
296*32172Sedward     CurFont = LastFont;
297*32172Sedward     LastFont = temp;
298*32172Sedward     fprintf(OutFile, "%d F\n", CurFont);
299*32172Sedward }
300*32172Sedward 
301*32172Sedward /* put a character onto the page at the desired X and Y positions.
302*32172Sedward  * If the current position doesn't agree with the desired position, put out
303*32172Sedward  * movement directives.  Leave the current position updated
304*32172Sedward  * to account for the character.
305*32172Sedward  */
306*32172Sedward private ShowChar (c)
307*32172Sedward register int c; {
308*32172Sedward     register struct font   *f;
309*32172Sedward     register    nX, nY;
310*32172Sedward     static level = 0;
311*32172Sedward 
312*32172Sedward     level++;
313*32172Sedward     f = &fonts[CurFont];
314*32172Sedward 
315*32172Sedward     if (f->Xwid[c] == NOTDEF) {
316*32172Sedward 	UndefChars++;
317*32172Sedward 	if(ListOmitted)
318*32172Sedward 	    printf("\'%c\' (%03o) not found in font %s\n",c,c,f->name);
319*32172Sedward 	if(level<=1){
320*32172Sedward 	    ShowChar('\\');
321*32172Sedward 	    ShowChar((c>>6)+'0');
322*32172Sedward 	    ShowChar(((c>>3)&07)+'0');
323*32172Sedward 	    ShowChar((c&07)+'0');
324*32172Sedward 	}
325*32172Sedward 	level--;
326*32172Sedward 	return;
327*32172Sedward     }
328*32172Sedward     nX = dX + f->Xwid[c]; /* resulting position after showing this char */
329*32172Sedward     nY = dY;
330*32172Sedward 
331*32172Sedward     if (c != ' ' || ((cX == dX) && (cY == dY)))
332*32172Sedward 	if ((!Rotated && (nX <= PageWidth) && (nY <= PageLength))
333*32172Sedward 	|| (Rotated && (nX <= PageLength) && (nY <= PageWidth))) {
334*32172Sedward 	    if (cX != dX) {
335*32172Sedward 	       if (cY != dY) {
336*32172Sedward 		  FlushShow();
337*32172Sedward 		  /* absolute x, relative y */
338*32172Sedward 		  fprintf(OutFile,"%d %d",dX, dY);
339*32172Sedward 		  movepending = AbsXY;
340*32172Sedward 		  }
341*32172Sedward 	       else {
342*32172Sedward 		  FlushShow();
343*32172Sedward 		  fprintf(OutFile,"%d",dX-cX); /* relative x */
344*32172Sedward 		  movepending = RelX;
345*32172Sedward 		  }
346*32172Sedward 	    }
347*32172Sedward 	    else if (cY != dY) {
348*32172Sedward 		FlushShow();
349*32172Sedward 		fprintf(OutFile,"%d",dY-cY); /* relative y */
350*32172Sedward 		movepending = RelY;
351*32172Sedward 		}
352*32172Sedward 	    OUTputc (c);
353*32172Sedward 	    showpending++;
354*32172Sedward 	    cX = nX;
355*32172Sedward 	    cY = nY;
356*32172Sedward 	}
357*32172Sedward 	else
358*32172Sedward 	    TruncChars++;
359*32172Sedward     dX = nX;
360*32172Sedward     dY = nY;
361*32172Sedward 
362*32172Sedward     level--;
363*32172Sedward }
364*32172Sedward 
365*32172Sedward /* put out a shown string to the PS file */
366*32172Sedward private ShowStr (s)
367*32172Sedward register char  *s; {
368*32172Sedward     while (*s) {
369*32172Sedward 	if (*s >= 040) ShowChar (*s);
370*32172Sedward 	s++;
371*32172Sedward     }
372*32172Sedward }
373*32172Sedward 
374*32172Sedward /* flush pending show */
375*32172Sedward private FlushShow() {
376*32172Sedward     if (showpending) {
377*32172Sedward        putc(')',OutFile);
378*32172Sedward 	switch (movepending) {
379*32172Sedward 	    case RelX:
380*32172Sedward 		putc('X',OutFile);
381*32172Sedward 		break;
382*32172Sedward 	    case RelY:
383*32172Sedward 	    	putc('Y',OutFile);
384*32172Sedward 		break;
385*32172Sedward 	    case AbsXY:
386*32172Sedward 	    	putc('B',OutFile);
387*32172Sedward 		break;
388*32172Sedward 	    case None:
389*32172Sedward 	    	putc('S',OutFile);
390*32172Sedward 	    	break;
391*32172Sedward 	}
392*32172Sedward 	putc('\n',OutFile);
393*32172Sedward 	movepending = None;
394*32172Sedward 	showpending = 0;
395*32172Sedward     }
396*32172Sedward }
397*32172Sedward 
398*32172Sedward /* put out a page heading to the PS file */
399*32172Sedward private InitPage () {
400*32172Sedward     char    *basename();
401*32172Sedward     char    header[200];
402*32172Sedward     register int  OldFont = CurFont;
403*32172Sedward 
404*32172Sedward     TotalPages++;
405*32172Sedward     fprintf(OutFile, "%%%%Page: ? %d\n", TotalPages);
406*32172Sedward     fprintf(OutFile, "StartPage\n");
407*32172Sedward     LinesLeft = 64;
408*32172Sedward     SeenText = 0;
409*32172Sedward     cX = cY = -1;
410*32172Sedward     showpending = 0;
411*32172Sedward     FirstCol = 1;
412*32172Sedward     lX = dX = UperInch;
413*32172Sedward     lY = dY = PageLength - UperHLine * 3 / 2;
414*32172Sedward     if (Rotated) {
415*32172Sedward         fprintf(OutFile, "Landscape\n");
416*32172Sedward 	lX = dX = UperInch / 4;
417*32172Sedward     }
418*32172Sedward     movepending = None;
419*32172Sedward     cX = dX; cY = dY;
420*32172Sedward     if (!NoTitle) {
421*32172Sedward 	SetFont (HeaderFont);
422*32172Sedward         fprintf(OutFile, "%d %d ", cX, cY);
423*32172Sedward         movepending = AbsXY;
424*32172Sedward 	if (UsersHeader) {
425*32172Sedward 	    if (*UsersHeader == 0) {
426*32172Sedward 		fprintf(OutFile,"()B\n");
427*32172Sedward 		movepending = None;
428*32172Sedward 		showpending = 0;
429*32172Sedward 	    }
430*32172Sedward 	    else ShowStr (UsersHeader);
431*32172Sedward 	}
432*32172Sedward 	else {
433*32172Sedward 	    Page++;
434*32172Sedward 	    if (FileName == 0)
435*32172Sedward 		    sprintf(header, "Page %d", Page);
436*32172Sedward 	    else
437*32172Sedward 	    sprintf (header, "%s,  page %d", basename(FileName), Page);
438*32172Sedward 	    ShowStr (header);
439*32172Sedward 	}
440*32172Sedward 	FlushShow();
441*32172Sedward 	dX = lX = lX + crX * 3;
442*32172Sedward 	dY = lY = lY + crY * 3;
443*32172Sedward     }
444*32172Sedward     else {
445*32172Sedward 	/* fake it to force a moveto */
446*32172Sedward 	cX = cY = 0;
447*32172Sedward     }
448*32172Sedward     SetFont (OldFont);
449*32172Sedward }
450*32172Sedward 
451*32172Sedward /* terminate a page. */
452*32172Sedward private ClosePage () {
453*32172Sedward     FlushShow();
454*32172Sedward     fprintf(OutFile,"EndPage\n");
455*32172Sedward }
456*32172Sedward 
457*32172Sedward /* skip to a new page */
458*32172Sedward private PageEject () {
459*32172Sedward     if (TwoColumn && FirstCol) {
460*32172Sedward 	FirstCol = 0;
461*32172Sedward 	lX = dX = TruePageWidth / 2;
462*32172Sedward 	lY = dY = PageLength - (UperHLine * 3 / 2);
463*32172Sedward 	if (Rotated) {
464*32172Sedward 	   lX = dX = TruePageLength / 2;
465*32172Sedward 	   }
466*32172Sedward 	if (!NoTitle) {
467*32172Sedward 	    dX = lX = lX + crX * 3;
468*32172Sedward 	    dY = lY = lY + crY * 3;
469*32172Sedward 	}
470*32172Sedward     }
471*32172Sedward     else {
472*32172Sedward 	ClosePage ();
473*32172Sedward 	InitPage ();
474*32172Sedward     }
475*32172Sedward     LinesLeft = 64;
476*32172Sedward     SeenText = 0;
477*32172Sedward }
478*32172Sedward 
479*32172Sedward #if 0
480*32172Sedward /* commented out AIS Fri Feb 22 10:00:36 1985 */
481*32172Sedward private PageMessage (TotalPages)
482*32172Sedward {
483*32172Sedward     if (TotalPages > 0) {
484*32172Sedward 	printf ("psgrind formatted[ %d page%s * %d cop%s ]\n",
485*32172Sedward 		TotalPages, TotalPages > 1 ? "s" : "",
486*32172Sedward 		spoolCopies, spoolCopies > 1 ? "ies" : "y" );
487*32172Sedward     }
488*32172Sedward }
489*32172Sedward #endif
490*32172Sedward 
491*32172Sedward private CommentHeader() {
492*32172Sedward     long clock;
493*32172Sedward     struct passwd *pswd;
494*32172Sedward     char hostname[40];
495*32172Sedward     /* copy the file, prepending a new comment header */
496*32172Sedward     fprintf(OutFile,"%%!%s\n",COMMENTVERSION);
497*32172Sedward     fprintf(OutFile,"%%%%Creator: ");
498*32172Sedward     pswd = getpwuid(getuid());
499*32172Sedward     gethostname(hostname, (int) sizeof hostname);
500*32172Sedward     fprintf(OutFile,"%s:%s (%s)%s\n", hostname, pswd->pw_name,
501*32172Sedward     	pswd->pw_gecos, spoolJobClass);
502*32172Sedward 
503*32172Sedward     fprintf(OutFile,"%%%%Title: %s %s\n",
504*32172Sedward     	(FileName?FileName:"stdin"),
505*32172Sedward 	spoolJobName);
506*32172Sedward 
507*32172Sedward     fprintf(OutFile,"%%%%CreationDate: %s",(time(&clock),ctime(&clock)));
508*32172Sedward }
509*32172Sedward 
510*32172Sedward 
511*32172Sedward /* list of C keywords to put in KwordFont */
512*32172Sedward private char *KeyWordList[] = {
513*32172Sedward     "int", "char", "float", "double", "struct", "union",
514*32172Sedward     "long", "short", "unsigned", "auto", "extern", "register",
515*32172Sedward     "typedef", "static", "goto", "return", "sizeof", "break",
516*32172Sedward     "continue", "if", "else", "for", "do", "while", "switch",
517*32172Sedward     "case", "default", "entry", NULL
518*32172Sedward };
519*32172Sedward 
520*32172Sedward /* macros identifying C identifiers */
521*32172Sedward #define isfirst(c)	(isalpha(c) || (c) == '_')
522*32172Sedward #define isident(c)	(isalnum(c) || (c) == '_')
523*32172Sedward 
524*32172Sedward /* Copy the standard input file to the PS file */
525*32172Sedward private CopyFile () {
526*32172Sedward     register int   c, last;
527*32172Sedward     register int    col = 1;
528*32172Sedward     int	InComment, InString, InChar, IsKword;
529*32172Sedward     char token[50], *tend = token + sizeof (token) - 1;
530*32172Sedward     register char *tp, **kwp;
531*32172Sedward 
532*32172Sedward     if (OutFile == 0) {
533*32172Sedward 	if (OutOnly && !(PageSpec || Reverse)) {
534*32172Sedward 	   OutFile = PipeOut ? stdout : fopen(OutName,"w");
535*32172Sedward 	}
536*32172Sedward 	else {
537*32172Sedward 	    mktemp(mstrcat(TempName,TempDir,PSGRINDTEMP,sizeof TempName));
538*32172Sedward 	    OutFile = fopen (TempName, "w");
539*32172Sedward 	}
540*32172Sedward     }
541*32172Sedward     if (OutFile == NULL) {
542*32172Sedward 	fprintf(stderr, "Can't create PS file %s\n",TempName);
543*32172Sedward 	exit(1);
544*32172Sedward     }
545*32172Sedward     if (!ScannedFonts) {
546*32172Sedward 	ScannedFonts++;
547*32172Sedward 	ScanFont();
548*32172Sedward     }
549*32172Sedward     if (!Cvted) {
550*32172Sedward 	CommentHeader();
551*32172Sedward 	if (nf) {
552*32172Sedward 	    register struct font *f;
553*32172Sedward 	    fprintf(OutFile,"%%%%DocumentFonts:");
554*32172Sedward  	    ForAllFonts(f) {
555*32172Sedward 		fprintf(OutFile," %s",f->name);
556*32172Sedward 	    }
557*32172Sedward 	    fprintf(OutFile,"\n");
558*32172Sedward 	}
559*32172Sedward 	/* copy in fixed prolog */
560*32172Sedward 	if (copyfile(mstrcat(tempstr,LibDir,PSGRINDPRO,sizeof tempstr),
561*32172Sedward 		OutFile)) {
562*32172Sedward 	    fprintf(stderr,"trouble copying prolog file \"%s\".\n",tempstr);
563*32172Sedward 	    exit(1);
564*32172Sedward 	}
565*32172Sedward 	fprintf(OutFile,"StartEnscriptDoc %% end fixed prolog\n");
566*32172Sedward 	DumpFonts();
567*32172Sedward 	fprintf(OutFile,"%%%%EndProlog\n");
568*32172Sedward 	if (PreFeed) {
569*32172Sedward 	    fprintf(OutFile,"true DoPreFeed\n");
570*32172Sedward 	}
571*32172Sedward     }
572*32172Sedward     Cvted++;
573*32172Sedward 
574*32172Sedward     Page = 0;
575*32172Sedward     LineNo = 1;
576*32172Sedward     BadChars = 0;		/* give each file a clean slate */
577*32172Sedward     InitPage ();
578*32172Sedward     last = '\0';
579*32172Sedward     InComment = InChar = InString = 0;
580*32172Sedward     while ((c = getchar ()) != EOF) {
581*32172Sedward 	if ((c > 0177 || c < 0) && (!IgnoreGarbage)) {
582*32172Sedward 	    if (BadChars++ > MAXBAD) {/* allow some kruft but not much */
583*32172Sedward 	      fprintf(stderr,"\"%s\" not a text file? - char '\\%03o'@0%o\nTry -g.\n",
584*32172Sedward 		    FileName ? FileName : "stdin", c, ftell (stdin) - 1);
585*32172Sedward 	      exit(1);
586*32172Sedward 	    }
587*32172Sedward 	} else {
588*32172Sedward 	    switch (c) {
589*32172Sedward 		case 010: /* backspace */
590*32172Sedward 		    dX -= BSWidth;
591*32172Sedward 		    break;
592*32172Sedward 		case 015: /* carriage return ^M */
593*32172Sedward 		    dY = lY;
594*32172Sedward 		    dX = lX;
595*32172Sedward 		    break;
596*32172Sedward 		case 012: /* linefeed ^J */
597*32172Sedward 		    LineNo++;
598*32172Sedward 		    if (dX != lX || dY != lY || !LPTsimulate || SeenText){
599*32172Sedward 			SeenText++;
600*32172Sedward 			dY = lY = lY + crY;
601*32172Sedward 			dX = lX = lX + crX;
602*32172Sedward 		    }
603*32172Sedward 		    else
604*32172Sedward 			LinesLeft = 64;
605*32172Sedward 		    if (((!Rotated) && (dY < UperLine))
606*32172Sedward 		    || (Rotated && (dY < ((PageLength-TruePageWidth) +
607*32172Sedward 						3*UperLine+480)))
608*32172Sedward 		    || (LPTsimulate && (--LinesLeft <= 0)))
609*32172Sedward 			PageEject ();
610*32172Sedward 		    col = 1;
611*32172Sedward 		    break;
612*32172Sedward 		case 014: /* form feed ^L */
613*32172Sedward 		    PageEject ();
614*32172Sedward 		    col = 1;
615*32172Sedward 		    break;
616*32172Sedward 		case 011: /* tab ^I */
617*32172Sedward 		    col = (col - 1) / 8 * 8 + 9;
618*32172Sedward 		    dX = lX + (col - 1) / 8 * TabWidth;
619*32172Sedward 		    break;
620*32172Sedward 	        case '\\': /* special escape */
621*32172Sedward 		    last = c;
622*32172Sedward 		    if ((c = getchar()) == EOF)
623*32172Sedward 			goto done;
624*32172Sedward 		    ShowChar('\\');
625*32172Sedward 		    col++;
626*32172Sedward 		    if (c == '\n') {
627*32172Sedward 			/* want to leave newlines alone */
628*32172Sedward 			ungetc(c, stdin);
629*32172Sedward 		    } else {
630*32172Sedward 			ShowChar(c);
631*32172Sedward 			col++;
632*32172Sedward 		    }
633*32172Sedward 		    break;
634*32172Sedward 	        case '"': /* a string quote mark */
635*32172Sedward 		    if (InComment || InChar) {
636*32172Sedward 			/* just put out the quote */
637*32172Sedward 			ShowChar('"');
638*32172Sedward 			col++;
639*32172Sedward 		    } else if (InString) {
640*32172Sedward 			ShowChar('"');
641*32172Sedward 			col++;
642*32172Sedward 			PrevFont();
643*32172Sedward 			InString = 0;
644*32172Sedward 		    } else {
645*32172Sedward 			SetFont(LiteralFont);
646*32172Sedward 			ShowChar('"');
647*32172Sedward 			col++;
648*32172Sedward 			InString = 1;
649*32172Sedward 		    }
650*32172Sedward 		    break;
651*32172Sedward 	        case '\'': /* a char quote mark */
652*32172Sedward 		    if (InComment || InString) {
653*32172Sedward 			/* just put out the character */
654*32172Sedward 			ShowChar('\'');
655*32172Sedward 			col++;
656*32172Sedward 		    } else if (InChar) {
657*32172Sedward 			ShowChar('\'');
658*32172Sedward 			col++;
659*32172Sedward 			PrevFont();
660*32172Sedward 			InChar = 0;
661*32172Sedward 		    } else {
662*32172Sedward 			SetFont(LiteralFont);
663*32172Sedward 			ShowChar('\'');
664*32172Sedward 			col++;
665*32172Sedward 			InChar = 1;
666*32172Sedward 		    }
667*32172Sedward 		    break;
668*32172Sedward 	        case '/':
669*32172Sedward 		    if (InComment && last == '*') {
670*32172Sedward 			ShowChar('/');
671*32172Sedward 			col++;
672*32172Sedward 			SetFont(BodyFont);
673*32172Sedward 			InComment = 0;
674*32172Sedward 		    } else if ((c = getchar()) == '*' && !InComment) {
675*32172Sedward 			SetFont(CommentFont);
676*32172Sedward 			InComment = 1;
677*32172Sedward 			ShowChar('/');
678*32172Sedward 			ShowChar('*');
679*32172Sedward 			col += 2;
680*32172Sedward 		    } else {
681*32172Sedward 			ungetc(c, stdin);
682*32172Sedward 			ShowChar('/');
683*32172Sedward 			col++;
684*32172Sedward 			c = '/';
685*32172Sedward 		    }
686*32172Sedward 		    break;
687*32172Sedward 		default: /* plain text, put it out */
688*32172Sedward 		    if (!InComment && !InString && isfirst(c)) {
689*32172Sedward 			tp = token;
690*32172Sedward 			while (isident(c) && tp < tend) {
691*32172Sedward 			    *tp++ = c;
692*32172Sedward 			    last = c;
693*32172Sedward 			    c = getchar();
694*32172Sedward 			}
695*32172Sedward 			*tp = '\0';
696*32172Sedward 			ungetc(c, stdin);
697*32172Sedward 			tp = token;
698*32172Sedward 			IsKword = 0;
699*32172Sedward 			for (kwp = KeyWordList; *kwp != NULL; kwp++)
700*32172Sedward 				if (!strcmp(*kwp, tp)) {
701*32172Sedward 					IsKword = 1;
702*32172Sedward 					break;
703*32172Sedward 				}
704*32172Sedward 			if (IsKword)
705*32172Sedward 			    SetFont(KwordFont);
706*32172Sedward 			ShowStr(tp);
707*32172Sedward 			col += strlen(tp);
708*32172Sedward 			if (IsKword)
709*32172Sedward 			    SetFont(BodyFont);
710*32172Sedward 		    } else if (fonts[CurFont].Xwid[c] != NOTDEF) {
711*32172Sedward 			/* other normal character */
712*32172Sedward 			ShowChar (c);
713*32172Sedward 			col++;
714*32172Sedward 		    } else { /* not in font, quote it */
715*32172Sedward 			ShowChar ('\\');
716*32172Sedward 			ShowChar ((c >> 6) + '0');
717*32172Sedward 			ShowChar (((c >> 3) & 7) + '0');
718*32172Sedward 			ShowChar ((c & 7) + '0');
719*32172Sedward 			col += 4;
720*32172Sedward 		    }
721*32172Sedward 		    break;
722*32172Sedward 	     }
723*32172Sedward 	}
724*32172Sedward 	last = c;
725*32172Sedward     }
726*32172Sedward 
727*32172Sedward done:
728*32172Sedward     ClosePage ();
729*32172Sedward }
730*32172Sedward 
731*32172Sedward /* dump the fonts to the PS file for setup */
732*32172Sedward private DumpFonts () {
733*32172Sedward     register struct font   *f;
734*32172Sedward 
735*32172Sedward     ForAllFonts (f) {
736*32172Sedward         fprintf(OutFile,"%d %d /%s\n",f-&fonts[0],f->dsize*UperPt,f->name);
737*32172Sedward     }
738*32172Sedward     fprintf(OutFile, "%d SetUpFonts\n", nf);
739*32172Sedward }
740*32172Sedward 
741*32172Sedward 
742*32172Sedward /*
743*32172Sedward  * close the PS file
744*32172Sedward  */
745*32172Sedward private ClosePS () {
746*32172Sedward     fprintf(OutFile,"%%%%Trailer\n");
747*32172Sedward     if (PreFeed) {
748*32172Sedward 	fprintf(OutFile,"false DoPreFeed\n");
749*32172Sedward     }
750*32172Sedward     fprintf(OutFile,"EndEnscriptDoc\nEnscriptJob restore\n");
751*32172Sedward }
752*32172Sedward 
753*32172Sedward private ProcessArg (p)
754*32172Sedward register char  *p; {
755*32172Sedward     static  enum State {
756*32172Sedward 	normal, PSname,
757*32172Sedward 	H_fontname, B_fontname, K_fontname, C_fontname, L_fontname,
758*32172Sedward 	grabheader, getclass, getjobname
759*32172Sedward     } state = normal;
760*32172Sedward 
761*32172Sedward     switch (state) {
762*32172Sedward 	case PSname:
763*32172Sedward 	    strcpy (OutName, p);
764*32172Sedward 	    if (strcmp(OutName,"-") == 0) PipeOut++;
765*32172Sedward 	    state = normal;
766*32172Sedward 	    break;
767*32172Sedward 	case H_fontname:
768*32172Sedward 	    decodefont (p, &fonts[HeaderFont]);
769*32172Sedward 	    state = normal;
770*32172Sedward 	    break;
771*32172Sedward 	case B_fontname:
772*32172Sedward 	    decodefont (p, &fonts[BodyFont]);
773*32172Sedward 	    state = normal;
774*32172Sedward 	    break;
775*32172Sedward 	case K_fontname:
776*32172Sedward 	    decodefont (p, &fonts[KwordFont]);
777*32172Sedward 	    state = normal;
778*32172Sedward 	    break;
779*32172Sedward 	case L_fontname:
780*32172Sedward 	    decodefont (p, &fonts[LiteralFont]);
781*32172Sedward 	    state = normal;
782*32172Sedward 	    break;
783*32172Sedward 	case C_fontname:
784*32172Sedward 	    decodefont (p, &fonts[CommentFont]);
785*32172Sedward 	    state = normal;
786*32172Sedward 	    break;
787*32172Sedward 	case grabheader:
788*32172Sedward 	    UsersHeader = p;
789*32172Sedward 	    state = normal;
790*32172Sedward 	    break;
791*32172Sedward 	case getclass:
792*32172Sedward 	    spoolJobClass = p;
793*32172Sedward 	    state = normal;
794*32172Sedward 	    break;
795*32172Sedward 	case getjobname:
796*32172Sedward 	    spoolJobName = p;
797*32172Sedward 	    state = normal;
798*32172Sedward 	    break;
799*32172Sedward 	default:
800*32172Sedward 	    if (*p == '-') while (*++p) switch (*p) {
801*32172Sedward 		case '1':
802*32172Sedward 		    TwoColumn = 0;
803*32172Sedward 		    if (SeenFile) {
804*32172Sedward 			fprintf(stderr,"Specify -1 before any files\n");
805*32172Sedward 			exit(1);
806*32172Sedward 		    }
807*32172Sedward 		    break;
808*32172Sedward 		case '2':
809*32172Sedward 		    TwoColumn++;
810*32172Sedward 		    if (SeenFile){
811*32172Sedward 			fprintf(stderr,"Specify -2 before any files\n");
812*32172Sedward 			exit(1);
813*32172Sedward 		    }
814*32172Sedward 		    break;
815*32172Sedward 		case 'v':
816*32172Sedward 		    Reverse = 1;
817*32172Sedward 		    break;
818*32172Sedward 		case 's':
819*32172Sedward 		     PageSpec = (++p);
820*32172Sedward 		     while (*p != '\0') p++;
821*32172Sedward 		     return;
822*32172Sedward 
823*32172Sedward 		/* the following options allow uswer specification
824*32172Sedward 		   of the five files used by the program */
825*32172Sedward 		case 'H': state = H_fontname; break;
826*32172Sedward 		case 'B': state = B_fontname; break;
827*32172Sedward 		case 'K': state = K_fontname; break;
828*32172Sedward 		case 'L': state = L_fontname; break;
829*32172Sedward 		case 'C': state = C_fontname; break;
830*32172Sedward 
831*32172Sedward 		case 'g': IgnoreGarbage++; break;
832*32172Sedward 		case 'o': ListOmitted++; break;
833*32172Sedward 		case 'p': OutOnly++; state = PSname; break;
834*32172Sedward 		case 'r':
835*32172Sedward 		    Rotated++;
836*32172Sedward 		    if (SeenFile){
837*32172Sedward 			fprintf(stderr,"Specify rotation before any files\n");
838*32172Sedward 			exit(1);
839*32172Sedward 		    }
840*32172Sedward 		    break;
841*32172Sedward 		case 'R':
842*32172Sedward 		    Rotated = 0;
843*32172Sedward 		    if (SeenFile){
844*32172Sedward 			fprintf(stderr,"Specify rotation before any files\n");
845*32172Sedward 			exit(1);
846*32172Sedward 		    }
847*32172Sedward 		    break;
848*32172Sedward 		case 'k':
849*32172Sedward 		    PreFeed++;
850*32172Sedward 		    if (SeenFile){
851*32172Sedward 			fprintf(stderr,"Specify prefeed before any files\n");
852*32172Sedward 			exit(1);
853*32172Sedward 		    }
854*32172Sedward 		    break;
855*32172Sedward 
856*32172Sedward 		/* the following switches are as in lpr(1) and */
857*32172Sedward 		/* are passed through when spooling to a printer */
858*32172Sedward 		case 'P': /* printer name */
859*32172Sedward 		    PrinterName = (++p);
860*32172Sedward 		    while (*p != '\0') p++;
861*32172Sedward 		    return;
862*32172Sedward 		case 'J': /* job name (title) for the Job: field */
863*32172Sedward 		    state = getjobname;
864*32172Sedward 		    break;
865*32172Sedward 		case 'm': /* notify by mail */
866*32172Sedward 		    spoolNotify = 1;
867*32172Sedward 		    break;
868*32172Sedward 		case 'h':
869*32172Sedward 		    spoolNoBurst = 1;
870*32172Sedward 		    break;
871*32172Sedward 		case '#':
872*32172Sedward 		    spoolCopies = atoi(++p);
873*32172Sedward 		    if (spoolCopies < 1){
874*32172Sedward 		        fprintf(stderr,"Bad argument for -# (number of copies)\n");
875*32172Sedward 			exit(1);
876*32172Sedward 		    }
877*32172Sedward 		    break;
878*32172Sedward 
879*32172Sedward 		default:
880*32172Sedward 		    printf ("Unknown option: %c\n", *p);
881*32172Sedward 		    SeenFile++;
882*32172Sedward 		    break;
883*32172Sedward 		}
884*32172Sedward 	    else {/* not a flag -- a filename */
885*32172Sedward 		FileName = Header = p;
886*32172Sedward 		if (freopen (FileName, "r", stdin) == NULL) {
887*32172Sedward 		    printf ("Can't open %s\n", FileName);
888*32172Sedward 		    exit (1);
889*32172Sedward 		}
890*32172Sedward 		fstat (fileno (stdin), &S);
891*32172Sedward 		FileDate = strcpy(DateStr,ctime (&S.st_mtime));
892*32172Sedward 		CopyFile ();
893*32172Sedward 		fclose (stdin);
894*32172Sedward 		SeenFile = 1;
895*32172Sedward 	    }
896*32172Sedward     }
897*32172Sedward }
898*32172Sedward 
899*32172Sedward main (argc, argv)
900*32172Sedward char  **argv; {
901*32172Sedward     register char  *p, *arg;
902*32172Sedward 
903*32172Sedward     prog = *argv;
904*32172Sedward 
905*32172Sedward     BodyFont = LastFont = CurFont = DefineFont (BODYFONT, 10);
906*32172Sedward     HeaderFont = DefineFont (HEADERFONT, 12);
907*32172Sedward     KwordFont = DefineFont (KWORDFONT, 10);
908*32172Sedward     CommentFont = DefineFont (COMMENTFONT, 10);
909*32172Sedward     LiteralFont = DefineFont (LITERALFONT, 11);
910*32172Sedward 
911*32172Sedward     /* process args in environment variable PSGRIND */
912*32172Sedward     if (p = getenv ("PSGRIND"))
913*32172Sedward 	while (1) {
914*32172Sedward 	    register char   quote = ' ';
915*32172Sedward 	    while (*p == ' ')
916*32172Sedward 		p++;
917*32172Sedward 	    if (*p == '"' || *p == '\'')
918*32172Sedward 		quote = *p++;
919*32172Sedward 	    arg = p;
920*32172Sedward 	    while (*p != quote && *p != '\0')
921*32172Sedward 		p++;
922*32172Sedward 	    if (*p == '\0') {
923*32172Sedward 		if (*arg)
924*32172Sedward 		    ProcessArg (arg);
925*32172Sedward 		break;
926*32172Sedward 	    }
927*32172Sedward 	    *p++ = '\0';
928*32172Sedward 	    ProcessArg (arg);
929*32172Sedward 	}
930*32172Sedward 
931*32172Sedward     /* process the command line arguments */
932*32172Sedward     while (argc > 1) {
933*32172Sedward 	argc--;
934*32172Sedward 	ProcessArg (*++argv);
935*32172Sedward     }
936*32172Sedward 
937*32172Sedward     if (!SeenFile) {
938*32172Sedward 	FileName = Header = 0;
939*32172Sedward 	FileDate = "";
940*32172Sedward 	fstat (fileno (stdin), &S);
941*32172Sedward 
942*32172Sedward 	if ((S.st_mode & S_IFMT) == S_IFREG)
943*32172Sedward 	    FileDate = strcpy(DateStr, ctime (&S.st_mtime));
944*32172Sedward 	CopyFile ();
945*32172Sedward     }
946*32172Sedward 
947*32172Sedward     if (Cvted) {
948*32172Sedward 	ClosePS ();
949*32172Sedward 	fclose (OutFile);
950*32172Sedward 	OutFile = 0;
951*32172Sedward     }
952*32172Sedward     if (TruncChars)
953*32172Sedward 	printf ("%d characters omitted because of long lines.\n",
954*32172Sedward 		TruncChars);
955*32172Sedward     if (UndefChars)
956*32172Sedward 	printf ("%d characters omitted because of incomplete fonts.\n",
957*32172Sedward 		UndefChars);
958*32172Sedward /*  PageMessage (TotalPages); */
959*32172Sedward     if (Cvted) {
960*32172Sedward 	if (OutOnly) {
961*32172Sedward 	    if (Reverse || PageSpec) {
962*32172Sedward 		char temparg[200];
963*32172Sedward 		char *sargs[200];
964*32172Sedward 		int args = 0;
965*32172Sedward 
966*32172Sedward 		int cpid = 0;
967*32172Sedward 		/* feed Temporary through psrev */
968*32172Sedward 		freopen(TempName, "r", stdin);
969*32172Sedward 		if (!PipeOut) freopen(OutName, "w", stdout);
970*32172Sedward 		unlink(TempName);
971*32172Sedward 
972*32172Sedward 		addarg(sargs, REVERSE, &args);
973*32172Sedward 		addarg(sargs, "-r", &args);
974*32172Sedward 		if (!Reverse) addarg(sargs, "-R", &args);
975*32172Sedward 
976*32172Sedward 		if (PageSpec) {
977*32172Sedward 		    sprintf(temparg,"-s%s",PageSpec);
978*32172Sedward 		    addarg(sargs, temparg, &args);
979*32172Sedward 		}
980*32172Sedward 		if ((cpid = fork()) < 0) pexit(prog,1);
981*32172Sedward 		if (cpid == 0) {
982*32172Sedward 		    execvp(REVERSE, sargs);
983*32172Sedward 		    pexit(prog,1);
984*32172Sedward 		}
985*32172Sedward 		else {
986*32172Sedward 		    wait(0);
987*32172Sedward 		}
988*32172Sedward 	    }
989*32172Sedward 	  /*  fprintf (stderr,"PS file left on %s\n", OutName); */
990*32172Sedward 	}
991*32172Sedward 	else
992*32172Sedward 	    SpoolIt();
993*32172Sedward     }
994*32172Sedward }
995*32172Sedward 
996*32172Sedward private addarg(argv, argstr, argc)
997*32172Sedward char **argv;
998*32172Sedward char *argstr;
999*32172Sedward register int *argc;
1000*32172Sedward {
1001*32172Sedward     register char *p = (char *) malloc (strlen(argstr) + 1);
1002*32172Sedward     strcpy (p, argstr);
1003*32172Sedward     argv[(*argc)++] = p;
1004*32172Sedward     argv[*argc] = '\0';
1005*32172Sedward }
1006*32172Sedward 
1007*32172Sedward private SpoolIt()
1008*32172Sedward {
1009*32172Sedward     char temparg[200];
1010*32172Sedward     char *argstr[200];
1011*32172Sedward     int nargs = 0;
1012*32172Sedward 
1013*32172Sedward     char *rargs[40];
1014*32172Sedward     int  nr = 0;
1015*32172Sedward     int cpid =0;
1016*32172Sedward     int fdpipe[2];
1017*32172Sedward 
1018*32172Sedward     addarg(argstr, LPR, &nargs);
1019*32172Sedward     if (spoolCopies > 1) {
1020*32172Sedward 	sprintf(temparg,"-#%d",spoolCopies);
1021*32172Sedward 	addarg(argstr, temparg, &nargs);
1022*32172Sedward     }
1023*32172Sedward     if (PrinterName) {
1024*32172Sedward 	sprintf(temparg,"-P%s",PrinterName);
1025*32172Sedward 	addarg(argstr, temparg, &nargs);
1026*32172Sedward     }
1027*32172Sedward     else if (getenv("PRINTER") == 0) {
1028*32172Sedward 	/* no printer name known anywhere, use default */
1029*32172Sedward 	sprintf(temparg,"-P%s",POSTSCRIPTPRINTER);
1030*32172Sedward 	addarg(argstr, temparg, &nargs);
1031*32172Sedward     }
1032*32172Sedward     if (spoolJobClass) {
1033*32172Sedward 	addarg(argstr, "-C", &nargs);
1034*32172Sedward 	addarg(argstr, spoolJobClass, &nargs);
1035*32172Sedward     }
1036*32172Sedward     addarg(argstr, "-J", &nargs);
1037*32172Sedward     if (spoolJobName) {
1038*32172Sedward 	addarg(argstr, spoolJobName, &nargs);
1039*32172Sedward     }
1040*32172Sedward     else {
1041*32172Sedward 	if (!FileName) addarg(argstr, "stdin", &nargs);
1042*32172Sedward 	else addarg(argstr, FileName, &nargs);
1043*32172Sedward     }
1044*32172Sedward     if (spoolNotify) {
1045*32172Sedward 	addarg(argstr, "-m", &nargs);
1046*32172Sedward     }
1047*32172Sedward     if (spoolNoBurst) {
1048*32172Sedward 	addarg(argstr, "-h", &nargs);
1049*32172Sedward     }
1050*32172Sedward 
1051*32172Sedward     if (Reverse || PageSpec) {
1052*32172Sedward 	/* lpr input will be stdin */
1053*32172Sedward 
1054*32172Sedward 	addarg(rargs, REVERSE, &nr);
1055*32172Sedward 	addarg(rargs, "-r", &nr);
1056*32172Sedward 	if (!Reverse) addarg(rargs, "-R", &nr);
1057*32172Sedward 	if (PageSpec) {
1058*32172Sedward 	    sprintf(temparg,"-s%s",PageSpec);
1059*32172Sedward 	    addarg(rargs, temparg, &nr);
1060*32172Sedward         }
1061*32172Sedward /*	addarg(rargs, TempName, &nr); */
1062*32172Sedward 
1063*32172Sedward 	freopen(TempName,"r",stdin);
1064*32172Sedward 	unlink(TempName);
1065*32172Sedward 	if (pipe(fdpipe)) pexit(prog,1);
1066*32172Sedward 	if ((cpid = fork()) < 0) pexit(prog,1);
1067*32172Sedward 	else if (!cpid) { /* child */
1068*32172Sedward 	    if (close(1)) {
1069*32172Sedward 		pexit(prog,1);
1070*32172Sedward 	    }
1071*32172Sedward 	    /* set stdout to be the output pipe */
1072*32172Sedward 	    if (dup (fdpipe[1]) == -1) {
1073*32172Sedward 		pexit(prog,1);
1074*32172Sedward 	    }
1075*32172Sedward 	    /* don't want to read or write the pipe itself, since dup */
1076*32172Sedward 	    if (close (fdpipe[1]) || close (fdpipe[0])) {
1077*32172Sedward 		pexit(prog,1);
1078*32172Sedward 	    }
1079*32172Sedward 	    /* leave stderr alone */
1080*32172Sedward 	    execvp (REVERSE, rargs);
1081*32172Sedward 	    pexit(prog,1);
1082*32172Sedward 	}
1083*32172Sedward 	else {
1084*32172Sedward 	    /* parent */
1085*32172Sedward 	    /* replace stdin with pipe */
1086*32172Sedward 	    if (close(0)) {
1087*32172Sedward 		pexit(prog,1);
1088*32172Sedward 	    }
1089*32172Sedward 
1090*32172Sedward 	    if (dup(fdpipe[0]) == -1) {
1091*32172Sedward 		pexit(prog,1);
1092*32172Sedward 	    }
1093*32172Sedward 	    if (close (fdpipe[0]) || close (fdpipe[1])) {
1094*32172Sedward 		pexit(prog,1);
1095*32172Sedward 	    }
1096*32172Sedward 
1097*32172Sedward 	    /* leave stdout and stderr alone */
1098*32172Sedward 	    execvp(LPR, argstr);
1099*32172Sedward 	    pexit(prog,1);
1100*32172Sedward 	}
1101*32172Sedward     }
1102*32172Sedward     else { /* just do lpr */
1103*32172Sedward 	/* remove the temporary file after spooling */
1104*32172Sedward 	addarg(argstr, "-r", &nargs); /* should we use a symbolic link too? */
1105*32172Sedward 	addarg(argstr, TempName, &nargs);
1106*32172Sedward 	execvp(LPR, argstr);
1107*32172Sedward 	pexit(prog,1);
1108*32172Sedward     }
1109*32172Sedward }
1110*32172Sedward 
1111*32172Sedward char *
1112*32172Sedward basename(path)
1113*32172Sedward 	char	*path;
1114*32172Sedward {
1115*32172Sedward 	register char	*cp;
1116*32172Sedward 
1117*32172Sedward 	for (cp = path; *cp != '\0'; cp++)
1118*32172Sedward 		;
1119*32172Sedward 	for (--cp; cp > path && *cp != '/'; cp--)
1120*32172Sedward 		;
1121*32172Sedward 	if (*cp == '/' && *(cp+1) != '\0')
1122*32172Sedward 		return (cp + 1);
1123*32172Sedward 	else
1124*32172Sedward 		return (path);
1125*32172Sedward }
1126