New english hyphenation hints
[ccbib.git] / psutils / psutil.c
blobb831935a6e031b3912822146292c9bd5296306b4
1 /* psutil.c
2 * Copyright (C) Angus J. C. Duggan 1991-1995
3 * See file LICENSE for details.
5 * utilities for PS programs
6 */
8 /*
9 * AJCD 6/4/93
10 * Changed to using ftell() and fseek() only (no length calculations)
11 * Hunter Goatley 31-MAY-1993 23:33
12 * Fixed VMS support.
13 * Hunter Goatley 2-MAR-1993 14:41
14 * Added VMS support.
16 #include "psutil.h"
17 #include "pserror.h"
18 #include "patchlev.h"
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
24 #define iscomment(x,y) (strncmp(x,y,strlen(y)) == 0)
26 extern char *program ;
27 extern int pages;
28 extern int verbose;
29 extern FILE *infile;
30 extern FILE *outfile;
31 extern char pagelabel[BUFSIZ];
32 extern int pageno;
34 static char buffer[BUFSIZ];
35 static long bytes = 0;
36 static long pagescmt = 0;
37 static long headerpos = 0;
38 static long endsetup = 0;
39 static long beginprocset = 0; /* start of pstops procset */
40 static long endprocset = 0;
41 static int outputpage = 0;
42 static int maxpages = 100;
43 static long *pageptr;
45 /* list of paper sizes supported */
46 static Paper papersizes[] = {
47 { "a3", 842, 1191 }, /* 29.7cm * 42cm */
48 { "a4", 595, 842 }, /* 21cm * 29.7cm */
49 { "a5", 421, 595 }, /* 14.85cm * 21cm */
50 { "b5", 516, 729 }, /* 18.2cm * 25.72cm */
51 { "A3", 842, 1191 }, /* 29.7cm * 42cm */
52 { "A4", 595, 842 }, /* 21cm * 29.7cm */
53 { "A5", 421, 595 }, /* 14.85cm * 21cm */
54 { "B5", 516, 729 }, /* 18.2cm * 25.72cm */
55 { "letter", 612, 792 }, /* 8.5in * 11in */
56 { "legal", 612, 1008 }, /* 8.5in * 14in */
57 { "ledger", 1224, 792 }, /* 17in * 11in */
58 { "tabloid", 792, 1224 }, /* 11in * 17in */
59 { "statement", 396, 612 }, /* 5.5in * 8.5in */
60 { "executive", 540, 720 }, /* 7.6in * 10in */
61 { "folio", 612, 936 }, /* 8.5in * 13in */
62 { "quarto", 610, 780 }, /* 8.5in * 10.83in */
63 { "10x14", 720, 1008 }, /* 10in * 14in */
64 { NULL, 0, 0 }
67 /* return pointer to paper size struct or NULL */
68 Paper* findpaper(char *name)
70 Paper *pp;
71 for (pp = papersizes; PaperName(pp); pp++) {
72 if (strcmp(PaperName(pp), name) == 0) {
73 return pp;
76 return (Paper *)NULL;
79 /* Make a file seekable, using temporary files if necessary */
80 FILE *seekable(FILE *fp)
82 #ifndef MSDOS
83 FILE *ft;
84 long r, w ;
85 #endif
86 char *p;
87 char buffer[BUFSIZ] ;
88 #if defined(WINNT)
89 struct _stat fs ;
90 #else
91 long fpos;
92 #endif
94 #if defined(WINNT)
95 if (_fstat(fileno(fp), &fs) == 0 && (fs.st_mode&_S_IFREG) != 0)
96 return (fp);
97 #else
98 if ((fpos = ftell(fp)) >= 0)
99 if (!fseek(fp, 0L, SEEK_END) && !fseek(fp, fpos, SEEK_SET))
100 return (fp);
101 #endif
103 #if defined(MSDOS)
104 message(FATAL, "input is not seekable\n");
105 return (NULL) ;
106 #else
107 if ((ft = tmpfile()) == NULL)
108 return (NULL);
110 while ((r = fread(p = buffer, sizeof(char), BUFSIZ, fp)) > 0) {
111 do {
112 if ((w = fwrite(p, sizeof(char), r, ft)) == 0)
113 return (NULL) ;
114 p += w ;
115 r -= w ;
116 } while (r > 0) ;
119 if (!feof(fp))
120 return (NULL) ;
122 /* discard the input file, and rewind the temporary */
123 (void) fclose(fp);
124 if (fseek(ft, 0L, SEEK_SET) != 0)
125 return (NULL) ;
127 return (ft);
128 #endif
132 /* copy input file from current position upto new position to output file */
133 static int fcopy(long upto)
135 long here = ftell(infile);
136 while (here < upto) {
137 if ((fgets(buffer, BUFSIZ, infile) == NULL) ||
138 (fputs(buffer, outfile) == EOF))
139 return(0);
140 here = ftell(infile);
141 bytes += strlen(buffer);
143 return (1);
146 /* build array of pointers to start/end of pages */
147 void scanpages(void)
149 register char *comment = buffer+2;
150 register int nesting = 0;
151 register long int record;
153 if ((pageptr = (long *)malloc(sizeof(long)*maxpages)) == NULL)
154 message(FATAL, "out of memory\n");
155 pages = 0;
156 fseek(infile, 0L, SEEK_SET);
157 while (record = ftell(infile), fgets(buffer, BUFSIZ, infile) != NULL)
158 if (*buffer == '%') {
159 if (buffer[1] == '%') {
160 if (nesting == 0 && iscomment(comment, "Page:")) {
161 if (pages >= maxpages-1) {
162 maxpages *= 2;
163 if ((pageptr = (long *)realloc((char *)pageptr,
164 sizeof(long)*maxpages)) == NULL)
165 message(FATAL, "out of memory\n");
167 pageptr[pages++] = record;
168 } else if (headerpos == 0 && iscomment(comment, "Pages:"))
169 pagescmt = record;
170 else if (headerpos == 0 && iscomment(comment, "EndComments"))
171 headerpos = ftell(infile);
172 else if (iscomment(comment, "BeginDocument") ||
173 iscomment(comment, "BeginBinary") ||
174 iscomment(comment, "BeginFile"))
175 nesting++;
176 else if (iscomment(comment, "EndDocument") ||
177 iscomment(comment, "EndBinary") ||
178 iscomment(comment, "EndFile"))
179 nesting--;
180 else if (nesting == 0 && iscomment(comment, "EndSetup"))
181 endsetup = record;
182 else if (nesting == 0 && iscomment(comment, "BeginProlog"))
183 headerpos = ftell(infile);
184 else if (nesting == 0 &&
185 iscomment(comment, "BeginProcSet: PStoPS"))
186 beginprocset = record;
187 else if (beginprocset && !endprocset &&
188 iscomment(comment, "EndProcSet"))
189 endprocset = ftell(infile);
190 else if (nesting == 0 && (iscomment(comment, "Trailer") ||
191 iscomment(comment, "EOF"))) {
192 fseek(infile, record, SEEK_SET);
193 break;
195 } else if (headerpos == 0 && buffer[1] != '!')
196 headerpos = record;
197 } else if (headerpos == 0)
198 headerpos = record;
199 pageptr[pages] = ftell(infile);
200 if (endsetup == 0 || endsetup > pageptr[0])
201 endsetup = pageptr[0];
204 /* seek a particular page */
205 void seekpage(int p)
207 fseek(infile, pageptr[p], SEEK_SET);
208 if (fgets(buffer, BUFSIZ, infile) != NULL &&
209 iscomment(buffer, "%%Page:")) {
210 char *start, *end;
211 for (start = buffer+7; isspace(*start); start++);
212 if (*start == '(') {
213 int paren = 1;
214 for (end = start+1; paren > 0; end++)
215 switch (*end) {
216 case '\0':
217 message(FATAL, "Bad page label while seeking page %d\n", p);
218 case '(':
219 paren++;
220 break;
221 case ')':
222 paren--;
223 break;
225 } else
226 for (end = start; !isspace(*end); end++);
227 strncpy(pagelabel, start, end-start);
228 pagelabel[end-start] = '\0';
229 pageno = atoi(end);
230 } else
231 message(FATAL, "I/O error seeking page %d\n", p);
234 /* Output routines. These all update the global variable bytes with the number
235 * of bytes written */
236 void writestring(char *s)
238 fputs(s, outfile);
239 bytes += strlen(s);
242 /* write page comment */
243 void writepageheader(char *label, int page)
245 if (verbose)
246 message(LOG, "[%d] ", page);
247 sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
248 writestring(buffer);
251 /* search for page setup */
252 void writepagesetup(void)
254 char buffer[BUFSIZ];
255 if (beginprocset) {
256 for (;;) {
257 if (fgets(buffer, BUFSIZ, infile) == NULL)
258 message(FATAL, "I/O error reading page setup %d\n", outputpage);
259 if (!strncmp(buffer, "PStoPSxform", 11))
260 break;
261 if (fputs(buffer, outfile) == EOF)
262 message(FATAL, "I/O error writing page setup %d\n", outputpage);
263 bytes += strlen(buffer);
268 /* write the body of a page */
269 void writepagebody(int p)
271 if (!fcopy(pageptr[p+1]))
272 message(FATAL, "I/O error writing page %d\n", outputpage);
275 /* write a whole page */
276 void writepage(int p)
278 seekpage(p);
279 writepageheader(pagelabel, p+1);
280 writepagebody(p);
283 /* write from start of file to end of header comments */
284 void writeheader(int p)
286 fseek(infile, 0L, SEEK_SET);
287 if (pagescmt) {
288 if (!fcopy(pagescmt) || fgets(buffer, BUFSIZ, infile) == NULL)
289 message(FATAL, "I/O error in header\n");
290 sprintf(buffer, "%%%%Pages: %d 0\n", p);
291 writestring(buffer);
293 if (!fcopy(headerpos))
294 message(FATAL, "I/O error in header\n");
297 /* write prologue to end of setup section excluding PStoPS procset */
298 int writepartprolog(void)
300 if (beginprocset && !fcopy(beginprocset))
301 message(FATAL, "I/O error in prologue\n");
302 if (endprocset)
303 fseek(infile, endprocset, SEEK_SET);
304 writeprolog();
305 return !beginprocset;
308 /* write prologue up to end of setup section */
309 void writeprolog(void)
311 if (!fcopy(endsetup))
312 message(FATAL, "I/O error in prologue\n");
315 /* write from end of setup to start of pages */
316 void writesetup(void)
318 if (!fcopy(pageptr[0]))
319 message(FATAL, "I/O error in prologue\n");
322 /* write trailer */
323 void writetrailer(void)
325 fseek(infile, pageptr[pages], SEEK_SET);
326 while (fgets(buffer, BUFSIZ, infile) != NULL) {
327 writestring(buffer);
329 if (verbose)
330 message(LOG, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
333 /* write a page with nothing on it */
334 void writeemptypage(void)
336 if (verbose)
337 message(LOG, "[*] ");
338 sprintf(buffer, "%%%%Page: * %d\n", ++outputpage);
339 writestring(buffer);
340 if (beginprocset)
341 writestring("PStoPSxform concat\n");
342 writestring("showpage\n");