home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / groff-1.09-src.lha / src / amiga / groff-1.09 / psbb / psbb.c < prev    next >
C/C++ Source or Header  |  1992-08-03  |  4KB  |  170 lines

  1. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  2.      Written by James Clark (jjc@jclark.com)
  3.  
  4. This file is part of groff.
  5.  
  6. groff is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation; either version 2, or (at your option) any later
  9. version.
  10.  
  11. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  12. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License along
  17. with groff; see the file COPYING.  If not, write to the Free Software
  18. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #ifndef errno
  24. extern int errno;
  25. #endif
  26.  
  27. struct bounding_box {
  28.   int llx, lly, urx, ury;
  29. };
  30.  
  31. #ifdef __STDC__
  32. const char *do_file(FILE *, struct bounding_box *);
  33. int parse_bounding_box(char *, struct bounding_box *);
  34. #else
  35. #define const /* as nothing */
  36. const char *do_file();
  37. int parse_bounding_box();
  38. #endif
  39.  
  40. int main(argc, argv)
  41. int argc;
  42. char **argv;
  43. {
  44.   FILE *fp;
  45.   const char *message;
  46.   struct bounding_box bb;
  47.   if (argc != 2) {
  48.     fprintf(stderr, "usage: %s filename\n", argv[0]);
  49.     exit(3);
  50.   }
  51.   errno = 0;
  52.   fp = fopen(argv[1], "r");
  53.   if (fp == NULL) {
  54.     fprintf(stderr, "%s: can't open `%s': ", argv[0], argv[1]);
  55.     perror((char *)NULL);
  56.     exit(2);
  57.   }
  58.   message = do_file(fp, &bb);
  59.   if (message) {
  60.     fprintf(stderr, "%s: ", argv[0]);
  61.     fprintf(stderr, message, argv[1]);
  62.     putc('\n', stderr);
  63.     exit(1);
  64.   }
  65.   printf("%d %d %d %d\n", bb.llx, bb.lly, bb.urx, bb.ury);
  66.   exit(0);
  67. }
  68.       
  69. /* If the bounding box was found return NULL, and store the bounding box
  70. in bb. If the bounding box was not found return a string suitable for
  71. giving to printf with the filename as an argument saying why not. */
  72.  
  73. const char *do_file(fp, bb)
  74. FILE *fp;
  75. struct bounding_box *bb;
  76. {
  77.   int bb_at_end = 0;
  78.   char buf[256];
  79.   if (!fgets(buf, sizeof(buf), fp))
  80.     return "%s is empty";
  81.   if (strncmp("%!PS-Adobe-", buf, 11) != 0)
  82.     return "%s is not conforming";
  83.   while (fgets(buf, sizeof(buf), fp) != 0) {
  84.     if (buf[0] != '%' || buf[1] != '%'
  85.     || strncmp(buf + 2, "EndComments", 11) == 0)
  86.       break;
  87.     if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
  88.       int res = parse_bounding_box(buf + 14, bb);
  89.       if (res == 1)
  90.     return NULL;
  91.       else if (res == 2) {
  92.     bb_at_end = 1;
  93.     break;
  94.       }
  95.       else
  96.     return "the arguments to the %%%%BoundingBox comment in %s are bad";
  97.     }
  98.   }
  99.   if (bb_at_end) {
  100.     long offset;
  101.     int last_try = 0;
  102.     /* in the trailer, the last BoundingBox comment is significant */
  103.     for (offset = 512; !last_try; offset *= 2) {
  104.       int had_trailer = 0;
  105.       int got_bb = 0;
  106.       if (offset > 32768 || fseek(fp, -offset, 2) == -1) {
  107.     last_try = 1;
  108.     if (fseek(fp, 0L, 0) == -1)
  109.       break;
  110.       }
  111.       while (fgets(buf, sizeof(buf), fp) != 0) {
  112.     if (buf[0] == '%' && buf[1] == '%') {
  113.       if (!had_trailer) {
  114.         if (strncmp(buf + 2, "Trailer", 7) == 0)
  115.           had_trailer = 1;
  116.       }
  117.       else {
  118.         if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
  119.           int res = parse_bounding_box(buf + 14, bb);
  120.           if (res == 1)
  121.         got_bb = 1;
  122.           else if (res == 2)
  123.         return "`(atend)' not allowed in trailer";
  124.           else
  125.         return "the arguments to the %%%%BoundingBox comment in %s are bad";
  126.         }
  127.       }
  128.     }
  129.       }
  130.       if (got_bb)
  131.     return NULL;
  132.     }
  133.   }
  134.   return "%%%%BoundingBox comment not found in %s";
  135. }
  136.  
  137. /* Parse the argument to a %%BoundingBox comment. Return 1 if it
  138. contains 4 numbers, 2 if it contains (atend), 0 otherwise. */
  139.  
  140. int parse_bounding_box(p, bb)
  141. char *p;
  142. struct bounding_box *bb;
  143. {
  144.   if (sscanf(p, "%d %d %d %d",
  145.          &bb->llx, &bb->lly, &bb->urx, &bb->ury) == 4)
  146.     return 1;
  147.   else {
  148.     /* The Document Structuring Conventions say that the numbers
  149.        should be integers. Unfortunately some broken applications
  150.        get this wrong. */
  151.     double x1, x2, x3, x4;
  152.     if (sscanf(p, "%lf %lf %lf %lf", &x1, &x2, &x3, &x4) == 4) {
  153.       bb->llx = (int)x1;
  154.       bb->lly = (int)x2;
  155.       bb->urx = (int)x3;
  156.       bb->ury = (int)x4;
  157.       return 1;
  158.     }
  159.     else {
  160.       for (; *p == ' ' || *p == '\t'; p++)
  161.     ;
  162.       if (strncmp(p, "(atend)", 7) == 0) {
  163.     return 2;
  164.       }
  165.     }
  166.   }
  167.   return 0;
  168. }
  169.  
  170.