home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume6 / ditrev / ditrev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  5.1 KB  |  178 lines

  1. /* Program to reverse pages from input and print on stdout, for ditroff(1)
  2.  * input.  This is useful when sending typeset ditroff output to a laser
  3.  * printer:  ditroff outputs the pages in an order that, without this filter,
  4.  * forces you to manually reverse them all.
  5.  *
  6.  * The transformation is simple: Below is some sample input. The X's below
  7.  * represent any character other than "p"; "p" delimits pages, and "x trailer"
  8.  * delimits the end of the last page.  Also, all lines start in column 1.
  9.  *    Xstartingstuff
  10.  *    p1
  11.  *    Xpage1stuff
  12.  *    p2
  13.  *    Xpage2stuff
  14.  *    x trailer
  15.  *    Xfinalstuff
  16.  *
  17.  * This input, when run through this filter, will produce the following output:
  18.  *    Xstartingstuff
  19.  *    p2
  20.  *    Xpage2stuff
  21.  *    p1
  22.  *    Xpage1stuff
  23.  *    x trailer
  24.  *    Xfinalstuff
  25.  *
  26.  * By Mike Schwartz, 6-24-86.
  27.  *    ihnp4!uw-beaver!schwartz  (USENET)
  28.  *    schwartz@wally.arpa  (ARPANET)
  29.  *    schwartz%wally.arpa@csnet-relay.arpa  (CSNET)
  30.  */
  31.  
  32.  
  33. #include <stdio.h>
  34.  
  35. #define PAGEBUFSIZE 30000    /* Number of bytes initially allocated for each
  36.                 postscript page.  I empirically determined that
  37.                 this is plenty more than ever seems to be
  38.                 needed (max was about 18k).  If compiled with
  39.                 -DREALLOC, there is no waste involved, since
  40.                 the buffers are realloc'd after their size is
  41.                 determined.  There seems to be similar time and
  42.                 CPU usage characteristics with or without
  43.                 -DREALLOC, but the space used is considerably
  44.                 less with -DREALLOC: a 320k input file caused
  45.                 the dynamic size to grow to about 500k with
  46.                 -DREALLOC, and to about 1200k without it.  */
  47.  
  48. #define MAXPAGES 500         /* Max number of pages in the document */
  49.  
  50. #define PageDelim(Char) (Char == 'p')
  51. #define EndOfAllPagesDelimString "x trailer"
  52. #define EndOfAllPages(Line) (strncmp(Line, EndOfAllPagesDelimString, 9) == 0)
  53.  
  54. int PageIndex = 0;
  55.  
  56. main(argc, argv)
  57. int argc;
  58. char **argv;
  59. {
  60.     FILE *InputFile = stdin;
  61.     char *InputBufPtr;
  62.     int CharIndex = 0;
  63.     char *PageBuf[MAXPAGES];
  64.     char *fgets(), *malloc(), *realloc();
  65.  
  66.     if (argc > 2) {
  67.         fputs("Usage: ditrev [file]\n", stderr);
  68.         exit(1);
  69.     }
  70.  
  71.     if (argc == 2) {
  72.         InputFile = fopen(argv[1], "r");
  73.         if (InputFile == NULL) {
  74.             perror("ditrev: fopen");
  75.             exit(1);
  76.         }
  77.     }
  78.  
  79.     PageBuf[PageIndex] = malloc(PAGEBUFSIZE);
  80.     if (PageBuf[PageIndex] == NULL)
  81.         Abort("malloc returned no storage");
  82.  
  83.     /* Copy preliminary stuff (before first page) from input to output */
  84.     do {
  85.         InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex],
  86.                     PAGEBUFSIZE, InputFile);
  87.         if (InputBufPtr == NULL)  /* EOF */
  88.             Abort("Invalid input format");
  89.         if (PageDelim(*InputBufPtr))
  90.             break;
  91.         fputs(InputBufPtr, stdout);
  92.     } while(1);
  93.  
  94.  
  95.     /* Now read and store away all pages until hit EndOfAllPages */
  96.     do {
  97.         InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex],
  98.                     PAGEBUFSIZE, InputFile);
  99.         if (InputBufPtr == NULL)  /* EOF */
  100.             Abort("Invalid input format");
  101.         if (EndOfAllPages(InputBufPtr)) {
  102.             /* Put a page delimeter into the end of this page so
  103.                we can find the end when we are printing everything
  104.                out */
  105.             *InputBufPtr = 'p';
  106.             break;
  107.         }
  108.         CharIndex += strlen(InputBufPtr) + 1;
  109.         /* +1 so we don't write over the null terminator */
  110.         if (CharIndex >= PAGEBUFSIZE) {
  111.             Abort("Page size being malloc'd is too small (recompile with larger PAGEBUFSIZE)");
  112.         }
  113.         if (PageDelim(*InputBufPtr)) {
  114. #ifdef REALLOC
  115.             /* Now that we know how big this page is, realloc the
  116.                old page buffer so we don't waste unused space */
  117.             PageBuf[PageIndex] = realloc(PageBuf[PageIndex],
  118.                              CharIndex);
  119.             if (PageBuf[PageIndex] == NULL)
  120.                 Abort("realloc returned no storage");
  121. #endif REALLOC
  122.             /* (Leave the page delimeter in place so we can find
  123.                the end of the old page when we are printing
  124.                everything out).  Advance PageIndex, reset
  125.                CharIndex, and malloc more storage, so we can start
  126.                reading in the next page */
  127.             PageIndex++;
  128.             PageBuf[PageIndex] = malloc(PAGEBUFSIZE);
  129.             if (PageBuf[PageIndex] == NULL)
  130.                 Abort("malloc returned no storage");
  131.             CharIndex = 0;
  132.         }
  133.     } while(1);
  134.  
  135.  
  136.     /* Now print out the buffered up pages in reverse order */
  137.  
  138.     for (PageIndex = PageIndex; PageIndex >= 0; PageIndex--) {
  139.         CharIndex = 0;
  140.         /* Output the page delimeter record expected by the drivers */
  141.         printf("p%d\n", PageIndex + 1);
  142.         do {
  143.             if (PageDelim(PageBuf[PageIndex][CharIndex]))
  144.                 break;
  145.             fputs(&PageBuf[PageIndex][CharIndex], stdout);
  146.             CharIndex += strlen(&PageBuf[PageIndex][CharIndex]) + 1;
  147.             /* +1 to skip the null terminator */
  148.         } while(1);
  149.     }
  150.  
  151.     /* Now print out the final lines, starting with the end-pages
  152.        delimeter line */
  153.     puts(EndOfAllPagesDelimString);
  154.     PageIndex = 0;
  155.     CharIndex = 0;
  156. #ifdef REALLOC
  157.     /* Current PageBuf may have been chopped off too short for final
  158.        stuff */
  159.     PageBuf[PageIndex] = realloc(PageBuf[PageIndex], PAGEBUFSIZE);
  160.     if (PageBuf[PageIndex] == NULL)
  161.         Abort("realloc returned no storage");
  162. #endif REALLOC
  163.     do {
  164.         InputBufPtr = fgets(&PageBuf[PageIndex][CharIndex],
  165.                     PAGEBUFSIZE, InputFile);
  166.         if (InputBufPtr == NULL)   /* EOF */
  167.             exit(0);
  168.         fputs(InputBufPtr, stdout);
  169.     } while(1);
  170. }
  171.  
  172. Abort(Message)
  173. char *Message;
  174. {
  175.         fprintf(stderr, "ditrev: %s at page %d\n", Message, PageIndex);
  176.         exit(1);
  177. }
  178.