home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / psroff / part03 / psxlate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-17  |  5.1 KB  |  261 lines

  1. /*    Copyright 1985, 1986, 1987, 1988 Chris Lewis
  2.         All Rights Reserved
  3.  
  4.     Permission to copy and further distribute is freely given provided 
  5.     this copyright notice remains intact and that this software is not 
  6.     sold for profit.
  7.  
  8.     Project:    Generic Troff drivers
  9.     Module:        psxlate.c
  10.     Author:     Chris Lewis
  11.     Specs:        Generic Postscript filter (page reversal etc.)
  12.  */
  13. #ifndef    SVR3
  14. #ifndef    lint
  15. static char SCCSid[] = "@(#)psxlate.c: 1.4 Copyright 89/04/21 11:48:27 Chris Lewis";
  16. #endif
  17. #else
  18. #ident  "@(#)psxlate.c: 1.4 Copyright 89/04/21 11:48:27 Chris Lewis"
  19. #endif
  20. #include <stdio.h>
  21.  
  22. int    xlate = 0;
  23. #define    MAXPAGE    1000
  24.  
  25. struct headers {
  26.     char *hptr;
  27.     struct headers *next;
  28. };
  29.  
  30. struct pagedesc {
  31.     unsigned long start;
  32.     unsigned long end;
  33.     char *type;
  34.     struct headers *comments;
  35. } pageidx[MAXPAGE];
  36.  
  37. char *tmp = "/tmp/psxXXXXXX";
  38. int page = 0;
  39. char *progname;
  40. int debug;
  41.  
  42. main(argc, argv)
  43. int argc; char **argv; {
  44.     extern int optind;
  45.     int c;
  46.     progname = argv[0];
  47.     while ((c = getopt(argc, argv, "drx")) != EOF)
  48.     switch(c) {
  49.         case 'r': xlate = 0; break;
  50.         case 'x': xlate = 1; break;
  51.         case 'd': debug = 1; break;
  52.         default:
  53.         usage();
  54.         exit(1);
  55.     }
  56.     mktemp(tmp);
  57.     scan(stdin, tmp);
  58.     transform();
  59.     emit(tmp);
  60.     if (!debug)
  61.     cleanup();
  62.     exit(0);
  63. }
  64.  
  65. scan(f, file)
  66. FILE *f; char *file; {
  67.     FILE *t;
  68.     extern char *malloc();
  69.     int state = 1;
  70.     long ind = 0;
  71.     int c;
  72.     char buf[100];
  73.     if ((t = fopen(file, "w")) == NULL) {
  74.     fprintf(stderr, "Cannot open temporary file %s\n", file);
  75.     exit(1);
  76.     }
  77.     page = 0;
  78.     while((c = getc(f)) != EOF) {
  79.     putc(c, t);
  80.     ind++;
  81.     switch(state) {
  82.         case 0:
  83.         if (c == '\n') {
  84.             state = 1;
  85.         }
  86.         break;
  87.         case 1:    /* seen \n */
  88.         if (c == '%') {
  89.             fgets(buf, sizeof(buf), f);
  90.             fputs(buf, t);
  91.             if (0 == strncmp(buf, "!PS-Adobe", 9) ||
  92.             0 == strncmp(buf, "%Page:", 6) ||
  93.             0 == strncmp(buf, "%Trailer", 8)) {
  94.             if (page)
  95.                 pageidx[page-1].end = ind - 2;
  96.             pageidx[page].start = ind - 1;
  97.             strcpy(pageidx[page].type = malloc(strlen(buf)+1), buf);
  98.             add(page, buf);
  99.             page++;
  100.             } else
  101.             add(page, buf);
  102.             ind += strlen(buf);
  103.             break;
  104.         }
  105.         state = 0;
  106.         break;
  107.     }
  108.     }
  109.     if (page)
  110.     pageidx[page-1].end = ind - 1;
  111.     fclose(t);
  112. }
  113.  
  114. cleanup() {
  115.     unlink(tmp);
  116. }
  117.  
  118. emit(file)
  119. char *file; {
  120.     FILE *t;
  121.     register int i;
  122.     if ((t = fopen(file, "r")) == NULL) {
  123.     fprintf(stderr, "Panic\n");
  124.     exit(1);
  125.     }
  126.     for(i = 0; i < page; i++) {
  127.     register long start, end, cnt;
  128.     register int c;
  129.  
  130.     start = pageidx[i].start;
  131.     end = pageidx[i].end;
  132.     cnt = end - start + 1;
  133.     fseek(t, start, 0);
  134.     while(cnt--)
  135.         putchar(getc(t));
  136.     }
  137. }
  138.  
  139.  
  140. usage() {
  141.     fprintf(stderr, "Usage: %s [-r|-x] < file > file\n", progname);
  142. }
  143.  
  144. dumppg() {
  145.     register int i;
  146.     register struct headers *h;
  147.     if (debug) {
  148.     for (i = 0; i < page; i++) {
  149.         fprintf(stderr, "%d %d %d %s\n", i, pageidx[i].start, 
  150.         pageidx[i].end, pageidx[i].type);
  151.         for (h = pageidx[i].comments; h; h=h->next)
  152.         fprintf(stderr, "%s", h->hptr);
  153.     }
  154.     }
  155. }
  156.  
  157. transform() {
  158.     dumppg();
  159.     switch(xlate) {
  160.     case 0:
  161.         revpages();
  162.         break;
  163.     case 1:
  164.         xpages();
  165.         break;
  166.     }
  167.     dumppg();
  168. }
  169.  
  170. fstart() {
  171.     register int i;
  172.     for (i = 0; i < page; i++)
  173.     if (0 == strncmp(pageidx[i].type, "%Page:", 6))
  174.         break;
  175.     return(i);
  176. }
  177. fend() {
  178.     register int i;
  179.     for (i = page-1; i >= 0; i--)
  180.     if (0 == strncmp(pageidx[i].type, "%Page:", 6))
  181.         break;
  182.     return(i);
  183. }
  184.  
  185. revpages() {
  186.     register int i, j;
  187.     struct pagedesc t;
  188.     i = fstart();
  189.  
  190.     if (i == page)
  191.     return;
  192.     
  193.     j = fend();
  194.  
  195.     while(i < j) {
  196.     t = pageidx[i];
  197.     pageidx[i] = pageidx[j];
  198.     pageidx[j] = t;
  199.     i++;j--;
  200.     }
  201. }
  202.  
  203. xpages() {
  204.     register int i, j, mid, first, last;
  205.     struct pagedesc t;
  206.     struct pagedesc *p = 
  207.     (struct pagedesc *) malloc(sizeof(struct pagedesc) * page);
  208.     revpages();
  209.     first = fstart();
  210.  
  211.     if (first == page)
  212.     return;
  213.     
  214.     last = fend();
  215.  
  216.     if (debug)
  217.     fprintf(stderr, "first: %d, last: %d, page: %d\n", first, last, page);
  218.     if ((last - first + 1) < 3)
  219.     return;
  220.  
  221.     if (first)
  222.     memcpy(p, pageidx, sizeof(struct pagedesc) * first);    /* prolog */
  223.     if (page - last)    /* copy epilog */
  224.     memcpy(p+last+1, 
  225.         &pageidx[last+1], sizeof(struct pagedesc) * (page - last - 1));
  226.     mid = (last + first + 1) / 2 ;    /* offset of middle */
  227.     for (i = first; i < mid; i++)
  228.     p[first + (i - first) * 2] = pageidx[i];
  229.     for (i = mid; i <= last; i++)
  230.     p[first + (i - mid) * 2 + 1] = pageidx[i];
  231.     memcpy(pageidx, p, sizeof(struct pagedesc) * page);
  232.     free(p);
  233. }
  234.  
  235. add(page, buf)
  236. int page; char *buf; {
  237.     struct headers *hdr, *hp, *ohp;
  238.     char *p;
  239.     if (debug)
  240.     fprintf(stderr, "Adding %s\n", buf);
  241.     hdr = (struct headers *) malloc(sizeof(struct headers));
  242.     if (hdr == 0 || !(hdr->hptr = malloc(strlen(buf) + 2))) {
  243.     fprintf(stderr, "psxlate: Out of space\n");
  244.     exit(1);
  245.     }
  246.     strcpy(hdr->hptr, "%");
  247.     strcat(hdr->hptr, buf);
  248.     hdr->next = NULL;
  249.     for (ohp = hp = pageidx[page].comments; ; hp = hp->next) {
  250.     if (!hp) {
  251.         if (ohp == pageidx[page].comments)
  252.         pageidx[page].comments = hdr;
  253.         else
  254.         ohp->next = hdr;
  255.         break;
  256.     }
  257.     ohp = hp;
  258.     }
  259.     return;
  260. }
  261.