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