xref: /csrg-svn/local/transcript/src/psgrind.c (revision 45864)
1*45864Skarels /*	@(#)psgrind.c	1.3 12/31/90	*/
232172Sedward /*
332172Sedward  *  psgrind - quick hack to grind C source files directly into
432172Sedward  *  PostScript.
532172Sedward  *
632172Sedward  *  John Coker
732172Sedward  *  University of California, Berkeley
832172Sedward  *
932172Sedward  *  The basis for this program is the enscript utility provided
1032172Sedward  *  by TranScript to driver the Apple LaserWriter printer.  This
1132172Sedward  *  code was taken and mangled without permission of any kind;
1232172Sedward  *  don't tell anyone.  -john
1332172Sedward  */
1432172Sedward 
1532172Sedward #define POSTSCRIPTPRINTER "gp"
1632172Sedward 
1732172Sedward #define HEADERFONT	"Helvetica-Bold"
1832172Sedward #define BODYFONT 	"Helvetica"
1932172Sedward #define KWORDFONT 	"Helvetica-Bold"
2032172Sedward #define COMMENTFONT	"Helvetica-Oblique"
2132172Sedward #define LITERALFONT  	"Courier"
2232172Sedward 
2332172Sedward #ifndef PSGRINDPRO
2432172Sedward #define PSGRINDPRO	"/psgrind.pro"
2532172Sedward #endif !PSGRINDPRO
2632172Sedward 
2732172Sedward #ifndef PSGRINDTEMP
2832172Sedward #define PSGRINDTEMP	"/GRXXXXXX"
2932172Sedward #endif !PSGRINDTEMP
3032172Sedward 
3132172Sedward #define UperInch 1440
3232172Sedward #define PtsPerInch 72
3332172Sedward #define UperPt 20
3432172Sedward #define TruePageWidth  (UperInch*17/2)
35*45864Skarels #define PageWidth  (UperInch*(4*17-3)/8)
3632172Sedward #define PageLength (UperInch*(8*11-3)/8)
3732172Sedward #define TruePageLength (UperInch*11)
3832172Sedward 
3932172Sedward #include <stdio.h>
4032172Sedward #include <ctype.h>
4132172Sedward #include <strings.h>
4232172Sedward #include <pwd.h>
4332172Sedward #include <sys/types.h>
4432172Sedward #include <sys/stat.h>
4532172Sedward #include "transcript.h"
4632172Sedward 
4732172Sedward #define LPR "lpr"
4832172Sedward #define REVERSE "psrev"
4932172Sedward 
5032172Sedward #define MAXBAD 20	/* number of bad chars to pass before complaint */
5132172Sedward 
5232172Sedward private struct stat S;
5332172Sedward char   *ctime ();
5432172Sedward char   *getenv ();
5532172Sedward char   *rindex ();
5632172Sedward 
5732172Sedward #define FSIZEMAX 256		/* number of chars per font */
5832172Sedward 
5932172Sedward /* the layout of a font information block */
6032172Sedward struct font {
6132172Sedward     char    name[100];		/* PostScript font name */
6232172Sedward     int     dsize;		/* size */
6332172Sedward     int     Xwid[FSIZEMAX];	/* X widths for each character */
6432172Sedward };
6532172Sedward 
6632172Sedward private struct font fonts[16];		/* 16 possible fonts at one time */
6732172Sedward private int nf = 0;			/* number of fonts known about */
6832172Sedward 
6932172Sedward private int HeaderFont = -1;		/* handle for header font */
7032172Sedward private int BodyFont = -1;		/* handle for body font */
7132172Sedward private int KwordFont = -1;		/* handle for keyword font */
7232172Sedward private int LiteralFont = -1;		/* handle for literal font */
7332172Sedward private int CommentFont = -1;		/* handle for comment font */
7432172Sedward 
7532172Sedward private int TabWidth = TruePageWidth / 10;	/* width of a tab */
7632172Sedward private int BSWidth;				/* width of a backspace */
7732172Sedward 
7832172Sedward private int UperLine = UperInch / 7;
7932172Sedward private int UperHLine = UperInch / 7;
8032172Sedward 
8132172Sedward private char *prog;		/* program name argv[0] */
8232172Sedward private char TempName[100];	/* name of temporary PostScript file */
8332172Sedward private char OutName[256] = 0;	/* filename for disk output */
8432172Sedward private int PipeOut = 0;	/* true if output to stdout (-p -) */
8532172Sedward private int ListOmitted = 0;	/* list omitted chars on the tty */
8632172Sedward private int LPTsimulate = 0;	/* true if an lpt should be simulated */
8732172Sedward private int LinesLeft = 64;	/* lines left on page when in LPT mode */
88*45864Skarels private int col;		/* column number on current line */
8932172Sedward private int LineNo;		/* line number in current file */
9032172Sedward private int SeenText = 1;	/* true if seen some text on this page */
9132172Sedward private int OutOnly = 0;	/* true if PS file only wanted */
9232172Sedward private int Rotated = 0;	/* true if the page is to be rotated */
9332172Sedward private int Reverse = 0;	/* output should be piped to psrev */
9432172Sedward private char *PageSpec = 0;	/* ditto */
9532172Sedward private int PreFeed = 0;	/* true if prefeed should be enabled */
9632172Sedward private int TwoColumn = 0;	/* true of if in two-column mode */
9732172Sedward private int FirstCol = 1;	/* true if we're printing column 1 */
9832172Sedward private int NoTitle = 0;	/* true if title line is to be suppressed */
9932172Sedward private int Cvted = 0;		/* true if converted a file to PS format */
10032172Sedward 
10132172Sedward private int IgnoreGarbage = 0;	/* true if garbage should be ignored */
10232172Sedward private int SeenFile = 0;	/* true if a file has been processed */
10332172Sedward private int SeenFont = 0;	/* true if we've seen a font request */
10432172Sedward private int ScannedFonts = 0;	/* true if we've scanned the font file */
10532172Sedward private char *FileName = 0;	/* name of file currently being PSed */
10632172Sedward private char *FileDate = 0;	/* last mod date of file being PSed */
10732172Sedward private char DateStr[27];	/* thanks, but no thanks ctime! */
10832172Sedward 
10932172Sedward private char *spoolJobClass = 0;
11032172Sedward private char *spoolJobName = 0;
11132172Sedward private char *PrinterName = 0;
11232172Sedward private int spoolNotify = 0;
11332172Sedward private int spoolNoBurst = 0;
11432172Sedward private int spoolCopies = 1;
11532172Sedward 
11632172Sedward private char tempstr[256];	/* various path names */
11732172Sedward 
11832172Sedward private int CurFont;		/* current Font */
11932172Sedward private int LastFont;		/* previous Font */
12032172Sedward 
12132172Sedward private int cX, cY;		/* current page positions */
12232172Sedward private int dX, dY;		/* desired page positions */
12332172Sedward private int lX, lY;		/* page positions of the start of the line */
12432172Sedward private int crX, crY;		/* X and Y increments to apply to CR's */
12532172Sedward 
12632172Sedward #define None	0
12732172Sedward #define RelX	1
12832172Sedward #define	RelY	2
12932172Sedward #define RelXY	3
13032172Sedward #define AbsX	4
13132172Sedward #define AbsY	8
13232172Sedward #define AbsXY	12
13332172Sedward 
13432172Sedward private int movepending;	/* moveto pending coords on stack */
13532172Sedward private int showpending;	/* number of characters waiting to be shown */
13632172Sedward private char *UsersHeader = 0;	/* user specified heading */
13732172Sedward private char *Header = 0;	/* generated header (usually FileName) */
13832172Sedward private int Page = 0;		/* current page number */
13932172Sedward private int TotalPages = 0;	/* total number of pages printed */
14032172Sedward private int TruncChars = 0;	/* number of characters truncated */
14132172Sedward private int UndefChars = 0;	/* number of characters skipped because
14232172Sedward 				   they weren't defined in some font */
14332172Sedward private int BadChars   = 0;	/* number of bad characters seen so far */
14432172Sedward 
14532172Sedward private FILE *OutFile = 0;	/* output ps file */
14632172Sedward 
14732172Sedward /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */
decodefont(name,f)14832172Sedward private decodefont (name, f)
14932172Sedward register char  *name;
15032172Sedward register struct font *f; {
15132172Sedward     register char *d, *p;
15232172Sedward 
15332172Sedward     SeenFont++;
15432172Sedward     if (ScannedFonts) {
15532172Sedward 	fprintf(stderr,"Fonts must be specified before any files are processed\n");
15632172Sedward 	exit(1);
15732172Sedward     }
15832172Sedward     p = name;
15932172Sedward     d = f->name;
16032172Sedward     while (isascii(*p) && (isalpha(*p) || (*p == '-'))) {*d++ = *p++;}
16132172Sedward     *d++ = '\0';
16232172Sedward     if (isascii(*p) && isdigit(*p)) {
16332172Sedward 	f->dsize = 0;
16432172Sedward 	do
16532172Sedward 	    f->dsize = f->dsize * 10 + *p++ - '0';
16632172Sedward 	while ('0' <= *p && *p <= '9');
16732172Sedward     }
16832172Sedward     if (*p || !f->dsize || !f->name[0]) {
16932172Sedward 	fprintf (stderr, "Poorly formed font name: \"%s\"\n", name);
17032172Sedward 	exit (1);
17132172Sedward     }
17232172Sedward }
17332172Sedward 
17432172Sedward 
17532172Sedward #define NOTDEF 0x8000
17632172Sedward #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--)
17732172Sedward 
17832172Sedward /* Scan the font metrics directory looking for entries that match the
17932172Sedward  * entries in ``fonts''.  For entries
18032172Sedward  * that are found the data in the font description is filled in,
18132172Sedward  * if any are missing, it dies horribly.
18232172Sedward  */
ScanFont()18332172Sedward private ScanFont () {
18432172Sedward     register struct font   *f;
18532172Sedward     register FILE *FontData;		/* afm file */
18632172Sedward     char    *c;
18732172Sedward     int     ccode, cwidth, inChars;
18832172Sedward     char   *MetricsDir = (char *) getenv ("METRICS");
18932172Sedward     char    FontFile[512];		/* afm file name */
19032172Sedward     char    afmbuf[BUFSIZ];
19132172Sedward 
19232172Sedward     if (MetricsDir == 0)
19332172Sedward 	MetricsDir = LibDir;
19432172Sedward 
19532172Sedward     if (!SeenFont & Rotated & TwoColumn) {
19632172Sedward 	fonts[HeaderFont].dsize = 10;
19732172Sedward 	fonts[BodyFont].dsize = 7;
19832172Sedward 	fonts[KwordFont].dsize = 7;
19932172Sedward 	fonts[LiteralFont].dsize = 8;
20032172Sedward 	fonts[CommentFont].dsize = 7;
20132172Sedward     }
20232172Sedward 
20332172Sedward     /* loop through fonts, find and read metric entry in dir */
20432172Sedward     ForAllFonts (f) {
20532172Sedward 	mstrcat(FontFile, MetricsDir, "/", sizeof FontFile);
20632172Sedward 	mstrcat(FontFile, FontFile, f->name, sizeof FontFile);
20732172Sedward 	mstrcat(FontFile, FontFile, ".afm", sizeof FontFile);
20832172Sedward 	if ((FontData = fopen(FontFile,"r")) == NULL){
20932172Sedward 	    fprintf(stderr,"Can't open font metrics file %s\n",FontFile);
21032172Sedward 	    exit(1);
21132172Sedward 	}
21232172Sedward 	/* read the .afm file to get the widths */
21332172Sedward 	for (ccode = 0; ccode < FSIZEMAX; ccode++) f->Xwid[ccode] = NOTDEF;
21432172Sedward 
21532172Sedward 	inChars = 0;
21632172Sedward 	while(fgets(afmbuf, sizeof afmbuf, FontData) != NULL) {
21732172Sedward 	    /* strip off newline */
21832172Sedward 	    if ((c = index(afmbuf, '\n')) == 0) {
21932172Sedward 		fprintf(stderr, "AFM file %s line too long %s\n", FontFile, afmbuf);
22032172Sedward 		exit(1);
22132172Sedward 	    }
22232172Sedward 	    *c = '\0';
22332172Sedward 	    if (*afmbuf == '\0') continue;
22432172Sedward 	    if (strcmp(afmbuf, "StartCharMetrics") == 0) {
22532172Sedward 		inChars++;
22632172Sedward 		continue;
22732172Sedward 	    }
22832172Sedward 	    if (strcmp(afmbuf, "EndCharMetrics") == 0) break;
22932172Sedward 	    if (inChars == 1) {
23032172Sedward 		if (sscanf(afmbuf, "C %d ; WX %d ;",&ccode,&cwidth) != 2) {
23132172Sedward 		    fprintf(stderr,"Trouble with AFM file %s\n",FontFile);
23232172Sedward 		    exit(1);
23332172Sedward 		}
23432172Sedward 		/* get out once we see an unencoded char */
23532172Sedward 		if (ccode == -1) break;
23632172Sedward 		if (ccode > 255) continue;
23732172Sedward 		f->Xwid[ccode] = (cwidth * f->dsize * UperPt) / 1000;
23832172Sedward 		continue;
23932172Sedward 	    }
24032172Sedward 	}
24132172Sedward     fclose (FontData);
24232172Sedward     }
24332172Sedward 
24432172Sedward     TabWidth = fonts[BodyFont].Xwid['0'] * 8; /* 8 * figure width */
24532172Sedward     BSWidth = fonts[BodyFont].Xwid[' ']; /* space width */
24632172Sedward 
24732172Sedward     UperLine = (fonts[BodyFont].dsize + 1) * UperPt;
24832172Sedward 
24932172Sedward     if (LPTsimulate)
25032172Sedward 	UperHLine = UperLine;
25132172Sedward     else
25232172Sedward 	UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt;
25332172Sedward 
25432172Sedward     crX = 0;
25532172Sedward     crY = -UperLine;
25632172Sedward }
25732172Sedward 
25832172Sedward /* Return a font number for the font with the indicated name
25932172Sedward  * and size.  Adds info to the font list for the eventual search.
26032172Sedward  */
DefineFont(name,size)26132172Sedward private DefineFont (name, size)
26232172Sedward char   *name; {
26332172Sedward     register struct font   *p;
26432172Sedward     p = &fonts[nf];
26532172Sedward     strcpy (p->name, name);
26632172Sedward     p->dsize = size;
26732172Sedward     return (nf++);
26832172Sedward }
26932172Sedward 
27032172Sedward /* add a shown character to the PS file */
OUTputc(c)27132172Sedward private OUTputc (c)
27232172Sedward unsigned char    c; {
27332172Sedward     if (showpending == 0) {putc('(', OutFile); showpending++;}
27432172Sedward     if (c == '\\' || c=='(' || c == ')') putc('\\', OutFile);
27532172Sedward     if ((c > 0176) || (c < 040)) {
27632172Sedward 	putc('\\',OutFile);
27732172Sedward 	putc((c >> 6) +'0',OutFile);
27832172Sedward 	putc(((c >> 3) & 07)+'0', OutFile);
27932172Sedward 	putc((c & 07)+'0',OutFile);
28032172Sedward     }
28132172Sedward     else putc (c, OutFile);
28232172Sedward }
28332172Sedward 
28432172Sedward /* Set the current font */
SetFont(f)28532172Sedward private SetFont (f) {
28632172Sedward     FlushShow();
28732172Sedward     LastFont = CurFont;
28832172Sedward     fprintf(OutFile, "%d F\n", CurFont = f);
28932172Sedward }
29032172Sedward 
29132172Sedward /* Reset to previous font */
PrevFont()29232172Sedward private PrevFont () {
29332172Sedward     int	temp;
29432172Sedward 
29532172Sedward     FlushShow();
29632172Sedward     temp = CurFont;
29732172Sedward     CurFont = LastFont;
29832172Sedward     LastFont = temp;
29932172Sedward     fprintf(OutFile, "%d F\n", CurFont);
30032172Sedward }
30132172Sedward 
30232172Sedward /* put a character onto the page at the desired X and Y positions.
30332172Sedward  * If the current position doesn't agree with the desired position, put out
30432172Sedward  * movement directives.  Leave the current position updated
30532172Sedward  * to account for the character.
30632172Sedward  */
ShowChar(c)30732172Sedward private ShowChar (c)
30832172Sedward register int c; {
30932172Sedward     register struct font   *f;
31032172Sedward     register    nX, nY;
31132172Sedward     static level = 0;
31232172Sedward 
31332172Sedward     level++;
31432172Sedward     f = &fonts[CurFont];
31532172Sedward 
31632172Sedward     if (f->Xwid[c] == NOTDEF) {
31732172Sedward 	UndefChars++;
31832172Sedward 	if(ListOmitted)
31932172Sedward 	    printf("\'%c\' (%03o) not found in font %s\n",c,c,f->name);
32032172Sedward 	if(level<=1){
32132172Sedward 	    ShowChar('\\');
32232172Sedward 	    ShowChar((c>>6)+'0');
32332172Sedward 	    ShowChar(((c>>3)&07)+'0');
32432172Sedward 	    ShowChar((c&07)+'0');
32532172Sedward 	}
32632172Sedward 	level--;
32732172Sedward 	return;
32832172Sedward     }
32932172Sedward     nX = dX + f->Xwid[c]; /* resulting position after showing this char */
33032172Sedward     nY = dY;
33132172Sedward 
332*45864Skarels     if (c != ' ' || ((cX == dX) && (cY == dY))) {
333*45864Skarels 	    /*
334*45864Skarels 	     * If character doesn't fit on this line
335*45864Skarels 	     * (and we're not at left margin), simulate newline
336*45864Skarels 	     * and then call ourselves recursively.
337*45864Skarels 	     */
338*45864Skarels 	    if (((!Rotated && nX > PageWidth)
339*45864Skarels 	        || (Rotated && nX > PageLength)) &&
340*45864Skarels 	        dX > lX) {
341*45864Skarels 		    LineNo++;
342*45864Skarels 		    SeenText++;
343*45864Skarels 		    dY = lY = lY + crY;
344*45864Skarels 		    dX = lX = lX + crX;
345*45864Skarels 		    if (((!Rotated) && (dY < UperLine))
346*45864Skarels 		        || (Rotated && (dY < ((PageLength-TruePageWidth) +
347*45864Skarels 						3*UperLine+480)))
348*45864Skarels 		        || (LPTsimulate && (--LinesLeft <= 0)))
349*45864Skarels 			    PageEject ();
350*45864Skarels 		    col = 1;
351*45864Skarels 		    ShowChar(c);
352*45864Skarels 		    level--;
353*45864Skarels 		    return;
354*45864Skarels 	    }
35532172Sedward 	    if (cX != dX) {
35632172Sedward 	       if (cY != dY) {
35732172Sedward 		  FlushShow();
35832172Sedward 		  /* absolute x, relative y */
35932172Sedward 		  fprintf(OutFile,"%d %d",dX, dY);
36032172Sedward 		  movepending = AbsXY;
36132172Sedward 		  }
36232172Sedward 	       else {
36332172Sedward 		  FlushShow();
36432172Sedward 		  fprintf(OutFile,"%d",dX-cX); /* relative x */
36532172Sedward 		  movepending = RelX;
36632172Sedward 		  }
36732172Sedward 	    }
36832172Sedward 	    else if (cY != dY) {
36932172Sedward 		FlushShow();
37032172Sedward 		fprintf(OutFile,"%d",dY-cY); /* relative y */
37132172Sedward 		movepending = RelY;
37232172Sedward 		}
37332172Sedward 	    OUTputc (c);
37432172Sedward 	    showpending++;
37532172Sedward 	    cX = nX;
37632172Sedward 	    cY = nY;
37732172Sedward 	}
37832172Sedward     dX = nX;
37932172Sedward     dY = nY;
38032172Sedward 
38132172Sedward     level--;
38232172Sedward }
38332172Sedward 
38432172Sedward /* put out a shown string to the PS file */
ShowStr(s)38532172Sedward private ShowStr (s)
38632172Sedward register char  *s; {
38732172Sedward     while (*s) {
38832172Sedward 	if (*s >= 040) ShowChar (*s);
38932172Sedward 	s++;
39032172Sedward     }
39132172Sedward }
39232172Sedward 
39332172Sedward /* flush pending show */
FlushShow()39432172Sedward private FlushShow() {
39532172Sedward     if (showpending) {
39632172Sedward        putc(')',OutFile);
39732172Sedward 	switch (movepending) {
39832172Sedward 	    case RelX:
39932172Sedward 		putc('X',OutFile);
40032172Sedward 		break;
40132172Sedward 	    case RelY:
40232172Sedward 	    	putc('Y',OutFile);
40332172Sedward 		break;
40432172Sedward 	    case AbsXY:
40532172Sedward 	    	putc('B',OutFile);
40632172Sedward 		break;
40732172Sedward 	    case None:
40832172Sedward 	    	putc('S',OutFile);
40932172Sedward 	    	break;
41032172Sedward 	}
41132172Sedward 	putc('\n',OutFile);
41232172Sedward 	movepending = None;
41332172Sedward 	showpending = 0;
41432172Sedward     }
41532172Sedward }
41632172Sedward 
41732172Sedward /* put out a page heading to the PS file */
InitPage()41832172Sedward private InitPage () {
41932172Sedward     char    *basename();
42032172Sedward     char    header[200];
42132172Sedward     register int  OldFont = CurFont;
42232172Sedward 
42332172Sedward     TotalPages++;
42432172Sedward     fprintf(OutFile, "%%%%Page: ? %d\n", TotalPages);
42532172Sedward     fprintf(OutFile, "StartPage\n");
42632172Sedward     LinesLeft = 64;
42732172Sedward     SeenText = 0;
42832172Sedward     cX = cY = -1;
42932172Sedward     showpending = 0;
43032172Sedward     FirstCol = 1;
43132172Sedward     lX = dX = UperInch;
43232172Sedward     lY = dY = PageLength - UperHLine * 3 / 2;
43332172Sedward     if (Rotated) {
43432172Sedward         fprintf(OutFile, "Landscape\n");
43532172Sedward 	lX = dX = UperInch / 4;
43632172Sedward     }
43732172Sedward     movepending = None;
43832172Sedward     cX = dX; cY = dY;
43932172Sedward     if (!NoTitle) {
44032172Sedward 	SetFont (HeaderFont);
44132172Sedward         fprintf(OutFile, "%d %d ", cX, cY);
44232172Sedward         movepending = AbsXY;
44332172Sedward 	if (UsersHeader) {
44432172Sedward 	    if (*UsersHeader == 0) {
44532172Sedward 		fprintf(OutFile,"()B\n");
44632172Sedward 		movepending = None;
44732172Sedward 		showpending = 0;
44832172Sedward 	    }
44932172Sedward 	    else ShowStr (UsersHeader);
45032172Sedward 	}
45132172Sedward 	else {
45232172Sedward 	    Page++;
45332172Sedward 	    if (FileName == 0)
45432172Sedward 		    sprintf(header, "Page %d", Page);
45532172Sedward 	    else
45632172Sedward 	    sprintf (header, "%s,  page %d", basename(FileName), Page);
45732172Sedward 	    ShowStr (header);
45832172Sedward 	}
45932172Sedward 	FlushShow();
46032172Sedward 	dX = lX = lX + crX * 3;
46132172Sedward 	dY = lY = lY + crY * 3;
46232172Sedward     }
46332172Sedward     else {
46432172Sedward 	/* fake it to force a moveto */
46532172Sedward 	cX = cY = 0;
46632172Sedward     }
46732172Sedward     SetFont (OldFont);
46832172Sedward }
46932172Sedward 
47032172Sedward /* terminate a page. */
ClosePage()47132172Sedward private ClosePage () {
47232172Sedward     FlushShow();
47332172Sedward     fprintf(OutFile,"EndPage\n");
47432172Sedward }
47532172Sedward 
47632172Sedward /* skip to a new page */
PageEject()47732172Sedward private PageEject () {
47832172Sedward     if (TwoColumn && FirstCol) {
47932172Sedward 	FirstCol = 0;
48032172Sedward 	lX = dX = TruePageWidth / 2;
48132172Sedward 	lY = dY = PageLength - (UperHLine * 3 / 2);
48232172Sedward 	if (Rotated) {
48332172Sedward 	   lX = dX = TruePageLength / 2;
48432172Sedward 	   }
48532172Sedward 	if (!NoTitle) {
48632172Sedward 	    dX = lX = lX + crX * 3;
48732172Sedward 	    dY = lY = lY + crY * 3;
48832172Sedward 	}
48932172Sedward     }
49032172Sedward     else {
49132172Sedward 	ClosePage ();
49232172Sedward 	InitPage ();
49332172Sedward     }
49432172Sedward     LinesLeft = 64;
49532172Sedward     SeenText = 0;
49632172Sedward }
49732172Sedward 
49832172Sedward #if 0
49932172Sedward /* commented out AIS Fri Feb 22 10:00:36 1985 */
50032172Sedward private PageMessage (TotalPages)
50132172Sedward {
50232172Sedward     if (TotalPages > 0) {
50332172Sedward 	printf ("psgrind formatted[ %d page%s * %d cop%s ]\n",
50432172Sedward 		TotalPages, TotalPages > 1 ? "s" : "",
50532172Sedward 		spoolCopies, spoolCopies > 1 ? "ies" : "y" );
50632172Sedward     }
50732172Sedward }
50832172Sedward #endif
50932172Sedward 
CommentHeader()51032172Sedward private CommentHeader() {
51132172Sedward     long clock;
51232172Sedward     struct passwd *pswd;
51332172Sedward     char hostname[40];
51432172Sedward     /* copy the file, prepending a new comment header */
51532172Sedward     fprintf(OutFile,"%%!%s\n",COMMENTVERSION);
51632172Sedward     fprintf(OutFile,"%%%%Creator: ");
51732172Sedward     pswd = getpwuid(getuid());
51832172Sedward     gethostname(hostname, (int) sizeof hostname);
51932172Sedward     fprintf(OutFile,"%s:%s (%s)%s\n", hostname, pswd->pw_name,
52032172Sedward     	pswd->pw_gecos, spoolJobClass);
52132172Sedward 
52232172Sedward     fprintf(OutFile,"%%%%Title: %s %s\n",
52332172Sedward     	(FileName?FileName:"stdin"),
52432172Sedward 	spoolJobName);
52532172Sedward 
52632172Sedward     fprintf(OutFile,"%%%%CreationDate: %s",(time(&clock),ctime(&clock)));
52732172Sedward }
52832172Sedward 
52932172Sedward 
53032172Sedward /* list of C keywords to put in KwordFont */
53132172Sedward private char *KeyWordList[] = {
53232180Sedward     "asm", "auto", "break", "case", "char", "continue", "default", "do",
53332180Sedward     "double", "else", "entry", "enum", "extern", "float", "for", "fortran",
53432180Sedward     "goto", "if", "int", "long", "register", "return", "short", "sizeof",
53532180Sedward     "static", "struct", "switch", "typedef", "union", "unsigned", "void",
53632180Sedward     "while", NULL
53732172Sedward };
53832172Sedward 
53932172Sedward /* macros identifying C identifiers */
54032172Sedward #define isfirst(c)	(isalpha(c) || (c) == '_')
54132172Sedward #define isident(c)	(isalnum(c) || (c) == '_')
54232172Sedward 
54332172Sedward /* Copy the standard input file to the PS file */
CopyFile()54432172Sedward private CopyFile () {
54532172Sedward     register int   c, last;
54632172Sedward     int	InComment, InString, InChar, IsKword;
54732172Sedward     char token[50], *tend = token + sizeof (token) - 1;
54832172Sedward     register char *tp, **kwp;
54932172Sedward 
550*45864Skarels     col = 1;
55132172Sedward     if (OutFile == 0) {
55232172Sedward 	if (OutOnly && !(PageSpec || Reverse)) {
55332172Sedward 	   OutFile = PipeOut ? stdout : fopen(OutName,"w");
55432172Sedward 	}
55532172Sedward 	else {
55632172Sedward 	    mktemp(mstrcat(TempName,TempDir,PSGRINDTEMP,sizeof TempName));
55732172Sedward 	    OutFile = fopen (TempName, "w");
55832172Sedward 	}
55932172Sedward     }
56032172Sedward     if (OutFile == NULL) {
56132172Sedward 	fprintf(stderr, "Can't create PS file %s\n",TempName);
56232172Sedward 	exit(1);
56332172Sedward     }
56432172Sedward     if (!ScannedFonts) {
56532172Sedward 	ScannedFonts++;
56632172Sedward 	ScanFont();
56732172Sedward     }
56832172Sedward     if (!Cvted) {
56932172Sedward 	CommentHeader();
57032172Sedward 	if (nf) {
57132172Sedward 	    register struct font *f;
57232172Sedward 	    fprintf(OutFile,"%%%%DocumentFonts:");
57332172Sedward  	    ForAllFonts(f) {
57432172Sedward 		fprintf(OutFile," %s",f->name);
57532172Sedward 	    }
57632172Sedward 	    fprintf(OutFile,"\n");
57732172Sedward 	}
57832172Sedward 	/* copy in fixed prolog */
57932172Sedward 	if (copyfile(mstrcat(tempstr,LibDir,PSGRINDPRO,sizeof tempstr),
58032172Sedward 		OutFile)) {
58132172Sedward 	    fprintf(stderr,"trouble copying prolog file \"%s\".\n",tempstr);
58232172Sedward 	    exit(1);
58332172Sedward 	}
58432172Sedward 	fprintf(OutFile,"StartEnscriptDoc %% end fixed prolog\n");
58532172Sedward 	DumpFonts();
58632172Sedward 	fprintf(OutFile,"%%%%EndProlog\n");
58732172Sedward 	if (PreFeed) {
58832172Sedward 	    fprintf(OutFile,"true DoPreFeed\n");
58932172Sedward 	}
59032172Sedward     }
59132172Sedward     Cvted++;
59232172Sedward 
59332172Sedward     Page = 0;
59432172Sedward     LineNo = 1;
59532172Sedward     BadChars = 0;		/* give each file a clean slate */
59632172Sedward     InitPage ();
59732172Sedward     last = '\0';
59832172Sedward     InComment = InChar = InString = 0;
59932172Sedward     while ((c = getchar ()) != EOF) {
60032172Sedward 	if ((c > 0177 || c < 0) && (!IgnoreGarbage)) {
60132172Sedward 	    if (BadChars++ > MAXBAD) {/* allow some kruft but not much */
60232172Sedward 	      fprintf(stderr,"\"%s\" not a text file? - char '\\%03o'@0%o\nTry -g.\n",
60332172Sedward 		    FileName ? FileName : "stdin", c, ftell (stdin) - 1);
60432172Sedward 	      exit(1);
60532172Sedward 	    }
60632172Sedward 	} else {
60732172Sedward 	    switch (c) {
60832172Sedward 		case 010: /* backspace */
60932172Sedward 		    dX -= BSWidth;
61032172Sedward 		    break;
61132172Sedward 		case 015: /* carriage return ^M */
61232172Sedward 		    dY = lY;
61332172Sedward 		    dX = lX;
61432172Sedward 		    break;
61532172Sedward 		case 012: /* linefeed ^J */
61632172Sedward 		    LineNo++;
61732172Sedward 		    if (dX != lX || dY != lY || !LPTsimulate || SeenText){
61832172Sedward 			SeenText++;
61932172Sedward 			dY = lY = lY + crY;
62032172Sedward 			dX = lX = lX + crX;
62132172Sedward 		    }
62232172Sedward 		    else
62332172Sedward 			LinesLeft = 64;
62432172Sedward 		    if (((!Rotated) && (dY < UperLine))
62532172Sedward 		    || (Rotated && (dY < ((PageLength-TruePageWidth) +
62632172Sedward 						3*UperLine+480)))
62732172Sedward 		    || (LPTsimulate && (--LinesLeft <= 0)))
62832172Sedward 			PageEject ();
62932172Sedward 		    col = 1;
63032172Sedward 		    break;
63132172Sedward 		case 014: /* form feed ^L */
63232172Sedward 		    PageEject ();
63332172Sedward 		    col = 1;
63432172Sedward 		    break;
63532172Sedward 		case 011: /* tab ^I */
63632172Sedward 		    col = (col - 1) / 8 * 8 + 9;
637*45864Skarels 		    dX += TabWidth - ((dX - lX) % TabWidth);
63832172Sedward 		    break;
63932172Sedward 	        case '\\': /* special escape */
64032172Sedward 		    last = c;
64132172Sedward 		    if ((c = getchar()) == EOF)
64232172Sedward 			goto done;
64332172Sedward 		    ShowChar('\\');
64432172Sedward 		    col++;
64532172Sedward 		    if (c == '\n') {
64632172Sedward 			/* want to leave newlines alone */
64732172Sedward 			ungetc(c, stdin);
64832172Sedward 		    } else {
64932172Sedward 			ShowChar(c);
65032172Sedward 			col++;
65132172Sedward 		    }
65232172Sedward 		    break;
65332172Sedward 	        case '"': /* a string quote mark */
65432172Sedward 		    if (InComment || InChar) {
65532172Sedward 			/* just put out the quote */
65632172Sedward 			ShowChar('"');
65732172Sedward 			col++;
65832172Sedward 		    } else if (InString) {
65932172Sedward 			ShowChar('"');
66032172Sedward 			col++;
66132172Sedward 			PrevFont();
66232172Sedward 			InString = 0;
66332172Sedward 		    } else {
66432172Sedward 			SetFont(LiteralFont);
66532172Sedward 			ShowChar('"');
66632172Sedward 			col++;
66732172Sedward 			InString = 1;
66832172Sedward 		    }
66932172Sedward 		    break;
67032172Sedward 	        case '\'': /* a char quote mark */
67132172Sedward 		    if (InComment || InString) {
67232172Sedward 			/* just put out the character */
67332172Sedward 			ShowChar('\'');
67432172Sedward 			col++;
67532172Sedward 		    } else if (InChar) {
67632172Sedward 			ShowChar('\'');
67732172Sedward 			col++;
67832172Sedward 			PrevFont();
67932172Sedward 			InChar = 0;
68032172Sedward 		    } else {
68132172Sedward 			SetFont(LiteralFont);
68232172Sedward 			ShowChar('\'');
68332172Sedward 			col++;
68432172Sedward 			InChar = 1;
68532172Sedward 		    }
68632172Sedward 		    break;
68732172Sedward 	        case '/':
68832172Sedward 		    if (InComment && last == '*') {
68932172Sedward 			ShowChar('/');
69032172Sedward 			col++;
69132172Sedward 			SetFont(BodyFont);
69232172Sedward 			InComment = 0;
69332172Sedward 		    } else if ((c = getchar()) == '*' && !InComment) {
69432172Sedward 			SetFont(CommentFont);
69532172Sedward 			InComment = 1;
69632172Sedward 			ShowChar('/');
69732172Sedward 			ShowChar('*');
69832172Sedward 			col += 2;
69932172Sedward 		    } else {
70032172Sedward 			ungetc(c, stdin);
70132172Sedward 			ShowChar('/');
70232172Sedward 			col++;
70332172Sedward 			c = '/';
70432172Sedward 		    }
70532172Sedward 		    break;
70632172Sedward 		default: /* plain text, put it out */
70732172Sedward 		    if (!InComment && !InString && isfirst(c)) {
70832172Sedward 			tp = token;
70932172Sedward 			while (isident(c) && tp < tend) {
71032172Sedward 			    *tp++ = c;
71132172Sedward 			    last = c;
71232172Sedward 			    c = getchar();
71332172Sedward 			}
71432172Sedward 			*tp = '\0';
71532172Sedward 			ungetc(c, stdin);
71632172Sedward 			tp = token;
71732172Sedward 			IsKword = 0;
71832180Sedward 			for (kwp = KeyWordList;
71932180Sedward 			     *kwp != NULL && **kwp <= *tp; kwp++)
72032172Sedward 				if (!strcmp(*kwp, tp)) {
72132172Sedward 					IsKword = 1;
72232172Sedward 					break;
72332172Sedward 				}
72432172Sedward 			if (IsKword)
72532172Sedward 			    SetFont(KwordFont);
72632172Sedward 			ShowStr(tp);
72732172Sedward 			col += strlen(tp);
72832172Sedward 			if (IsKword)
72932172Sedward 			    SetFont(BodyFont);
73032172Sedward 		    } else if (fonts[CurFont].Xwid[c] != NOTDEF) {
73132172Sedward 			/* other normal character */
73232172Sedward 			ShowChar (c);
73332172Sedward 			col++;
73432172Sedward 		    } else { /* not in font, quote it */
73532172Sedward 			ShowChar ('\\');
73632172Sedward 			ShowChar ((c >> 6) + '0');
73732172Sedward 			ShowChar (((c >> 3) & 7) + '0');
73832172Sedward 			ShowChar ((c & 7) + '0');
73932172Sedward 			col += 4;
74032172Sedward 		    }
74132172Sedward 		    break;
74232172Sedward 	     }
74332172Sedward 	}
74432172Sedward 	last = c;
74532172Sedward     }
74632172Sedward 
74732172Sedward done:
74832172Sedward     ClosePage ();
74932172Sedward }
75032172Sedward 
75132172Sedward /* dump the fonts to the PS file for setup */
DumpFonts()75232172Sedward private DumpFonts () {
75332172Sedward     register struct font   *f;
75432172Sedward 
75532172Sedward     ForAllFonts (f) {
75632172Sedward         fprintf(OutFile,"%d %d /%s\n",f-&fonts[0],f->dsize*UperPt,f->name);
75732172Sedward     }
75832172Sedward     fprintf(OutFile, "%d SetUpFonts\n", nf);
75932172Sedward }
76032172Sedward 
76132172Sedward 
76232172Sedward /*
76332172Sedward  * close the PS file
76432172Sedward  */
ClosePS()76532172Sedward private ClosePS () {
76632172Sedward     fprintf(OutFile,"%%%%Trailer\n");
76732172Sedward     if (PreFeed) {
76832172Sedward 	fprintf(OutFile,"false DoPreFeed\n");
76932172Sedward     }
77032172Sedward     fprintf(OutFile,"EndEnscriptDoc\nEnscriptJob restore\n");
77132172Sedward }
77232172Sedward 
ProcessArg(p)77332172Sedward private ProcessArg (p)
77432172Sedward register char  *p; {
77532172Sedward     static  enum State {
77632172Sedward 	normal, PSname,
77732172Sedward 	H_fontname, B_fontname, K_fontname, C_fontname, L_fontname,
77832172Sedward 	grabheader, getclass, getjobname
77932172Sedward     } state = normal;
78032172Sedward 
78132172Sedward     switch (state) {
78232172Sedward 	case PSname:
78332172Sedward 	    strcpy (OutName, p);
78432172Sedward 	    if (strcmp(OutName,"-") == 0) PipeOut++;
78532172Sedward 	    state = normal;
78632172Sedward 	    break;
78732172Sedward 	case H_fontname:
78832172Sedward 	    decodefont (p, &fonts[HeaderFont]);
78932172Sedward 	    state = normal;
79032172Sedward 	    break;
79132172Sedward 	case B_fontname:
79232172Sedward 	    decodefont (p, &fonts[BodyFont]);
79332172Sedward 	    state = normal;
79432172Sedward 	    break;
79532172Sedward 	case K_fontname:
79632172Sedward 	    decodefont (p, &fonts[KwordFont]);
79732172Sedward 	    state = normal;
79832172Sedward 	    break;
79932172Sedward 	case L_fontname:
80032172Sedward 	    decodefont (p, &fonts[LiteralFont]);
80132172Sedward 	    state = normal;
80232172Sedward 	    break;
80332172Sedward 	case C_fontname:
80432172Sedward 	    decodefont (p, &fonts[CommentFont]);
80532172Sedward 	    state = normal;
80632172Sedward 	    break;
80732172Sedward 	case grabheader:
80832172Sedward 	    UsersHeader = p;
80932172Sedward 	    state = normal;
81032172Sedward 	    break;
81132172Sedward 	case getclass:
81232172Sedward 	    spoolJobClass = p;
81332172Sedward 	    state = normal;
81432172Sedward 	    break;
81532172Sedward 	case getjobname:
81632172Sedward 	    spoolJobName = p;
81732172Sedward 	    state = normal;
81832172Sedward 	    break;
81932172Sedward 	default:
82032172Sedward 	    if (*p == '-') while (*++p) switch (*p) {
82132172Sedward 		case '1':
82232172Sedward 		    TwoColumn = 0;
82332172Sedward 		    if (SeenFile) {
82432172Sedward 			fprintf(stderr,"Specify -1 before any files\n");
82532172Sedward 			exit(1);
82632172Sedward 		    }
82732172Sedward 		    break;
82832172Sedward 		case '2':
82932172Sedward 		    TwoColumn++;
83032172Sedward 		    if (SeenFile){
83132172Sedward 			fprintf(stderr,"Specify -2 before any files\n");
83232172Sedward 			exit(1);
83332172Sedward 		    }
83432172Sedward 		    break;
83532172Sedward 		case 'v':
83632172Sedward 		    Reverse = 1;
83732172Sedward 		    break;
83832172Sedward 		case 's':
83932172Sedward 		     PageSpec = (++p);
84032172Sedward 		     while (*p != '\0') p++;
84132172Sedward 		     return;
84232172Sedward 
84332172Sedward 		/* the following options allow uswer specification
84432172Sedward 		   of the five files used by the program */
84532172Sedward 		case 'H': state = H_fontname; break;
84632172Sedward 		case 'B': state = B_fontname; break;
84732172Sedward 		case 'K': state = K_fontname; break;
84832172Sedward 		case 'L': state = L_fontname; break;
84932172Sedward 		case 'C': state = C_fontname; break;
85032172Sedward 
85132172Sedward 		case 'g': IgnoreGarbage++; break;
85232172Sedward 		case 'o': ListOmitted++; break;
85332172Sedward 		case 'p': OutOnly++; state = PSname; break;
85432172Sedward 		case 'r':
85532172Sedward 		    Rotated++;
85632172Sedward 		    if (SeenFile){
85732172Sedward 			fprintf(stderr,"Specify rotation before any files\n");
85832172Sedward 			exit(1);
85932172Sedward 		    }
86032172Sedward 		    break;
86132172Sedward 		case 'R':
86232172Sedward 		    Rotated = 0;
86332172Sedward 		    if (SeenFile){
86432172Sedward 			fprintf(stderr,"Specify rotation before any files\n");
86532172Sedward 			exit(1);
86632172Sedward 		    }
86732172Sedward 		    break;
86832172Sedward 		case 'k':
86932172Sedward 		    PreFeed++;
87032172Sedward 		    if (SeenFile){
87132172Sedward 			fprintf(stderr,"Specify prefeed before any files\n");
87232172Sedward 			exit(1);
87332172Sedward 		    }
87432172Sedward 		    break;
87532172Sedward 
87632172Sedward 		/* the following switches are as in lpr(1) and */
87732172Sedward 		/* are passed through when spooling to a printer */
87832172Sedward 		case 'P': /* printer name */
87932172Sedward 		    PrinterName = (++p);
88032172Sedward 		    while (*p != '\0') p++;
88132172Sedward 		    return;
88232172Sedward 		case 'J': /* job name (title) for the Job: field */
88332172Sedward 		    state = getjobname;
88432172Sedward 		    break;
88532172Sedward 		case 'm': /* notify by mail */
88632172Sedward 		    spoolNotify = 1;
88732172Sedward 		    break;
88832172Sedward 		case 'h':
88932172Sedward 		    spoolNoBurst = 1;
89032172Sedward 		    break;
89132172Sedward 		case '#':
89232172Sedward 		    spoolCopies = atoi(++p);
89332172Sedward 		    if (spoolCopies < 1){
89432172Sedward 		        fprintf(stderr,"Bad argument for -# (number of copies)\n");
89532172Sedward 			exit(1);
89632172Sedward 		    }
89732172Sedward 		    break;
89832172Sedward 
89932172Sedward 		default:
90032172Sedward 		    printf ("Unknown option: %c\n", *p);
90132172Sedward 		    SeenFile++;
90232172Sedward 		    break;
90332172Sedward 		}
90432172Sedward 	    else {/* not a flag -- a filename */
90532172Sedward 		FileName = Header = p;
90632172Sedward 		if (freopen (FileName, "r", stdin) == NULL) {
90732172Sedward 		    printf ("Can't open %s\n", FileName);
90832172Sedward 		    exit (1);
90932172Sedward 		}
91032172Sedward 		fstat (fileno (stdin), &S);
91132172Sedward 		FileDate = strcpy(DateStr,ctime (&S.st_mtime));
91232172Sedward 		CopyFile ();
91332172Sedward 		fclose (stdin);
91432172Sedward 		SeenFile = 1;
91532172Sedward 	    }
91632172Sedward     }
91732172Sedward }
91832172Sedward 
main(argc,argv)91932172Sedward main (argc, argv)
92032172Sedward char  **argv; {
92132172Sedward     register char  *p, *arg;
92232172Sedward 
92332172Sedward     prog = *argv;
92432172Sedward 
92532172Sedward     BodyFont = LastFont = CurFont = DefineFont (BODYFONT, 10);
92632172Sedward     HeaderFont = DefineFont (HEADERFONT, 12);
92732172Sedward     KwordFont = DefineFont (KWORDFONT, 10);
92832172Sedward     CommentFont = DefineFont (COMMENTFONT, 10);
92932172Sedward     LiteralFont = DefineFont (LITERALFONT, 11);
93032172Sedward 
93132172Sedward     /* process args in environment variable PSGRIND */
93232172Sedward     if (p = getenv ("PSGRIND"))
93332172Sedward 	while (1) {
93432172Sedward 	    register char   quote = ' ';
93532172Sedward 	    while (*p == ' ')
93632172Sedward 		p++;
93732172Sedward 	    if (*p == '"' || *p == '\'')
93832172Sedward 		quote = *p++;
93932172Sedward 	    arg = p;
94032172Sedward 	    while (*p != quote && *p != '\0')
94132172Sedward 		p++;
94232172Sedward 	    if (*p == '\0') {
94332172Sedward 		if (*arg)
94432172Sedward 		    ProcessArg (arg);
94532172Sedward 		break;
94632172Sedward 	    }
94732172Sedward 	    *p++ = '\0';
94832172Sedward 	    ProcessArg (arg);
94932172Sedward 	}
95032172Sedward 
95132172Sedward     /* process the command line arguments */
95232172Sedward     while (argc > 1) {
95332172Sedward 	argc--;
95432172Sedward 	ProcessArg (*++argv);
95532172Sedward     }
95632172Sedward 
95732172Sedward     if (!SeenFile) {
95832172Sedward 	FileName = Header = 0;
95932172Sedward 	FileDate = "";
96032172Sedward 	fstat (fileno (stdin), &S);
96132172Sedward 
96232172Sedward 	if ((S.st_mode & S_IFMT) == S_IFREG)
96332172Sedward 	    FileDate = strcpy(DateStr, ctime (&S.st_mtime));
96432172Sedward 	CopyFile ();
96532172Sedward     }
96632172Sedward 
96732172Sedward     if (Cvted) {
96832172Sedward 	ClosePS ();
96932172Sedward 	fclose (OutFile);
97032172Sedward 	OutFile = 0;
97132172Sedward     }
97232172Sedward     if (TruncChars)
97332172Sedward 	printf ("%d characters omitted because of long lines.\n",
97432172Sedward 		TruncChars);
97532172Sedward     if (UndefChars)
97632172Sedward 	printf ("%d characters omitted because of incomplete fonts.\n",
97732172Sedward 		UndefChars);
97832172Sedward /*  PageMessage (TotalPages); */
97932172Sedward     if (Cvted) {
98032172Sedward 	if (OutOnly) {
98132172Sedward 	    if (Reverse || PageSpec) {
98232172Sedward 		char temparg[200];
98332172Sedward 		char *sargs[200];
98432172Sedward 		int args = 0;
98532172Sedward 
98632172Sedward 		int cpid = 0;
98732172Sedward 		/* feed Temporary through psrev */
98832172Sedward 		freopen(TempName, "r", stdin);
98932172Sedward 		if (!PipeOut) freopen(OutName, "w", stdout);
99032172Sedward 		unlink(TempName);
99132172Sedward 
99232172Sedward 		addarg(sargs, REVERSE, &args);
99332172Sedward 		addarg(sargs, "-r", &args);
99432172Sedward 		if (!Reverse) addarg(sargs, "-R", &args);
99532172Sedward 
99632172Sedward 		if (PageSpec) {
99732172Sedward 		    sprintf(temparg,"-s%s",PageSpec);
99832172Sedward 		    addarg(sargs, temparg, &args);
99932172Sedward 		}
100032172Sedward 		if ((cpid = fork()) < 0) pexit(prog,1);
100132172Sedward 		if (cpid == 0) {
100232172Sedward 		    execvp(REVERSE, sargs);
100332172Sedward 		    pexit(prog,1);
100432172Sedward 		}
100532172Sedward 		else {
100632172Sedward 		    wait(0);
100732172Sedward 		}
100832172Sedward 	    }
100932172Sedward 	  /*  fprintf (stderr,"PS file left on %s\n", OutName); */
101032172Sedward 	}
101132172Sedward 	else
101232172Sedward 	    SpoolIt();
101332172Sedward     }
101432172Sedward }
101532172Sedward 
addarg(argv,argstr,argc)101632172Sedward private addarg(argv, argstr, argc)
101732172Sedward char **argv;
101832172Sedward char *argstr;
101932172Sedward register int *argc;
102032172Sedward {
102132172Sedward     register char *p = (char *) malloc (strlen(argstr) + 1);
102232172Sedward     strcpy (p, argstr);
102332172Sedward     argv[(*argc)++] = p;
102432172Sedward     argv[*argc] = '\0';
102532172Sedward }
102632172Sedward 
SpoolIt()102732172Sedward private SpoolIt()
102832172Sedward {
102932172Sedward     char temparg[200];
103032172Sedward     char *argstr[200];
103132172Sedward     int nargs = 0;
103232172Sedward 
103332172Sedward     char *rargs[40];
103432172Sedward     int  nr = 0;
103532172Sedward     int cpid =0;
103632172Sedward     int fdpipe[2];
103732172Sedward 
103832172Sedward     addarg(argstr, LPR, &nargs);
103932172Sedward     if (spoolCopies > 1) {
104032172Sedward 	sprintf(temparg,"-#%d",spoolCopies);
104132172Sedward 	addarg(argstr, temparg, &nargs);
104232172Sedward     }
104332172Sedward     if (PrinterName) {
104432172Sedward 	sprintf(temparg,"-P%s",PrinterName);
104532172Sedward 	addarg(argstr, temparg, &nargs);
104632172Sedward     }
104732172Sedward     else if (getenv("PRINTER") == 0) {
104832172Sedward 	/* no printer name known anywhere, use default */
104932172Sedward 	sprintf(temparg,"-P%s",POSTSCRIPTPRINTER);
105032172Sedward 	addarg(argstr, temparg, &nargs);
105132172Sedward     }
105232172Sedward     if (spoolJobClass) {
105332172Sedward 	addarg(argstr, "-C", &nargs);
105432172Sedward 	addarg(argstr, spoolJobClass, &nargs);
105532172Sedward     }
105632172Sedward     addarg(argstr, "-J", &nargs);
105732172Sedward     if (spoolJobName) {
105832172Sedward 	addarg(argstr, spoolJobName, &nargs);
105932172Sedward     }
106032172Sedward     else {
106132172Sedward 	if (!FileName) addarg(argstr, "stdin", &nargs);
106232172Sedward 	else addarg(argstr, FileName, &nargs);
106332172Sedward     }
106432172Sedward     if (spoolNotify) {
106532172Sedward 	addarg(argstr, "-m", &nargs);
106632172Sedward     }
106732172Sedward     if (spoolNoBurst) {
106832172Sedward 	addarg(argstr, "-h", &nargs);
106932172Sedward     }
107032172Sedward 
107132172Sedward     if (Reverse || PageSpec) {
107232172Sedward 	/* lpr input will be stdin */
107332172Sedward 
107432172Sedward 	addarg(rargs, REVERSE, &nr);
107532172Sedward 	addarg(rargs, "-r", &nr);
107632172Sedward 	if (!Reverse) addarg(rargs, "-R", &nr);
107732172Sedward 	if (PageSpec) {
107832172Sedward 	    sprintf(temparg,"-s%s",PageSpec);
107932172Sedward 	    addarg(rargs, temparg, &nr);
108032172Sedward         }
108132172Sedward /*	addarg(rargs, TempName, &nr); */
108232172Sedward 
108332172Sedward 	freopen(TempName,"r",stdin);
108432172Sedward 	unlink(TempName);
108532172Sedward 	if (pipe(fdpipe)) pexit(prog,1);
108632172Sedward 	if ((cpid = fork()) < 0) pexit(prog,1);
108732172Sedward 	else if (!cpid) { /* child */
108832172Sedward 	    if (close(1)) {
108932172Sedward 		pexit(prog,1);
109032172Sedward 	    }
109132172Sedward 	    /* set stdout to be the output pipe */
109232172Sedward 	    if (dup (fdpipe[1]) == -1) {
109332172Sedward 		pexit(prog,1);
109432172Sedward 	    }
109532172Sedward 	    /* don't want to read or write the pipe itself, since dup */
109632172Sedward 	    if (close (fdpipe[1]) || close (fdpipe[0])) {
109732172Sedward 		pexit(prog,1);
109832172Sedward 	    }
109932172Sedward 	    /* leave stderr alone */
110032172Sedward 	    execvp (REVERSE, rargs);
110132172Sedward 	    pexit(prog,1);
110232172Sedward 	}
110332172Sedward 	else {
110432172Sedward 	    /* parent */
110532172Sedward 	    /* replace stdin with pipe */
110632172Sedward 	    if (close(0)) {
110732172Sedward 		pexit(prog,1);
110832172Sedward 	    }
110932172Sedward 
111032172Sedward 	    if (dup(fdpipe[0]) == -1) {
111132172Sedward 		pexit(prog,1);
111232172Sedward 	    }
111332172Sedward 	    if (close (fdpipe[0]) || close (fdpipe[1])) {
111432172Sedward 		pexit(prog,1);
111532172Sedward 	    }
111632172Sedward 
111732172Sedward 	    /* leave stdout and stderr alone */
111832172Sedward 	    execvp(LPR, argstr);
111932172Sedward 	    pexit(prog,1);
112032172Sedward 	}
112132172Sedward     }
112232172Sedward     else { /* just do lpr */
112332172Sedward 	/* remove the temporary file after spooling */
112432172Sedward 	addarg(argstr, "-r", &nargs); /* should we use a symbolic link too? */
112532172Sedward 	addarg(argstr, TempName, &nargs);
112632172Sedward 	execvp(LPR, argstr);
112732172Sedward 	pexit(prog,1);
112832172Sedward     }
112932172Sedward }
113032172Sedward 
113132172Sedward char *
basename(path)113232172Sedward basename(path)
113332172Sedward 	char	*path;
113432172Sedward {
113532172Sedward 	register char	*cp;
113632172Sedward 
113732172Sedward 	for (cp = path; *cp != '\0'; cp++)
113832172Sedward 		;
113932172Sedward 	for (--cp; cp > path && *cp != '/'; cp--)
114032172Sedward 		;
114132172Sedward 	if (*cp == '/' && *(cp+1) != '\0')
114232172Sedward 		return (cp + 1);
114332172Sedward 	else
114432172Sedward 		return (path);
114532172Sedward }
1146