home *** CD-ROM | disk | FTP | other *** search
- /* Program to reverse pages from input and print on stdout, for ditroff(1)
- * input. This is useful when sending typeset ditroff output to a laser
- * printer: ditroff outputs the pages in an order that, without this filter,
- * forces you to manually reverse them all.
- *
- * The transformation is simple: Below is some sample input. The X's below
- * represent any character other than "p"; "p" delimits pages, and "x trailer"
- * delimits the end of the last page. Also, all lines start in column 1.
- * Xstartingstuff
- * p1
- * Xpage1stuff
- * p2
- * Xpage2stuff
- * x trailer
- * Xfinalstuff
- *
- * This input, when run through this filter, will produce the following output:
- * Xstartingstuff
- * p2
- * Xpage2stuff
- * p1
- * Xpage1stuff
- * x trailer
- * Xfinalstuff
- *
- * By Mike Schwartz, 6-24-86.
- * ihnp4!uw-beaver!schwartz (USENET)
- * schwartz@wally.arpa (ARPANET)
- * schwartz%wally.arpa@csnet-relay.arpa (CSNET)
- */
-
-
- #include <stdio.h>
-
- #define PAGEBUFSIZE 30000 /* Number of bytes initially allocated for each
- postscript page. I empirically determined that
- this is plenty more than ever seems to be
- needed (max was about 18k). If compiled with
- -DREALLOC, there is no waste involved, since
- the buffers are realloc'd after their size is
- determined. There seems to be similar time and
- CPU usage characteristics with or without
- -DREALLOC, but the space used is considerably
- less with -DREALLOC: a 320k input file caused
- the dynamic size to grow to about 500k with
- -DREALLOC, and to about 1200k without it. */
-
- #define MAXPAGES 500 /* Max number of pages in the document */
-
- #define PageDelim(Char) (Char == 'p')
- #define EndOfAllPagesDelimString "x trailer"
- #define EndOfAllPages(Line) (strncmp(Line, EndOfAllPagesDelimString, 9) == 0)
-
- int PageIndex = 0;
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- FILE *InputFile = stdin;
- char *InputBufPtr;
- int CharIndex = 0;
- char *PageBuf[MAXPAGES];
- char *fgets(), *malloc(), *realloc();
-
- if (argc > 2) {
- fputs("Usage: ditrev [file]\n", stderr);
- exit(1);
- }
-
- if (argc == 2) {
- InputFile = fopen(argv[1], "r");
- if (InputFile == NULL) {
- perror("ditrev: fopen");
- exit(1);
- }
- }
-
- PageBuf[PageIndex] = malloc(PAGEBUFSIZE);
- if (PageBuf[PageIndex] == NULL)
- Abort("malloc returned no storage");
-
- /* Copy preliminary stuff (before first page) from input to output */
- do {
- InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex],
- PAGEBUFSIZE, InputFile);
- if (InputBufPtr == NULL) /* EOF */
- Abort("Invalid input format");
- if (PageDelim(*InputBufPtr))
- break;
- fputs(InputBufPtr, stdout);
- } while(1);
-
-
- /* Now read and store away all pages until hit EndOfAllPages */
- do {
- InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex],
- PAGEBUFSIZE, InputFile);
- if (InputBufPtr == NULL) /* EOF */
- Abort("Invalid input format");
- if (EndOfAllPages(InputBufPtr)) {
- /* Put a page delimeter into the end of this page so
- we can find the end when we are printing everything
- out */
- *InputBufPtr = 'p';
- break;
- }
- CharIndex += strlen(InputBufPtr) + 1;
- /* +1 so we don't write over the null terminator */
- if (CharIndex >= PAGEBUFSIZE) {
- Abort("Page size being malloc'd is too small (recompile with larger PAGEBUFSIZE)");
- }
- if (PageDelim(*InputBufPtr)) {
- #ifdef REALLOC
- /* Now that we know how big this page is, realloc the
- old page buffer so we don't waste unused space */
- PageBuf[PageIndex] = realloc(PageBuf[PageIndex],
- CharIndex);
- if (PageBuf[PageIndex] == NULL)
- Abort("realloc returned no storage");
- #endif REALLOC
- /* (Leave the page delimeter in place so we can find
- the end of the old page when we are printing
- everything out). Advance PageIndex, reset
- CharIndex, and malloc more storage, so we can start
- reading in the next page */
- PageIndex++;
- PageBuf[PageIndex] = malloc(PAGEBUFSIZE);
- if (PageBuf[PageIndex] == NULL)
- Abort("malloc returned no storage");
- CharIndex = 0;
- }
- } while(1);
-
-
- /* Now print out the buffered up pages in reverse order */
-
- for (PageIndex = PageIndex; PageIndex >= 0; PageIndex--) {
- CharIndex = 0;
- /* Output the page delimeter record expected by the drivers */
- printf("p%d\n", PageIndex + 1);
- do {
- if (PageDelim(PageBuf[PageIndex][CharIndex]))
- break;
- fputs(&PageBuf[PageIndex][CharIndex], stdout);
- CharIndex += strlen(&PageBuf[PageIndex][CharIndex]) + 1;
- /* +1 to skip the null terminator */
- } while(1);
- }
-
- /* Now print out the final lines, starting with the end-pages
- delimeter line */
- puts(EndOfAllPagesDelimString);
- PageIndex = 0;
- CharIndex = 0;
- #ifdef REALLOC
- /* Current PageBuf may have been chopped off too short for final
- stuff */
- PageBuf[PageIndex] = realloc(PageBuf[PageIndex], PAGEBUFSIZE);
- if (PageBuf[PageIndex] == NULL)
- Abort("realloc returned no storage");
- #endif REALLOC
- do {
- InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex],
- PAGEBUFSIZE, InputFile);
- if (InputBufPtr == NULL) /* EOF */
- exit(0);
- fputs(InputBufPtr, stdout);
- } while(1);
- }
-
- Abort(Message)
- char *Message;
- {
- fprintf(stderr, "ditrev: %s at page %d\n", Message, PageIndex);
- exit(1);
- }
-