sources-request@mirror.UUCP (07/09/86)
Submitted by: cca!caip!uw-beaver!uw-wally!schwartz (Michael F. Schwartz) Mod.sources: Volume 6, Issue 42 Archive-name: ditrev Documents generated by ditroff(1) come out with page 1 on the bottom and the last page on top when you print them. I got tired of having to manually reverse the pages, so I hacked up a filter that reverses the pages for you. It's simple to use, and runs pretty fast: ditrev [file] outputs to stdout an image like the input, except all the pages are reversed. So, to use this, use something like the following command: troff inputfile -t | ditrev | lpr -n (where the /usr/local/ditroff is before the /bin/troff version in your search path). Note: There is another program called psrev that reverses PostScript file pages (my filter reverses ditroff pages; ditroff output is translated to PostScript before being printed on laserwriters). More about the differences between these programs is described in the man page. - Mike Schwartz University of Washington Computer Science Department ihnp4!uw-beaver!schwartz (USENET) schwartz@wally.arpa (ARPANET) schwartz%wally.arpa@csnet-relay.arpa (CSNET) #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # ditrev.1 # ditrev.c # makefile # This archive created: Fri Jun 27 15:47:59 1986 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'ditrev.1'" '(2762 characters)' if test -f 'ditrev.1' then echo shar: "will not over-write existing file 'ditrev.1'" else sed 's/^ X//' << \SHAR_EOF > 'ditrev.1' X.TH DITREV 1 local X.SH NAME Xditrev \- reverse ditroff(1) pages X.SH SYNOPSIS X.B ditrev X[file] X.SH DESCRIPTION X.I Ditrev Xreverses the pages in a ditroff Xfile (or stdin, if no file is Xspecified) and outputs to stdout. This is useful when sending typeset Xditroff output to a laser printer: Xditroff outputs the pages in an order that, without this filter, forces Xyou to manually reverse them all. X.PP XTo use this filter, you would use something like the following command: X.RS Xtroff file -t -Pps | ditrev | lpr -n -Pps X.RE X(where /usr/local/ditroff is ahead of /usr/bin in your search path). X.SH COMPARISON WITH PSREV XThere is another program called psrev Xthat reverses the pages of PostScript Xfiles. Since many laser printers (e.g., the MacIntosh LaserWriter) use XPostScript, one could do X.RS Xtroff file -t -Pps | dps | psrev | lpr -Pps X.RE X(dps translates between ditroff format and PostScript). Although I didn't know Xof the existence of psrev when I wrote X.I ditrev, Xit turns out that there are several advantages of X.I ditrev Xover psrev: X.IP 1. X.I Ditrev Xis more general - it works no matter what image format the printer accepts. XThus, X.I ditrev Xcan be used for any printer, and the user doesn't have to know what format Xthe printer expects. X.IP XOn the other hand, psrev works no matter what Xtext formatter generated the file, as long as the printer accepts XPostScript. But, since most text processors (Scribe and tex(1L) in Xparticular) output the pages in the correct order, this probably Xisn't too useful. X.IP 2. X.I Ditrev Xruns faster than psrev. X.IP 3. XNeither dps nor psrev seem to have man pages. X.IP 4. XDps is often only available on the machine Xwhich drives the printer, so you would actually have to do X.RS X.RS Xtroff file -t -Pps | rsh 'dps | psrev | lpr -Pps' X.RE XThis can become more complicated and installation dependent Xif these other filters aren't Xin your search path on the remote machine. X.RE X.SH AUTHOR XMike Schwartz, University of Washington Computer Science Department. X.ce 3 Xihnp4!uw-beaver!schwartz (USENET) Xschwartz@wally.arpa (ARPANET) Xschwartz%wally.arpa@csnet-relay.arpa (CSNET) X.SH BUGS X.IP 1. XThe transformation performed is very simple; I discovered it by looking at the Xoutput of ditroff and the source of dsun(1). Thus, although this filter Xseems to work, I may have made some oversimplifications. X.IP 2. XInput is read into dynamically allocated buffers, and hence, for a large input Xfile, alot of memory is used (but no more than necessary, if compiled with X-DREALLOC). This could have been avoided by disallowing input from stdin and Xusing fseek(3) to move through the file. I didn't do this because I wanted to Xallow input to come from stdin. X.SH SEE ALSO Xtroff(1), ditroff(1), dsun(1), lpr(1), tex(1L), printcap(5). SHAR_EOF if test 2762 -ne "`wc -c < 'ditrev.1'`" then echo shar: "error transmitting 'ditrev.1'" '(should have been 2762 characters)' fi fi echo shar: "extracting 'ditrev.c'" '(5198 characters)' if test -f 'ditrev.c' then echo shar: "will not over-write existing file 'ditrev.c'" else sed 's/^ X//' << \SHAR_EOF > 'ditrev.c' X/* Program to reverse pages from input and print on stdout, for ditroff(1) X * input. This is useful when sending typeset ditroff output to a laser X * printer: ditroff outputs the pages in an order that, without this filter, X * forces you to manually reverse them all. X * X * The transformation is simple: Below is some sample input. The X's below X * represent any character other than "p"; "p" delimits pages, and "x trailer" X * delimits the end of the last page. Also, all lines start in column 1. X * Xstartingstuff X * p1 X * Xpage1stuff X * p2 X * Xpage2stuff X * x trailer X * Xfinalstuff X * X * This input, when run through this filter, will produce the following output: X * Xstartingstuff X * p2 X * Xpage2stuff X * p1 X * Xpage1stuff X * x trailer X * Xfinalstuff X * X * By Mike Schwartz, 6-24-86. X * ihnp4!uw-beaver!schwartz (USENET) X * schwartz@wally.arpa (ARPANET) X * schwartz%wally.arpa@csnet-relay.arpa (CSNET) X */ X X X#include <stdio.h> X X#define PAGEBUFSIZE 30000 /* Number of bytes initially allocated for each X postscript page. I empirically determined that X this is plenty more than ever seems to be X needed (max was about 18k). If compiled with X -DREALLOC, there is no waste involved, since X the buffers are realloc'd after their size is X determined. There seems to be similar time and X CPU usage characteristics with or without X -DREALLOC, but the space used is considerably X less with -DREALLOC: a 320k input file caused X the dynamic size to grow to about 500k with X -DREALLOC, and to about 1200k without it. */ X X#define MAXPAGES 500 /* Max number of pages in the document */ X X#define PageDelim(Char) (Char == 'p') X#define EndOfAllPagesDelimString "x trailer" X#define EndOfAllPages(Line) (strncmp(Line, EndOfAllPagesDelimString, 9) == 0) X Xint PageIndex = 0; X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X FILE *InputFile = stdin; X char *InputBufPtr; X int CharIndex = 0; X char *PageBuf[MAXPAGES]; X char *fgets(), *malloc(), *realloc(); X X if (argc > 2) { X fputs("Usage: ditrev [file]\n", stderr); X exit(1); X } X X if (argc == 2) { X InputFile = fopen(argv[1], "r"); X if (InputFile == NULL) { X perror("ditrev: fopen"); X exit(1); X } X } X X PageBuf[PageIndex] = malloc(PAGEBUFSIZE); X if (PageBuf[PageIndex] == NULL) X Abort("malloc returned no storage"); X X /* Copy preliminary stuff (before first page) from input to output */ X do { X InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex], X PAGEBUFSIZE, InputFile); X if (InputBufPtr == NULL) /* EOF */ X Abort("Invalid input format"); X if (PageDelim(*InputBufPtr)) X break; X fputs(InputBufPtr, stdout); X } while(1); X X X /* Now read and store away all pages until hit EndOfAllPages */ X do { X InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex], X PAGEBUFSIZE, InputFile); X if (InputBufPtr == NULL) /* EOF */ X Abort("Invalid input format"); X if (EndOfAllPages(InputBufPtr)) { X /* Put a page delimeter into the end of this page so X we can find the end when we are printing everything X out */ X *InputBufPtr = 'p'; X break; X } X CharIndex += strlen(InputBufPtr) + 1; X /* +1 so we don't write over the null terminator */ X if (CharIndex >= PAGEBUFSIZE) { X Abort("Page size being malloc'd is too small (recompile with larger PAGEBUFSIZE)"); X } X if (PageDelim(*InputBufPtr)) { X#ifdef REALLOC X /* Now that we know how big this page is, realloc the X old page buffer so we don't waste unused space */ X PageBuf[PageIndex] = realloc(PageBuf[PageIndex], X CharIndex); X if (PageBuf[PageIndex] == NULL) X Abort("realloc returned no storage"); X#endif REALLOC X /* (Leave the page delimeter in place so we can find X the end of the old page when we are printing X everything out). Advance PageIndex, reset X CharIndex, and malloc more storage, so we can start X reading in the next page */ X PageIndex++; X PageBuf[PageIndex] = malloc(PAGEBUFSIZE); X if (PageBuf[PageIndex] == NULL) X Abort("malloc returned no storage"); X CharIndex = 0; X } X } while(1); X X X /* Now print out the buffered up pages in reverse order */ X X for (PageIndex = PageIndex; PageIndex >= 0; PageIndex--) { X CharIndex = 0; X /* Output the page delimeter record expected by the drivers */ X printf("p%d\n", PageIndex + 1); X do { X if (PageDelim(PageBuf[PageIndex][CharIndex])) X break; X fputs(&PageBuf[PageIndex][CharIndex], stdout); X CharIndex += strlen(&PageBuf[PageIndex][CharIndex]) + 1; X /* +1 to skip the null terminator */ X } while(1); X } X X /* Now print out the final lines, starting with the end-pages X delimeter line */ X puts(EndOfAllPagesDelimString); X PageIndex = 0; X CharIndex = 0; X#ifdef REALLOC X /* Current PageBuf may have been chopped off too short for final X stuff */ X PageBuf[PageIndex] = realloc(PageBuf[PageIndex], PAGEBUFSIZE); X if (PageBuf[PageIndex] == NULL) X Abort("realloc returned no storage"); X#endif REALLOC X do { X InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex], X PAGEBUFSIZE, InputFile); X if (InputBufPtr == NULL) /* EOF */ X exit(0); X fputs(InputBufPtr, stdout); X } while(1); X} X XAbort(Message) Xchar *Message; X{ X fprintf(stderr, "ditrev: %s at page %d\n", Message, PageIndex); X exit(1); X} SHAR_EOF if test 5198 -ne "`wc -c < 'ditrev.c'`" then echo shar: "error transmitting 'ditrev.c'" '(should have been 5198 characters)' fi fi echo shar: "extracting 'makefile'" '(146 characters)' if test -f 'makefile' then echo shar: "will not over-write existing file 'makefile'" else sed 's/^ X//' << \SHAR_EOF > 'makefile' X# use -DREALLOC if you want this program to use realloc(1) XCFLAGS = -O -DREALLOC X Xditrev: ditrev.c X cc ${CFLAGS} -o ditrev ditrev.c X strip ditrev SHAR_EOF if test 146 -ne "`wc -c < 'makefile'`" then echo shar: "error transmitting 'makefile'" '(should have been 146 characters)' fi fi exit 0 # End of shell archive