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