home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2351 / psrev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  6.5 KB  |  329 lines

  1. /* psrev.c */
  2.  
  3. #ifndef lint
  4. static char rcsid[] = "$Header: /usr/jjc/lprps/RCS/psrev.c,v 1.2 90/12/18 09:58:35 jjc Rel $";
  5. #endif
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9.  
  10. char *malloc();
  11. char *realloc();
  12.  
  13. char *xmalloc();
  14. char *xrealloc();
  15. char *prog;
  16.  
  17. typedef struct line_buf {
  18.   char *buf;
  19.   int len;
  20.   int size;
  21. } line_buf;
  22.  
  23. int get_line(lb, fp)
  24. line_buf *lb;
  25. FILE *fp;
  26. {
  27.   int left;
  28.   char *ptr;
  29.   if (lb->buf == NULL) {
  30.     lb->size = 16;
  31.     lb->buf = xmalloc(16);
  32.   }
  33.   ptr = lb->buf;
  34.   left = lb->size - 1;
  35.   for (;;) {
  36.     int c = getc(fp);
  37.     if (c == EOF) {
  38.       if (ferror(fp))
  39.     return 0;
  40.       if (ptr == lb->buf)
  41.     return 0;
  42.       lb->len = ptr - lb->buf;
  43.       *ptr++ = '\0';
  44.       return 1;
  45.     }
  46.     if (left <= 0) {
  47.       int n = ptr - lb->buf;
  48.       lb->size *= 2;
  49.       lb->buf = xrealloc(lb->buf, lb->size);
  50.       left = lb->size - n - 1;
  51.       ptr = lb->buf + n;
  52.     }
  53.     *ptr++ = c;
  54.     left -= 1;
  55.     if (c == '\n') {
  56.       lb->len = ptr - lb->buf;
  57.       *ptr++ = '\0';
  58.       return 1;
  59.     }
  60.   }
  61. }
  62.  
  63. void put_line(lb, fp)
  64. line_buf *lb;
  65. FILE *fp;
  66. {
  67.   fwrite(lb->buf, 1, lb->len, fp);
  68. }
  69.  
  70. /* is s2 a prefix of s1? */
  71. int strprefix(s1, s2)
  72. char *s1, *s2;
  73. {
  74.   for (; *s1 != '\0' && *s1 == *s2; s1++, s2++)
  75.     ;
  76.   return *s2 == '\0';
  77. }
  78.  
  79. void copy_and_exit(fp)
  80. FILE *fp;
  81. {
  82.   int c;
  83.   while ((c = getc(fp)) != EOF)
  84.     putchar(c);
  85.   exit(0);
  86. }
  87.  
  88. typedef struct page_list {
  89.   long pos;
  90.   struct page_list *next;
  91. } page_list;
  92.  
  93. main(argc, argv)
  94. int argc;
  95. char **argv;
  96. {
  97.   int dont_reverse = 0;
  98.   int pageno;
  99.   int pending_line = 0;
  100.   int had_pages_comment = 0;
  101.   int pages_comment_atend = 0;
  102.   int npages = -1;
  103.   int page_order;
  104.   int had_page_order;
  105.   FILE *tempfp = NULL;
  106.   page_list *pl = 0;
  107.   long trailer_pos = -1;
  108.   long prev_pos;
  109.   int level = 0;
  110.   line_buf lb;
  111.   prog = argv[0];
  112.   lb.buf = 0;
  113.   if (!get_line(&lb, stdin))
  114.     exit(0);
  115.   put_line(&lb, stdout);
  116.   if (!strprefix(lb.buf, "%!PS-Adobe-"))
  117.     copy_and_exit(stdin);
  118.  
  119.   /* process the header section */
  120.   while (get_line(&lb, stdin)) {
  121.     int suppress = 0;
  122.     if (!strprefix(lb.buf, "%%")) {
  123.       pending_line = 1;
  124.       break;
  125.     }
  126.     else if (strprefix(lb.buf, "%%Pages:")) {
  127.       suppress = 1;        /* don't print it yet */
  128.       /* the first %%Pages comment is the significant one */
  129.       if (!had_pages_comment) {
  130.     char *ptr = lb.buf + 8;
  131.     while (*ptr == ' ')
  132.       ptr++;
  133.     had_pages_comment = 1;
  134.     if (strprefix(ptr, "(atend)"))
  135.       pages_comment_atend = 1;
  136.     else {
  137.       if (sscanf(ptr, "%d %d", &npages, &page_order) == 2)
  138.         had_page_order = 1;
  139.     }
  140.       }
  141.     }
  142.     if (strprefix(lb.buf, "%%EndComments"))
  143.       break;
  144.     if (!suppress)
  145.       put_line(&lb, stdout);
  146.   }
  147.  
  148.   if (had_pages_comment) {
  149.     if (pages_comment_atend)
  150.       printf("%%%%Pages: (atend)\n");
  151.     else if (had_page_order) {
  152.       switch (page_order) {
  153.       case 1:
  154.     printf("%%%%Pages: %d -1\n", npages);
  155.     break;
  156.       case -1:
  157.     dont_reverse = 1;
  158.     printf("%%%%Pages: %d -1\n", npages);
  159.     break;
  160.       case 0:
  161.     /* what should we do here? */
  162.       default:
  163.     printf("%%%%Pages: %d %d\n", npages, page_order);
  164.     break;
  165.       }
  166.     }
  167.     else if (npages >= 0)
  168.       printf("%%%%Pages: %d\n", npages);
  169.   }
  170.   else
  171.     dont_reverse = 1;
  172.   
  173.   printf("%%%%EndComments\n");
  174.  
  175.   if (dont_reverse)
  176.     copy_and_exit(stdin);
  177.  
  178.   /* process the prologue */
  179.   while (pending_line || get_line(&lb, stdin)) {
  180.     pending_line = 0;
  181.     if (strprefix(lb.buf, "%%BeginDocument"))
  182.       ++level;
  183.     else if (strprefix(lb.buf, "%%EndDocument")) {
  184.       if (level > 0)
  185.     --level;
  186.     }
  187.     else if (level == 0 && strprefix(lb.buf, "%%Page:")) {
  188.       pending_line = 1;
  189.       break;
  190.     }
  191.     put_line(&lb, stdout);
  192.   }
  193.  
  194.   /* if we didn't find any %%Page comments, we're done */
  195.   if (!pending_line)
  196.     exit(0);
  197.  
  198.   /* open a temporary file if necessary */
  199.   if (ftell(stdin) == -1) {
  200.     tempfp = tmpfile();
  201.     clearerr(stdin);
  202.   }
  203.  
  204.   /* process the body */
  205.   while (pending_line || get_line(&lb, stdin)) {
  206.     pending_line = 0;
  207.     if (strprefix(lb.buf, "%%BeginDocument"))
  208.       ++level;
  209.     else if (strprefix(lb.buf, "%%EndDocument")) {
  210.       if (level > 0)
  211.     --level;
  212.     }
  213.     else if (level == 0) {
  214.       if (strprefix(lb.buf, "%%Page:")) {
  215.     page_list *tem = (page_list *)xmalloc(sizeof(page_list));
  216.     tem->next = pl;
  217.     tem->pos = tempfp ? ftell(tempfp) : ftell(stdin) - lb.len;
  218.     pl = tem;
  219.       }
  220.       else if (strprefix(lb.buf, "%%Trailer")) {
  221.     pending_line = 1;
  222.     break;
  223.       }
  224.     }
  225.     if (tempfp != NULL)
  226.       put_line(&lb, tempfp);
  227.   }
  228.  
  229.   /* process the trailer */
  230.   if (pending_line) {
  231.     trailer_pos = tempfp ? ftell(tempfp) : ftell(stdin) - lb.len;
  232.     while (pending_line || get_line(&lb, stdin)) {
  233.       pending_line = 0;
  234.       if (pages_comment_atend && strprefix(lb.buf, "%%Pages:")) {
  235.     int npages, page_order;
  236.     if (sscanf(lb.buf + 8, "%d %d", &npages, &page_order) == 2
  237.         && page_order == -1)
  238.       dont_reverse = 1;
  239.     else
  240.       dont_reverse = 0;
  241.       }
  242.       if (tempfp != NULL)
  243.     put_line(&lb, tempfp);
  244.     }
  245.   }
  246.  
  247.   if (tempfp == NULL)
  248.     tempfp = stdin;
  249.  
  250.   if (dont_reverse) {
  251.     long first_page_pos;
  252.     if (pl == NULL)
  253.       abort();
  254.     /* find the position of the first page */
  255.     while (pl != NULL) {
  256.       page_list *tem = pl;
  257.       first_page_pos = pl->pos;
  258.       pl = pl->next;
  259.       free((char *)tem);
  260.     }
  261.     fseek(tempfp, first_page_pos, 0);
  262.     copy_and_exit(tempfp);
  263.   }
  264.  
  265.   /* output each page */
  266.   prev_pos = trailer_pos == -1 ? ftell(tempfp) : trailer_pos;
  267.   pageno = 1;
  268.   while (pl != NULL) {
  269.     char *ptr, *label;
  270.     int count = prev_pos - pl->pos;
  271.     fseek(tempfp, pl->pos, 0);
  272.     if (!get_line(&lb, tempfp))
  273.       abort();
  274.     if (!strprefix(lb.buf, "%%Page:"))
  275.       abort();
  276.     ptr = lb.buf + 7;
  277.     while (*ptr == ' ')
  278.       ptr++;
  279.     label = ptr;
  280.     while (*ptr != '\0' && !(isascii(*ptr) && isspace(*ptr)))
  281.       ptr++;
  282.     *ptr = '\0';
  283.     if (*label == '\0')
  284.       label = "?";
  285.     printf("%%%%Page: %s %d\n", label, pageno);
  286.     pageno += 1;
  287.     count -= lb.len;
  288.     while (--count >= 0) {
  289.       int c = getc(tempfp);
  290.       if (c == EOF)
  291.     abort();
  292.       putc(c, stdout);
  293.     }
  294.     prev_pos = pl->pos;
  295.     pl = pl->next;
  296.   }
  297.  
  298.   /* output the trailer if there is one */
  299.   if (trailer_pos != -1) {
  300.     fseek(tempfp, trailer_pos, 0);
  301.     copy_and_exit(tempfp);
  302.   }
  303.  
  304.   exit(0);
  305. }
  306.  
  307. char *xmalloc(size)
  308. int size;
  309. {
  310.   char *tem;
  311.   if ((tem = malloc(size)) == NULL) {
  312.     fprintf(stderr, "%s: out of memory\n", prog);
  313.     exit(1);
  314.   }
  315.   return tem;
  316. }
  317.  
  318. char *xrealloc(ptr, size)
  319. char *ptr;
  320. int size;
  321. {
  322.   char *tem;
  323.   if ((tem = realloc(ptr, size)) == NULL) {
  324.     fprintf(stderr, "%s: out of memory\n", prog);
  325.     exit(1);
  326.   }
  327.   return tem;
  328. }
  329.