home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume39 / psutils / part02 / psutil.c < prev   
Encoding:
C/C++ Source or Header  |  1993-09-20  |  8.0 KB  |  343 lines

  1. /* psutil.c
  2.  * AJCD 29/1/91
  3.  * utilities for PS programs
  4.  */
  5.  
  6. /*
  7.  *  AJCD 6/4/93
  8.  *    Changed to using ftell() and fseek() only (no length calculations)
  9.  *  Hunter Goatley    31-MAY-1993 23:33
  10.  *    Fixed VMS support.
  11.  *  Hunter Goatley     2-MAR-1993 14:41
  12.  *    Added VMS support.
  13.  */
  14. #define LOCAL
  15. #include "psutil.h"
  16. #include "patchlevel.h"
  17.  
  18. #ifdef VMS
  19. #include <file.h>
  20. #else
  21. #include <fcntl.h>
  22. #endif
  23. #include <string.h>
  24.  
  25. #define iscomment(x,y) (strncmp(x,y,strlen(y)) == 0)
  26.  
  27. extern void argerror();
  28.  
  29. static char buffer[BUFSIZ];
  30. static long bytes = 0;
  31. static long pagescmt = 0;
  32. static long headerpos = 0;
  33. static long endsetup = 0;
  34. static int outputpage = 0;
  35. static int maxpages = 100;
  36. static long *pageptr;
  37.  
  38. /* list of paper sizes supported */
  39. static struct papersize papersizes[] = {
  40.    { "a3", 842, 1191 },        /* 29.7cm * 42cm */
  41.    { "a4", 595, 842 },        /* 21cm * 29.7cm */
  42.    { "a5", 421, 595 },        /* 14.85cm * 21cm */
  43.    { "b5", 516, 729 },        /* 18.2cm * 25.72cm */
  44.    { "A3", 842, 1191 },        /* 29.7cm * 42cm */
  45.    { "A4", 595, 842 },        /* 21cm * 29.7cm */
  46.    { "A5", 421, 595 },        /* 14.85cm * 21cm */
  47.    { "B5", 516, 729 },        /* 18.2cm * 25.72cm */
  48.    { "letter", 612, 792 },    /* 8.5in * 11in */
  49.    { "legal", 612, 1008 },    /* 8.5in * 14in */
  50.    { "ledger", 1224, 792 },    /* 17in * 11in */
  51.    { "tabloid", 792, 1224 },    /* 11in * 17in */
  52.    { "statement", 396, 612 },    /* 5.5in * 8.5in */
  53.    { "executive", 540, 720 },    /* 7.6in * 10in */
  54.    { "folio", 612, 936 },    /* 8.5in * 13in */
  55.    { "quarto", 610, 780 },    /* 8.5in * 10.83in */
  56.    { "10x14", 720, 1008 },    /* 10in * 14in */
  57.    { NULL, 0, 0 }
  58. };
  59.  
  60. /* return pointer to paper size struct or NULL */
  61. struct papersize* findpaper(name)
  62.      char *name;
  63. {
  64.    struct papersize *pp;
  65.    for (pp = papersizes; pp->name; pp++) {
  66.       if (strcmp(pp->name, name) == 0) {
  67.      return pp;
  68.       }
  69.    }
  70.    return NULL;
  71. }
  72.  
  73. /* make a file seekable; trick stolen from Chris Torek's libdvi */
  74. FILE *seekable(fp)
  75.      FILE *fp;
  76. {
  77.    int fd, tf, n, w;
  78.    char *tmpdir, *p;
  79.  
  80.    fd = fileno(fp);
  81.    if (lseek(fd, 0L, 1) >= 0 && !isatty(fd))
  82.       return (fp);
  83.  
  84. #ifdef MSDOS
  85.    fprintf(stderr, "%s: input is not seekable\n", prog);
  86.    fflush(stderr);
  87.    exit(1);
  88. #else
  89.    if ((tmpdir = getenv("TMPDIR")) == NULL)
  90.       tmpdir = TMPDIR;
  91.    (void) sprintf(buffer, "%s/#%d", tmpdir, getpid());
  92.    if ((tf = open(buffer, O_RDWR | O_CREAT | O_EXCL, 0666)) == -1)
  93.       return (NULL);
  94.    (void) unlink(buffer);
  95.  
  96.    while ((n = read(fd, p = buffer, BUFSIZ)) > 0) {
  97.       do {
  98.      if ((w = write(tf, p, n)) < 0) {
  99.         (void) close(tf);
  100.         (void) fclose(fp);
  101.         return (NULL);
  102.      }
  103.      p += w;
  104.       } while ((n -= w) > 0);
  105.    }
  106.    if (n < 0) {
  107.       (void) close(tf);
  108.       (void) fclose(fp);
  109.       return (NULL);
  110.    }
  111.  
  112.    /* discard the input file, and rewind and open the temporary */
  113.    (void) fclose(fp);
  114.    (void) lseek(tf, 0L, 0);
  115.    if ((fp = fdopen(tf, "r")) == NULL) {
  116.       (void) close(tf);
  117.    }
  118.    return (fp);
  119. #endif
  120. }
  121.  
  122. /* copy input file from current position upto new position to output file */
  123. static int fcopy(upto)
  124.      long upto;
  125. {
  126.    long here = ftell(infile);
  127.    while (here < upto) {
  128.       if ((fgets(buffer, BUFSIZ, infile) == NULL) ||
  129.       (fputs(buffer, outfile) == EOF))
  130.      return(0);
  131.       here = ftell(infile);
  132.       bytes += strlen(buffer);
  133.    }
  134.    return (1);
  135. }
  136.  
  137. /* build array of pointers to start/end of pages */
  138. void scanpages()
  139. {
  140.    register char *comment = buffer+2;
  141.    register int nesting = 0;
  142.    register long int record;
  143.  
  144.    if ((pageptr = (long *)malloc(sizeof(long)*maxpages)) == NULL) {
  145.       fprintf(stderr, "%s: out of memory\n", prog);
  146.       fflush(stderr);
  147.       exit(1);
  148.    }
  149.    pages = 0;
  150.    fseek(infile, 0L, 0);
  151.    while (record = ftell(infile), fgets(buffer, BUFSIZ, infile) != NULL)
  152.       if (*buffer == '%') {
  153.      if (buffer[1] == '%') {
  154.         if (nesting == 0 && iscomment(comment, "Page:")) {
  155.            if (pages >= maxpages-1) {
  156.           maxpages *= 2;
  157.           if ((pageptr = (long *)realloc((char *)pageptr,
  158.                          sizeof(long)*maxpages)) == NULL) {
  159.              fprintf(stderr, "%s: out of memory\n", prog);
  160.              fflush(stderr);
  161.              exit(1);
  162.           }
  163.            }
  164.            pageptr[pages++] = record;
  165.         } else if (headerpos == 0 && iscomment(comment, "Pages:"))
  166.            pagescmt = record;
  167.         else if (headerpos == 0 && iscomment(comment, "EndComments"))
  168.            headerpos = ftell(infile);
  169.         else if (iscomment(comment, "BeginDocument") ||
  170.              iscomment(comment, "BeginBinary") ||
  171.              iscomment(comment, "BeginFile"))
  172.            nesting++;
  173.         else if (iscomment(comment, "EndDocument") ||
  174.              iscomment(comment, "EndBinary") ||
  175.              iscomment(comment, "EndFile"))
  176.            nesting--;
  177.         else if (nesting == 0 && iscomment(comment, "EndSetup"))
  178.            endsetup = record;
  179.         else if (nesting == 0 && iscomment(comment, "Trailer")) {
  180.            fseek(infile, record, 0);
  181.            break;
  182.         }
  183.      } else if (headerpos == 0 && buffer[1] != '!')
  184.         headerpos = record;
  185.       } else if (headerpos == 0)
  186.      headerpos = record;
  187.    pageptr[pages] = ftell(infile);
  188.    if (endsetup == 0)
  189.       endsetup = pageptr[0];
  190. }
  191.  
  192. /* seek a particular page */
  193. void seekpage(p)
  194.      int p;
  195. {
  196.    fseek(infile, pageptr[p], 0);
  197.    if (fgets(buffer, BUFSIZ, infile) != NULL &&
  198.        iscomment(buffer, "%%Page:")) {
  199.       char *start, *end;
  200.       for (start = buffer+7; isspace(*start); start++);
  201.       if (*start == '(') {
  202.      int paren = 1;
  203.      for (end = start+1; paren > 0; end++)
  204.         switch (*end) {
  205.         case '\0':
  206.            fprintf(stderr,
  207.                "%s: Bad page label while seeking page %d\n", prog, p);
  208.            fflush(stderr);
  209.            exit(1);
  210.         case '(':
  211.            paren++;
  212.            break;
  213.         case ')':
  214.            paren--;
  215.            break;
  216.         }
  217.       } else
  218.      for (end = start; !isspace(*end); end++);
  219.       strncpy(pagelabel, start, end-start);
  220.       pageno = atoi(end);
  221.    } else {
  222.       fprintf(stderr, "%s: I/O error seeking page %d\n", prog, p);
  223.       fflush(stderr);
  224.       exit(1);
  225.    }
  226. }
  227.  
  228. /* Output routines. These all update the global variable bytes with the number
  229.  * of bytes written */
  230. void writestring(s)
  231.      char *s;
  232. {
  233.    fputs(s, outfile);
  234.    bytes += strlen(s);
  235. }
  236.  
  237. void writepageheader(label, page)
  238.      char *label;
  239.      int page;
  240. {
  241.    if (verbose) {
  242.       sprintf(buffer, "[%d] ", page);
  243.       message(buffer);
  244.    }
  245.    sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
  246.    writestring(buffer);
  247. }
  248.  
  249. void writepagebody(p)
  250.      int p;
  251. {
  252.    if (!fcopy(pageptr[p+1])) {
  253.       fprintf(stderr, "%s: I/O error writing page %d\n", prog, outputpage);
  254.       fflush(stderr);
  255.       exit(1);
  256.    }
  257. }
  258.  
  259. void writepage(p)
  260.      int p;
  261. {
  262.    seekpage(p);
  263.    writepageheader(pagelabel, p+1);
  264.    writepagebody(p);
  265. }
  266.  
  267. void writeheader(p)
  268.      int p;
  269. {
  270.    fseek(infile, 0L, 0);
  271.    if (pagescmt) {
  272.       if (!fcopy(pagescmt) || fgets(buffer, BUFSIZ, infile) == NULL) {
  273.      fprintf(stderr, "%s: I/O error in header\n", prog);
  274.      fflush(stderr);
  275.      exit(1);
  276.       }
  277.       sprintf(buffer, "%%%%Pages: %d 0\n", p);
  278.       writestring(buffer);
  279.    }
  280.    if (!fcopy(headerpos)) {
  281.       fprintf(stderr, "%s: I/O error in header\n", prog);
  282.       fflush(stderr);
  283.       exit(1);
  284.    }
  285. }
  286.  
  287.  
  288. void writeprolog(setup)
  289.      char *setup;
  290. {
  291.    if (!fcopy(endsetup)) {
  292.       fprintf(stderr, "%s: I/O error in prologue\n", prog);
  293.       fflush(stderr);
  294.       exit(1);
  295.    }
  296.    writestring(setup);
  297.    if (!fcopy(pageptr[0])) {
  298.       fprintf(stderr, "%s: I/O error in prologue\n", prog);
  299.       fflush(stderr);
  300.       exit(1);
  301.    }
  302. }
  303.  
  304. /* write trailer */
  305. void writetrailer()
  306. {
  307.    fseek(infile, pageptr[pages], 0);
  308.    while (fgets(buffer, BUFSIZ, infile) != NULL) {
  309.       writestring(buffer);
  310.    }
  311.    if (verbose) {
  312.       sprintf(buffer, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
  313.       message(buffer);
  314.    }
  315. }
  316.  
  317. /* write message to stderr */
  318. void message(s)
  319.      char *s;
  320. {
  321.    static int pos = 0;
  322.    char *nl = strchr(s, '\n');
  323.    int len = nl ? (nl-s) : strlen(s);
  324.  
  325.    if (pos+len > 79 && (pos > 79 || len < 80)) {
  326.       fputc('\n', stderr);
  327.       pos = 0;
  328.    }
  329.    fputs(s, stderr);
  330.    fflush(stderr);
  331.    pos += len;
  332. }
  333.  
  334.  
  335. void writeemptypage()
  336. {
  337.    if (verbose)
  338.       message("[*] ");
  339.    sprintf(buffer, "%%%%Page: * %d\nshowpage\n", ++outputpage);
  340.    writestring(buffer);
  341. }
  342.  
  343.