1 /* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved.
2
3 This file is part of GSview.
4
5 This file is distributed in the hope that it will be useful, but
6 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
7 to anyone for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing. Refer
9 to the GNU General Public License for full details.
10
11 Everyone is granted permission to copy, modify and redistribute this
12 file, but only under the conditions described in the GNU General
13 Public License. A copy of this license is supposed to have been given
14 to you along with this file so you can know your rights and
15 responsibilities. It should be in a file named COPYING. Among other
16 things, the copyright notice and this notice must be preserved on all
17 copies.
18 */
19
20 /* $Id$ */
21
22 /* dscparse.c - DSC parser */
23
24 /*
25 * This is a DSC parser, based on the DSC 3.0 spec,
26 * with a few DSC 2.1 additions for page size.
27 *
28 * Current limitations:
29 * %%+ may be used after any comment in the comment or trailer,
30 * but is currently only supported by
31 * %%DocumentMedia
32 *
33 * DSC 2.1 additions (discontinued in DSC 3.0):
34 * %%DocumentPaperColors:
35 * %%DocumentPaperForms:
36 * %%DocumentPaperSizes:
37 * %%DocumentPaperWeights:
38 * %%PaperColor: (ignored)
39 * %%PaperForm: (ignored)
40 * %%PaperSize:
41 * %%PaperWeight: (ignored)
42 *
43 * Other additions for defaults or page section
44 % %%ViewingOrientation: xx xy yx yy
45 */
46
47 #include <stdio.h> /* for sprintf(), not file I/O */
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ctype.h>
51
52 #define MAXSTR 256
53
54 #include "dscparse.h"
55
56 /* Macros for comparing string literals
57 * For maximum speed, the length of the second macro argument is
58 * computed at compile time.
59 * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
60 */
61 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
62 #define IS_DSC(line, str) (COMPARE((line), (str)))
63
64 /* Macros for comparing the first one or two characters */
65 #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
66 #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
67 #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
68 #define IS_BLANK(str) (IS_EOL(str[0]))
69 #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
70
71 /* Macros for document offset to start and end of line */
72 #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
73 #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
74
75 /* dsc_scan_SECTION() functions return one of
76 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
77 * or one of the following
78 */
79 /* The line should be passed on to the next section parser. */
80 #define CDSC_PROPAGATE 10
81
82 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
83 #define CDSC_NEEDMORE 11
84
85 /* local prototypes */
86 dsc_private void * dsc_memalloc(P2(CDSC *dsc, size_t size));
87 dsc_private void dsc_memfree(P2(CDSC*dsc, void *ptr));
88 dsc_private CDSC * dsc_init2(P1(CDSC *dsc));
89 dsc_private void dsc_reset(P1(CDSC *dsc));
90 dsc_private void dsc_section_join(P3(unsigned long begin, unsigned long *pend, unsigned long **pplast));
91 dsc_private int dsc_read_line(P1(CDSC *dsc));
92 dsc_private int dsc_read_doseps(P1(CDSC *dsc));
93 dsc_private char * dsc_alloc_string(P3(CDSC *dsc, const char *str, int len));
94 dsc_private char * dsc_add_line(P3(CDSC *dsc, const char *line, unsigned int len));
95 dsc_private char * dsc_copy_string(P5(char *str, unsigned int slen,
96 char *line, unsigned int len, unsigned int *offset));
97 dsc_private GSDWORD dsc_get_dword(P1(const unsigned char *buf));
98 dsc_private GSWORD dsc_get_word(P1(const unsigned char *buf));
99 dsc_private int dsc_get_int(P3(const char *line, unsigned int len, unsigned int *offset));
100 dsc_private float dsc_get_real(P3(const char *line, unsigned int len,
101 unsigned int *offset));
102 dsc_private int dsc_stricmp(P2(const char *s, const char *t));
103 dsc_private void dsc_unknown(P1(CDSC *dsc));
104 dsc_private GSBOOL dsc_is_section(char *line);
105 dsc_private int dsc_parse_pages(P1(CDSC *dsc));
106 dsc_private int dsc_parse_bounding_box(P3(CDSC *dsc, CDSCBBOX** pbbox, int offset));
107 dsc_private int dsc_parse_float_bounding_box(P3(CDSC *dsc, CDSCFBBOX** pfbbox, int offset));
108 dsc_private int dsc_parse_orientation(P3(CDSC *dsc, unsigned int *porientation,
109 int offset));
110 dsc_private int dsc_parse_order(P1(CDSC *dsc));
111 dsc_private int dsc_parse_media(P2(CDSC *dsc, const CDSCMEDIA **page_media));
112 dsc_private int dsc_parse_document_media(P1(CDSC *dsc));
113 dsc_private int dsc_parse_viewing_orientation(P2(CDSC *dsc, CDSCCTM **pctm));
114 dsc_private int dsc_parse_page(P1(CDSC *dsc));
115 dsc_private void dsc_save_line(P1(CDSC *dsc));
116 dsc_private int dsc_scan_type(P1(CDSC *dsc));
117 dsc_private int dsc_scan_comments(P1(CDSC *dsc));
118 dsc_private int dsc_scan_preview(P1(CDSC *dsc));
119 dsc_private int dsc_scan_defaults(P1(CDSC *dsc));
120 dsc_private int dsc_scan_prolog(P1(CDSC *dsc));
121 dsc_private int dsc_scan_setup(P1(CDSC *dsc));
122 dsc_private int dsc_scan_page(P1(CDSC *dsc));
123 dsc_private int dsc_scan_trailer(P1(CDSC *dsc));
124 dsc_private int dsc_error(P4(CDSC *dsc, unsigned int explanation,
125 char *line, unsigned int line_len));
126
127 /* DSC error reporting */
128 dsc_private const int dsc_severity[] = {
129 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */
130 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */
131 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */
132 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
133 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */
134 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */
135 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */
136 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */
137 CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */
138 CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */
139 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */
140 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */
141 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */
142 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */
143 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */
144 CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */
145 0
146 };
147
148 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
149
150 const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = {
151 /* These sizes taken from Ghostscript gs_statd.ps */
152 {"11x17", 792, 1224, 0, NULL, NULL, NULL},
153 {"A0", 2380, 3368, 0, NULL, NULL, NULL},
154 {"A1", 1684, 2380, 0, NULL, NULL, NULL},
155 {"A2", 1190, 1684, 0, NULL, NULL, NULL},
156 {"A3", 842, 1190, 0, NULL, NULL, NULL},
157 {"A4", 595, 842, 0, NULL, NULL, NULL},
158 {"A5", 421, 595, 0, NULL, NULL, NULL},
159 {"A6", 297, 421, 0, NULL, NULL, NULL},
160 {"A7", 210, 297, 0, NULL, NULL, NULL},
161 {"A8", 148, 210, 0, NULL, NULL, NULL},
162 {"A9", 105, 148, 0, NULL, NULL, NULL},
163 {"A10", 74, 105, 0, NULL, NULL, NULL},
164 {"B0", 2836, 4008, 0, NULL, NULL, NULL},
165 {"B1", 2004, 2836, 0, NULL, NULL, NULL},
166 {"B2", 1418, 2004, 0, NULL, NULL, NULL},
167 {"B3", 1002, 1418, 0, NULL, NULL, NULL},
168 {"B4", 709, 1002, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */
169 {"B5", 501, 709, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */
170 {"B6", 354, 501, 0, NULL, NULL, NULL},
171 {"C0", 2600, 3677, 0, NULL, NULL, NULL},
172 {"C1", 1837, 2600, 0, NULL, NULL, NULL},
173 {"C2", 1298, 1837, 0, NULL, NULL, NULL},
174 {"C3", 918, 1298, 0, NULL, NULL, NULL},
175 {"C4", 649, 918, 0, NULL, NULL, NULL},
176 {"C5", 459, 649, 0, NULL, NULL, NULL},
177 {"C6", 323, 459, 0, NULL, NULL, NULL},
178 {"Ledger", 1224, 792, 0, NULL, NULL, NULL},
179 {"Legal", 612, 1008, 0, NULL, NULL, NULL},
180 {"Letter", 612, 792, 0, NULL, NULL, NULL},
181 {"Note", 612, 792, 0, NULL, NULL, NULL},
182 // ISO and JIS B sizes are different....
183 {"jisb0", 2916, 4128, 0, NULL, NULL, NULL},
184 {"jisb1", 2064, 2916, 0, NULL, NULL, NULL},
185 {"jisb2", 1458, 2064, 0, NULL, NULL, NULL},
186 {"jisb3", 1032, 1458, 0, NULL, NULL, NULL},
187 {"jisb4", 729, 1032, 0, NULL, NULL, NULL},
188 {"jisb5", 516, 729, 0, NULL, NULL, NULL},
189 {"jisb6", 363, 516, 0, NULL, NULL, NULL},
190 // U.S. CAD standard paper sizes
191 {"archE", 2592, 3456, 0, NULL, NULL, NULL},
192 {"archD", 1728, 2592, 0, NULL, NULL, NULL},
193 {"archC", 1296, 1728, 0, NULL, NULL, NULL},
194 {"archB", 864, 1296, 0, NULL, NULL, NULL},
195 {"archA", 648, 864, 0, NULL, NULL, NULL},
196 // Other paper sizes
197 {"flsa", 612, 936, 0, NULL, NULL, NULL}, /* U.S. foolscap */
198 {"flse", 612, 936, 0, NULL, NULL, NULL}, /* European foolscap */
199 {"halfletter", 396, 612, 0, NULL, NULL, NULL},
200 {NULL, 0, 0, 0, NULL, NULL, NULL}
201 };
202
203 /* parser state */
204 enum CDSC_SCAN_SECTION {
205 scan_none = 0,
206 scan_comments = 1,
207 scan_pre_preview = 2,
208 scan_preview = 3,
209 scan_pre_defaults = 4,
210 scan_defaults = 5,
211 scan_pre_prolog = 6,
212 scan_prolog = 7,
213 scan_pre_setup = 8,
214 scan_setup = 9,
215 scan_pre_pages = 10,
216 scan_pages = 11,
217 scan_pre_trailer = 12,
218 scan_trailer = 13,
219 scan_eof = 14
220 };
221
222 static const char * const dsc_scan_section_name[15] = {
223 "Type", "Comments",
224 "pre-Preview", "Preview",
225 "pre-Defaults", "Defaults",
226 "pre-Prolog", "Prolog",
227 "pre-Setup", "Setup",
228 "pre-Page", "Page",
229 "pre-Trailer", "Trailer",
230 "EOF"
231 };
232
233 /******************************************************************/
234 /* Public functions */
235 /******************************************************************/
236
237 /* constructor */
238 CDSC *
dsc_init(void * caller_data)239 dsc_init(void *caller_data)
240 {
241 CDSC *dsc = (CDSC *)malloc(sizeof(CDSC));
242 if (dsc == NULL)
243 return NULL;
244 memset(dsc, 0, sizeof(CDSC));
245 dsc->caller_data = caller_data;
246
247 return dsc_init2(dsc);
248 }
249
250 /* constructor, with caller supplied memalloc */
251 CDSC *
dsc_init_with_alloc(void * caller_data,void * (* memalloc)(size_t size,void * closure_data),void (* memfree)(void * ptr,void * closure_data),void * closure_data)252 dsc_init_with_alloc(
253 void *caller_data,
254 void *(*memalloc)(size_t size, void *closure_data),
255 void (*memfree)(void *ptr, void *closure_data),
256 void *closure_data)
257 {
258 CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
259 if (dsc == NULL)
260 return NULL;
261 memset(dsc, 0, sizeof(CDSC));
262 dsc->caller_data = caller_data;
263
264 dsc->memalloc = memalloc;
265 dsc->memfree = memfree;
266 dsc->mem_closure_data = closure_data;
267
268 return dsc_init2(dsc);
269 }
270
271
272
273 /* destructor */
274 void
dsc_free(CDSC * dsc)275 dsc_free(CDSC *dsc)
276 {
277 if (dsc == NULL)
278 return;
279 dsc_reset(dsc);
280 dsc_memfree(dsc, dsc);
281 }
282
283
284 /* Tell DSC parser how long document will be, to allow ignoring
285 * of early %%Trailer and %%EOF. This is optional.
286 */
287 void
dsc_set_length(CDSC * dsc,unsigned long len)288 dsc_set_length(CDSC *dsc, unsigned long len)
289 {
290 dsc->file_length = len;
291 }
292
293 /* Process a buffer containing DSC comments and PostScript */
294 /* Return value is < 0 for error, >=0 for OK.
295 * CDSC_ERROR
296 * CDSC_OK
297 * CDSC_NOTDSC (DSC will be ignored)
298 * other values indicate the last DSC comment read
299 */
300 int
dsc_scan_data(CDSC * dsc,const char * data,int length)301 dsc_scan_data(CDSC *dsc, const char *data, int length)
302 {
303 int bytes_read;
304 int code = 0;
305
306 if (dsc == NULL)
307 return CDSC_ERROR;
308
309 if (dsc->id == CDSC_NOTDSC)
310 return CDSC_NOTDSC;
311 dsc->id = CDSC_OK;
312 if (dsc->eof)
313 return CDSC_OK; /* ignore */
314
315 if (length == 0) {
316 /* EOF, so process what remains */
317 dsc->eof = TRUE;
318 }
319
320 do {
321 if (dsc->id == CDSC_NOTDSC)
322 break;
323
324 if (length != 0) {
325 /* move existing data if needed */
326 if (dsc->data_length > CDSC_DATA_LENGTH/2) {
327 memmove(dsc->data, dsc->data + dsc->data_index,
328 dsc->data_length - dsc->data_index);
329 dsc->data_offset += dsc->data_index;
330 dsc->data_length -= dsc->data_index;
331 dsc->data_index = 0;
332 }
333 /* append to buffer */
334 bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
335 memcpy(dsc->data + dsc->data_length, data, bytes_read);
336 dsc->data_length += bytes_read;
337 data += bytes_read;
338 length -= bytes_read;
339 }
340 if (dsc->scan_section == scan_none) {
341 code = dsc_scan_type(dsc);
342 if (code == CDSC_NEEDMORE) {
343 /* need more characters before we can identify type */
344 code = CDSC_OK;
345 break;
346 }
347 dsc->id = code;
348 }
349
350 if (code == CDSC_NOTDSC) {
351 dsc->id = CDSC_NOTDSC;
352 break;
353 }
354
355 while ((code = dsc_read_line(dsc)) > 0) {
356 if (dsc->id == CDSC_NOTDSC)
357 break;
358 if (dsc->doseps_end &&
359 (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
360 /* have read past end of DOS EPS PostScript section */
361 return CDSC_OK; /* ignore */
362 }
363 if (dsc->eof)
364 return CDSC_OK;
365 if (dsc->skip_document)
366 continue; /* embedded document */
367 if (dsc->skip_lines)
368 continue; /* embedded lines */
369 if (IS_DSC(dsc->line, "%%BeginData:"))
370 continue;
371 if (IS_DSC(dsc->line, "%%BeginBinary:"))
372 continue;
373 if (IS_DSC(dsc->line, "%%EndDocument"))
374 continue;
375 if (IS_DSC(dsc->line, "%%EndData"))
376 continue;
377 if (IS_DSC(dsc->line, "%%EndBinary"))
378 continue;
379
380 do {
381 switch (dsc->scan_section) {
382 case scan_comments:
383 code = dsc_scan_comments(dsc);
384 break;
385 case scan_pre_preview:
386 case scan_preview:
387 code = dsc_scan_preview(dsc);
388 break;
389 case scan_pre_defaults:
390 case scan_defaults:
391 code = dsc_scan_defaults(dsc);
392 break;
393 case scan_pre_prolog:
394 case scan_prolog:
395 code = dsc_scan_prolog(dsc);
396 break;
397 case scan_pre_setup:
398 case scan_setup:
399 code = dsc_scan_setup(dsc);
400 break;
401 case scan_pre_pages:
402 case scan_pages:
403 code = dsc_scan_page(dsc);
404 break;
405 case scan_pre_trailer:
406 case scan_trailer:
407 code = dsc_scan_trailer(dsc);
408 break;
409 case scan_eof:
410 code = CDSC_OK;
411 break;
412 default:
413 /* invalid state */
414 code = CDSC_ERROR;
415 }
416 /* repeat if line is start of next section */
417 } while (code == CDSC_PROPAGATE);
418
419 /* if DOS EPS header not complete, ask for more */
420 if (code == CDSC_NEEDMORE) {
421 code = CDSC_OK;
422 break;
423 }
424 if (code == CDSC_NOTDSC) {
425 dsc->id = CDSC_NOTDSC;
426 break;
427 }
428 }
429 } while (length != 0);
430
431 return (code < 0) ? code : dsc->id;
432 }
433
434 /* Tidy up from incorrect DSC comments */
435 int
dsc_fixup(CDSC * dsc)436 dsc_fixup(CDSC *dsc)
437 {
438 unsigned int i;
439 char buf[32];
440 unsigned long *last;
441
442 if (dsc->id == CDSC_NOTDSC)
443 return 0;
444
445 /* flush last partial line */
446 dsc_scan_data(dsc, NULL, 0);
447
448 /* Fix DSC error: code between %%EndSetup and %%Page */
449 if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup)
450 && (dsc->endsetup != dsc->beginsetup)) {
451 dsc->endsetup = dsc->page[0].begin;
452 dsc_debug_print(dsc, "Warning: code included between setup and first page\n");
453 }
454
455 /* Last page contained a false trailer, */
456 /* so extend last page to start of trailer */
457 if (dsc->page_count && (dsc->begintrailer != 0) &&
458 (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) {
459 dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n");
460 dsc_debug_print(dsc, "and extending last page to start of trailer\n");
461 dsc->page[dsc->page_count-1].end = dsc->begintrailer;
462 }
463
464 /*
465 * Join up all sections.
466 * There might be extra code between them, or we might have
467 * missed including the \n which followed \r.
468 */
469 last = &dsc->endcomments;
470 dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last);
471 dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last);
472 dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last);
473 dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
474 for (i=0; i<dsc->page_count; i++)
475 dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last);
476 if (dsc->begintrailer)
477 *last = dsc->begintrailer;
478
479 if ((dsc->page_pages == 0) && (dsc->page_count == 1)) {
480 /* don't flag an error if %%Pages absent but one %%Page found */
481 /* adjust incorrect page count */
482 dsc->page_pages = dsc->page_count;
483 }
484
485 /* Warnings and Errors that we can now identify */
486 if ((dsc->page_count != dsc->page_pages)) {
487 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0);
488 switch (rc) {
489 case CDSC_RESPONSE_OK:
490 /* adjust incorrect page count */
491 dsc->page_pages = dsc->page_count;
492 break;
493 case CDSC_RESPONSE_CANCEL:
494 break;;
495 case CDSC_RESPONSE_IGNORE_ALL:
496 return CDSC_NOTDSC;
497 }
498 }
499
500 if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) {
501 /* EPS files MUST include a BoundingBox */
502 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0);
503 switch (rc) {
504 case CDSC_RESPONSE_OK:
505 /* Assume that it is EPS */
506 break;
507 case CDSC_RESPONSE_CANCEL:
508 /* Is NOT an EPS file */
509 dsc->epsf = FALSE;
510 case CDSC_RESPONSE_IGNORE_ALL:
511 return CDSC_NOTDSC;
512 }
513 }
514
515 if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) {
516 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0);
517 switch (rc) {
518 case CDSC_RESPONSE_OK:
519 /* Is an EPS file */
520 break;
521 case CDSC_RESPONSE_CANCEL:
522 /* Is NOT an EPS file */
523 dsc->epsf = FALSE;
524 break;
525 case CDSC_RESPONSE_IGNORE_ALL:
526 return CDSC_NOTDSC;
527 }
528 }
529
530 if ((dsc->media_count == 1) && (dsc->page_media == NULL)) {
531 /* if one only media was specified, and default page media */
532 /* was not specified, assume that default is the only media. */
533 dsc->page_media = dsc->media[0];
534 }
535
536 if ((dsc->media_count != 0) && (dsc->page_media == NULL)) {
537 int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0);
538 switch (rc) {
539 case CDSC_RESPONSE_OK:
540 /* default media is first listed */
541 dsc->page_media = dsc->media[0];
542 break;
543 case CDSC_RESPONSE_CANCEL:
544 /* No default media */
545 break;
546 case CDSC_RESPONSE_IGNORE_ALL:
547 return CDSC_NOTDSC;
548 }
549 }
550
551 /* make sure all pages have a label */
552 for (i=0; i<dsc->page_count; i++) {
553 if (strlen(dsc->page[i].label) == 0) {
554 sprintf(buf, "%d", i+1);
555 if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, strlen(buf)))
556 == (char *)NULL)
557 return CDSC_ERROR; /* no memory */
558 }
559 }
560 return CDSC_OK;
561 }
562
563 /* Install a function to be used for displaying messages about
564 * DSC errors and warnings, and to request advice from user.
565 * Installing an error function is optional.
566 */
567 void
dsc_set_error_function(CDSC * dsc,int (* fn)(P5 (void * caller_data,CDSC * dsc,unsigned int explanation,const char * line,unsigned int line_len)))568 dsc_set_error_function(CDSC *dsc,
569 int (*fn)(P5(void *caller_data, CDSC *dsc,
570 unsigned int explanation, const char *line, unsigned int line_len)))
571 {
572 dsc->dsc_error_fn = fn;
573 }
574
575
576 /* Install a function for printing debug messages */
577 /* This is optional */
578 void
dsc_set_debug_function(CDSC * dsc,void (* debug_fn)(P2 (void * caller_data,const char * str)))579 dsc_set_debug_function(CDSC *dsc,
580 void (*debug_fn)(P2(void *caller_data, const char *str)))
581 {
582 dsc->debug_print_fn = debug_fn;
583 }
584
585 /* Doesn't need to be public for PostScript documents */
586 /* Made public so GSview can add pages when processing PDF files */
587 int
dsc_add_page(CDSC * dsc,int ordinal,char * label)588 dsc_add_page(CDSC *dsc, int ordinal, char *label)
589 {
590 dsc->page[dsc->page_count].ordinal = ordinal;
591 dsc->page[dsc->page_count].label =
592 dsc_alloc_string(dsc, label, strlen(label)+1);
593 dsc->page[dsc->page_count].begin = 0;
594 dsc->page[dsc->page_count].end = 0;
595 dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
596 dsc->page[dsc->page_count].media = NULL;
597 dsc->page[dsc->page_count].bbox = NULL;
598 dsc->page[dsc->page_count].viewing_orientation = NULL;
599
600 dsc->page_count++;
601 if (dsc->page_count >= dsc->page_chunk_length) {
602 CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc,
603 (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE));
604 if (new_page == NULL)
605 return CDSC_ERROR; /* out of memory */
606 memcpy(new_page, dsc->page,
607 dsc->page_count * sizeof(CDSCPAGE));
608 dsc_memfree(dsc, dsc->page);
609 dsc->page= new_page;
610 dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count;
611 }
612 return CDSC_OK;
613 }
614
615 /* Doesn't need to be public for PostScript documents */
616 /* Made public so GSview can store PDF MediaBox */
617 int
dsc_add_media(CDSC * dsc,CDSCMEDIA * media)618 dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
619 {
620 CDSCMEDIA **newmedia_array;
621 CDSCMEDIA *newmedia;
622
623 /* extend media array */
624 newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc,
625 (dsc->media_count + 1) * sizeof(CDSCMEDIA *));
626 if (newmedia_array == NULL)
627 return CDSC_ERROR; /* out of memory */
628 if (dsc->media != NULL) {
629 memcpy(newmedia_array, dsc->media,
630 dsc->media_count * sizeof(CDSCMEDIA *));
631 dsc_memfree(dsc, dsc->media);
632 }
633 dsc->media = newmedia_array;
634
635 /* allocate new media */
636 newmedia = dsc->media[dsc->media_count] =
637 (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA));
638 if (newmedia == NULL)
639 return CDSC_ERROR; /* out of memory */
640 newmedia->name = NULL;
641 newmedia->width = 595.0;
642 newmedia->height = 842.0;
643 newmedia->weight = 80.0;
644 newmedia->colour = NULL;
645 newmedia->type = NULL;
646 newmedia->mediabox = NULL;
647
648 dsc->media_count++;
649
650 if (media->name) {
651 newmedia->name = dsc_alloc_string(dsc, media->name,
652 strlen(media->name));
653 if (newmedia->name == NULL)
654 return CDSC_ERROR; /* no memory */
655 }
656 newmedia->width = media->width;
657 newmedia->height = media->height;
658 newmedia->weight = media->weight;
659 if (media->colour) {
660 newmedia->colour = dsc_alloc_string(dsc, media->colour,
661 strlen(media->colour));
662 if (newmedia->colour == NULL)
663 return CDSC_ERROR; /* no memory */
664 }
665 if (media->type) {
666 newmedia->type = dsc_alloc_string(dsc, media->type,
667 strlen(media->type));
668 if (newmedia->type == NULL)
669 return CDSC_ERROR; /* no memory */
670 }
671 newmedia->mediabox = NULL;
672
673 if (media->mediabox) {
674 newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
675 if (newmedia->mediabox == NULL)
676 return CDSC_ERROR; /* no memory */
677 *newmedia->mediabox = *media->mediabox;
678 }
679 return CDSC_OK;
680 }
681
682 /* Doesn't need to be public for PostScript documents */
683 /* Made public so GSview can store PDF CropBox */
684 int
dsc_set_page_bbox(CDSC * dsc,unsigned int page_number,int llx,int lly,int urx,int ury)685 dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
686 int llx, int lly, int urx, int ury)
687 {
688 CDSCBBOX *bbox;
689 if (page_number >= dsc->page_count)
690 return CDSC_ERROR;
691 bbox = dsc->page[page_number].bbox;
692 if (bbox == NULL)
693 dsc->page[page_number].bbox = bbox =
694 (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
695 if (bbox == NULL)
696 return CDSC_ERROR;
697 bbox->llx = llx;
698 bbox->lly = lly;
699 bbox->urx = urx;
700 bbox->ury = ury;
701 return CDSC_OK;
702 }
703
704
705 /******************************************************************/
706 /* Private functions below here. */
707 /******************************************************************/
708
709 dsc_private void *
dsc_memalloc(CDSC * dsc,size_t size)710 dsc_memalloc(CDSC *dsc, size_t size)
711 {
712 if (dsc->memalloc)
713 return dsc->memalloc(size, dsc->mem_closure_data);
714 return malloc(size);
715 }
716
717 dsc_private void
dsc_memfree(CDSC * dsc,void * ptr)718 dsc_memfree(CDSC*dsc, void *ptr)
719 {
720 if (dsc->memfree)
721 dsc->memfree(ptr, dsc->mem_closure_data);
722 else
723 free(ptr);
724 }
725
726 /* private constructor */
727 dsc_private CDSC *
dsc_init2(CDSC * dsc)728 dsc_init2(CDSC *dsc)
729 {
730 dsc_reset(dsc);
731
732 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
733 if (dsc->string_head == NULL) {
734 dsc_free(dsc);
735 return NULL; /* no memory */
736 }
737 dsc->string = dsc->string_head;
738 dsc->string->next = NULL;
739 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
740 if (dsc->string->data == NULL) {
741 dsc_free(dsc);
742 return NULL; /* no memory */
743 }
744 dsc->string->index = 0;
745 dsc->string->length = CDSC_STRING_CHUNK;
746
747 dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
748 if (dsc->page == NULL) {
749 dsc_free(dsc);
750 return NULL; /* no memory */
751 }
752 dsc->page_chunk_length = CDSC_PAGE_CHUNK;
753 dsc->page_count = 0;
754
755 dsc->line = NULL;
756 dsc->data_length = 0;
757 dsc->data_index = dsc->data_length;
758
759 return dsc;
760 }
761
762
763 dsc_private void
dsc_reset(CDSC * dsc)764 dsc_reset(CDSC *dsc)
765 {
766 unsigned int i;
767 /* Clear public members */
768 dsc->dsc = FALSE;
769 dsc->ctrld = FALSE;
770 dsc->pjl = FALSE;
771 dsc->epsf = FALSE;
772 dsc->pdf = FALSE;
773 dsc->epsf = FALSE;
774 dsc->preview = CDSC_NOPREVIEW;
775 dsc->dsc_version = NULL; /* stored in dsc->string */
776 dsc->language_level = 0;
777 dsc->document_data = CDSC_DATA_UNKNOWN;
778 dsc->begincomments = 0;
779 dsc->endcomments = 0;
780 dsc->beginpreview = 0;
781 dsc->endpreview = 0;
782 dsc->begindefaults = 0;
783 dsc->enddefaults = 0;
784 dsc->beginprolog = 0;
785 dsc->endprolog = 0;
786 dsc->beginsetup = 0;
787 dsc->endsetup = 0;
788 dsc->begintrailer = 0;
789 dsc->endtrailer = 0;
790
791 for (i=0; i<dsc->page_count; i++) {
792 /* page media is pointer to an element of media or dsc_known_media */
793 /* do not free it. */
794
795 if (dsc->page[i].bbox)
796 dsc_memfree(dsc, dsc->page[i].bbox);
797 if (dsc->page[i].viewing_orientation)
798 dsc_memfree(dsc, dsc->page[i].viewing_orientation);
799 }
800 if (dsc->page)
801 dsc_memfree(dsc, dsc->page);
802 dsc->page = NULL;
803
804 dsc->page_count = 0;
805 dsc->page_pages = 0;
806 dsc->page_order = CDSC_ORDER_UNKNOWN;
807 dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
808 if (dsc->viewing_orientation)
809 dsc_memfree(dsc, dsc->viewing_orientation);
810 dsc->viewing_orientation = NULL;
811
812 if (dsc->media) {
813 for (i=0; i<dsc->media_count; i++) {
814 if (dsc->media[i]) {
815 if (dsc->media[i]->mediabox)
816 dsc_memfree(dsc, dsc->media[i]->mediabox);
817 dsc_memfree(dsc, dsc->media[i]);
818 }
819 }
820 dsc_memfree(dsc, dsc->media);
821 }
822 dsc->media_count = 0;
823 dsc->media = NULL;
824
825 /* page_media is pointer to an element of media or dsc_known_media */
826 /* do not free it. */
827 dsc->page_media = NULL;
828
829 if (dsc->bbox)
830 dsc_memfree(dsc, dsc->bbox);
831 dsc->bbox = NULL;
832 if (dsc->page_bbox)
833 dsc_memfree(dsc, dsc->page_bbox);
834 dsc->page_bbox = NULL;
835 if (dsc->doseps)
836 dsc_memfree(dsc, dsc->doseps);
837 dsc->doseps = NULL;
838
839 dsc->dsc_title = NULL;
840 dsc->dsc_creator = NULL;
841 dsc->dsc_date = NULL;
842 dsc->dsc_for = NULL;
843
844
845 dsc->max_error = DSC_MAX_ERROR;
846 dsc->severity = dsc_severity;
847
848 /* Clear private members */
849 /* Don't touch dsc->caller_data */
850 dsc->id = CDSC_OK;
851 dsc->scan_section = scan_none;
852 dsc->doseps_end = 0;
853 dsc->page_chunk_length = 0;
854 dsc->file_length = 0;
855 dsc->skip_document = 0;
856 dsc->skip_bytes = 0;
857 dsc->skip_lines = 0;
858 dsc->skip_pjl = 0;
859 dsc->begin_font_count = 0;
860 dsc->begin_feature_count = 0;
861 dsc->begin_resource_count = 0;
862 dsc->begin_procset_count = 0;
863
864 dsc->data_length = 0;
865 dsc->data_index = 0;
866 dsc->data_offset = 0;
867
868 dsc->eof = 0;
869
870 dsc->line = 0;
871 dsc->line_length = 0;
872 dsc->eol = 0;
873 dsc->last_cr = FALSE;
874 dsc->line_count = 1;
875 dsc->long_line = FALSE;
876 memset(dsc->last_line, 0, sizeof(dsc->last_line));
877
878 dsc->string = dsc->string_head;
879 while (dsc->string != (CDSCSTRING *)NULL) {
880 if (dsc->string->data)
881 dsc_memfree(dsc, dsc->string->data);
882 dsc->string_head = dsc->string;
883 dsc->string = dsc->string->next;
884 dsc_memfree(dsc, dsc->string_head);
885 }
886 dsc->string_head = NULL;
887 dsc->string = NULL;
888
889 /* don't touch caller functions */
890
891 /* public data */
892 if (dsc->hires_bbox)
893 dsc_memfree(dsc, dsc->hires_bbox);
894 dsc->hires_bbox = NULL;
895 if (dsc->crop_box)
896 dsc_memfree(dsc, dsc->crop_box);
897 dsc->crop_box = NULL;
898 }
899
900 /*
901 * Join up all sections.
902 * There might be extra code between them, or we might have
903 * missed including the \n which followed \r.
904 * begin is the start of this section
905 * pend is a pointer to the end of this section
906 * pplast is a pointer to a pointer of the end of the previous section
907 */
908 dsc_private void
dsc_section_join(unsigned long begin,unsigned long * pend,unsigned long ** pplast)909 dsc_section_join(unsigned long begin, unsigned long *pend, unsigned long **pplast)
910 {
911 if (begin)
912 **pplast = begin;
913 if (*pend > begin)
914 *pplast = pend;
915 }
916
917
918 /* return value is 0 if no line available, or length of line */
919 dsc_private int
dsc_read_line(CDSC * dsc)920 dsc_read_line(CDSC *dsc)
921 {
922 char *p, *last;
923 dsc->line = NULL;
924
925 if (dsc->eof) {
926 /* return all that remains, even if line incomplete */
927 dsc->line = dsc->data + dsc->data_index;
928 dsc->line_length = dsc->data_length - dsc->data_index;
929 dsc->data_index = dsc->data_length;
930 return dsc->line_length;
931 }
932
933 /* ignore embedded bytes */
934 if (dsc->skip_bytes) {
935 int cnt = min(dsc->skip_bytes,
936 (int)(dsc->data_length - dsc->data_index));
937 dsc->skip_bytes -= cnt;
938 dsc->data_index += cnt;
939 if (dsc->skip_bytes != 0)
940 return 0;
941 }
942
943 do {
944 dsc->line = dsc->data + dsc->data_index;
945 last = dsc->data + dsc->data_length;
946 if (dsc->data_index == dsc->data_length) {
947 dsc->line_length = 0;
948 return 0;
949 }
950 if (dsc->eol) {
951 /* if previous line was complete, increment line count */
952 dsc->line_count++;
953 if (dsc->skip_lines)
954 dsc->skip_lines--;
955 }
956
957 /* skip over \n which followed \r */
958 if (dsc->last_cr && dsc->line[0] == '\n') {
959 dsc->data_index++;
960 dsc->line++;
961 }
962 dsc->last_cr = FALSE;
963
964 /* look for EOL */
965 dsc->eol = FALSE;
966 for (p = dsc->line; p < last; p++) {
967 if (*p == '\r') {
968 p++;
969 if ((p<last) && (*p == '\n'))
970 p++; /* include line feed also */
971 else
972 dsc->last_cr = TRUE; /* we might need to skip \n */
973 dsc->eol = TRUE; /* dsc->line is a complete line */
974 break;
975 }
976 if (*p == '\n') {
977 p++;
978 dsc->eol = TRUE; /* dsc->line is a complete line */
979 break;
980 }
981 if (*p == '\032') { /* MS-DOS Ctrl+Z */
982 dsc->eol = TRUE;
983 }
984 }
985 if (dsc->eol == FALSE) {
986 /* we haven't got a complete line yet */
987 if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) {
988 /* buffer is less than half full, ask for some more */
989 dsc->line_length = 0;
990 return 0;
991 }
992 }
993 dsc->data_index += dsc->line_length = (p - dsc->line);
994 } while (dsc->skip_lines && dsc->line_length);
995
996 if (dsc->line_length == 0)
997 return 0;
998
999 if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) {
1000 /* handle recursive %%BeginDocument */
1001 if ((dsc->skip_document) && dsc->line_length &&
1002 COMPARE(dsc->line, "%%EndDocument")) {
1003 dsc->skip_document--;
1004 }
1005
1006 /* handle embedded lines or binary data */
1007 if (COMPARE(dsc->line, "%%BeginData:")) {
1008 /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
1009 * <numberof> ::= <uint> (Lines or physical bytes)
1010 * <type> ::= Hex | Binary | ASCII (Type of data)
1011 * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
1012 */
1013 char begindata[MAXSTR+1];
1014 int cnt;
1015 unsigned int num;
1016 const char *numberof, *bytesorlines;
1017 if ((num = dsc->line_length) >= sizeof(begindata)-1)
1018 num = sizeof(begindata)-1;
1019
1020 memcpy(begindata, dsc->line, num);
1021 begindata[num] = '\0';
1022 numberof = strtok(begindata+12, " \r\n");
1023 strtok(NULL, " \r\n"); /* dump type */
1024 bytesorlines = strtok(NULL, " \r\n");
1025 if (bytesorlines == NULL)
1026 bytesorlines = "Bytes";
1027
1028 if ( (numberof == NULL) || (bytesorlines == NULL) ) {
1029 /* invalid usage of %%BeginData */
1030 /* ignore that we ever saw it */
1031 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE,
1032 dsc->line, dsc->line_length);
1033 switch (rc) {
1034 case CDSC_RESPONSE_OK:
1035 case CDSC_RESPONSE_CANCEL:
1036 break;
1037 case CDSC_RESPONSE_IGNORE_ALL:
1038 return 0;
1039 }
1040 }
1041 else {
1042 cnt = atoi(numberof);
1043 if (cnt) {
1044 if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) {
1045 /* skip cnt lines */
1046 if (dsc->skip_lines == 0) {
1047 /* we are not already skipping lines */
1048 dsc->skip_lines = cnt+1;
1049 }
1050 }
1051 else {
1052 /* byte count doesn't includes \n or \r\n */
1053 /* or \r of %%BeginData: */
1054 /* skip cnt bytes */
1055 if (dsc->skip_bytes == 0) {
1056 /* we are not already skipping lines */
1057 dsc->skip_bytes = cnt;
1058 }
1059
1060 }
1061 }
1062 }
1063 }
1064 else if (COMPARE(dsc->line, "%%BeginBinary:")) {
1065 /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
1066 unsigned long cnt = atoi(dsc->line + 14);
1067 if (dsc->skip_bytes == 0) {
1068 /* we are not already skipping lines */
1069 dsc->skip_bytes = cnt;
1070 }
1071 }
1072 }
1073
1074 if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
1075 COMPARE(dsc->line, "%%BeginDocument:") ) {
1076 /* Skip over embedded document, recursively */
1077 dsc->skip_document++;
1078 }
1079
1080 if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
1081 dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
1082 dsc->long_line = TRUE;
1083 }
1084
1085 return dsc->line_length;
1086 }
1087
1088
1089 /* Save last DSC line, for use with %%+ */
1090 dsc_private void
dsc_save_line(CDSC * dsc)1091 dsc_save_line(CDSC *dsc)
1092 {
1093 int len = min(sizeof(dsc->last_line), dsc->line_length);
1094 memcpy(dsc->last_line, dsc->line, len);
1095 }
1096
1097 /* display unknown DSC line */
1098 dsc_private void
dsc_unknown(CDSC * dsc)1099 dsc_unknown(CDSC *dsc)
1100 {
1101 if (dsc->debug_print_fn) {
1102 char line[DSC_LINE_LENGTH];
1103 unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
1104 sprintf(line, "Unknown in %s section at line %d:\n ",
1105 dsc_scan_section_name[dsc->scan_section], dsc->line_count);
1106 dsc_debug_print(dsc, line);
1107 strncpy(line, dsc->line, length);
1108 line[length] = '\0';
1109 dsc_debug_print(dsc, line);
1110 }
1111 }
1112
1113
1114 dsc_private GSBOOL
dsc_is_section(char * line)1115 dsc_is_section(char *line)
1116 {
1117 if ( !((line[0]=='%') && (line[1]=='%')) )
1118 return FALSE;
1119 if (IS_DSC(line, "%%BeginPreview"))
1120 return TRUE;
1121 if (IS_DSC(line, "%%BeginDefaults"))
1122 return TRUE;
1123 if (IS_DSC(line, "%%BeginProlog"))
1124 return TRUE;
1125 if (IS_DSC(line, "%%BeginSetup"))
1126 return TRUE;
1127 if (IS_DSC(line, "%%Page:"))
1128 return TRUE;
1129 if (IS_DSC(line, "%%Trailer"))
1130 return TRUE;
1131 if (IS_DSC(line, "%%EOF"))
1132 return TRUE;
1133 return FALSE;
1134 }
1135
1136
1137 dsc_private GSDWORD
dsc_get_dword(const unsigned char * buf)1138 dsc_get_dword(const unsigned char *buf)
1139 {
1140 GSDWORD dw;
1141 dw = (GSDWORD)buf[0];
1142 dw += ((GSDWORD)buf[1])<<8;
1143 dw += ((GSDWORD)buf[2])<<16;
1144 dw += ((GSDWORD)buf[3])<<24;
1145 return dw;
1146 }
1147
1148 dsc_private GSWORD
dsc_get_word(const unsigned char * buf)1149 dsc_get_word(const unsigned char *buf)
1150 {
1151 GSWORD w;
1152 w = (GSWORD)buf[0];
1153 w |= (GSWORD)(buf[1]<<8);
1154 return w;
1155 }
1156
1157 dsc_private int
dsc_read_doseps(CDSC * dsc)1158 dsc_read_doseps(CDSC *dsc)
1159 {
1160 unsigned char *line = (unsigned char *)dsc->line;
1161 if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL)
1162 return CDSC_ERROR; /* no memory */
1163
1164 dsc->doseps->ps_begin = dsc_get_dword(line+4);
1165 dsc->doseps->ps_length = dsc_get_dword(line+8);
1166 dsc->doseps->wmf_begin = dsc_get_dword(line+12);
1167 dsc->doseps->wmf_length = dsc_get_dword(line+16);
1168 dsc->doseps->tiff_begin = dsc_get_dword(line+20);
1169 dsc->doseps->tiff_length = dsc_get_dword(line+24);
1170 dsc->doseps->checksum = dsc_get_word(line+28);
1171
1172 dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
1173
1174 /* move data_index backwards to byte after doseps header */
1175 dsc->data_index -= dsc->line_length - 30;
1176 /* we haven't read a line of PostScript code yet */
1177 dsc->line_count = 0;
1178 /* skip from current position to start of PostScript section */
1179 dsc->skip_bytes = dsc->doseps->ps_begin - 30;
1180
1181 if (dsc->doseps->tiff_begin)
1182 dsc->preview = CDSC_TIFF;
1183 if (dsc->doseps->wmf_begin)
1184 dsc->preview = CDSC_WMF;
1185
1186 return CDSC_OK;
1187 }
1188
1189
1190
1191 dsc_private int
dsc_parse_pages(CDSC * dsc)1192 dsc_parse_pages(CDSC *dsc)
1193 {
1194 int ip, io;
1195 unsigned int i;
1196 char *p;
1197 int n;
1198 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
1199 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1200 dsc->line_length);
1201 switch (rc) {
1202 case CDSC_RESPONSE_OK:
1203 case CDSC_RESPONSE_CANCEL:
1204 return CDSC_OK; /* ignore duplicate comments in header */
1205 case CDSC_RESPONSE_IGNORE_ALL:
1206 return CDSC_NOTDSC;
1207 }
1208 }
1209 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
1210 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1211 dsc->line_length);
1212 switch (rc) {
1213 case CDSC_RESPONSE_OK:
1214 case CDSC_RESPONSE_CANCEL:
1215 break; /* use duplicate comments in header */
1216 case CDSC_RESPONSE_IGNORE_ALL:
1217 return CDSC_NOTDSC;
1218 }
1219 }
1220
1221 n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
1222 while (IS_WHITE(dsc->line[n]))
1223 n++;
1224 p = dsc->line + n;
1225 if (COMPARE(p, "atend")) {
1226 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
1227 switch (rc) {
1228 case CDSC_RESPONSE_OK:
1229 /* assume (atend) */
1230 /* we should mark it as deferred */
1231 break;
1232 case CDSC_RESPONSE_CANCEL:
1233 /* ignore it */
1234 break;
1235 case CDSC_RESPONSE_IGNORE_ALL:
1236 return CDSC_NOTDSC;
1237 }
1238 }
1239 else if (COMPARE(p, "(atend)")) {
1240 /* do nothing */
1241 /* we should mark it as deferred */
1242 }
1243 else {
1244 ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1245 if (i) {
1246 n+=i;
1247 dsc->page_pages = ip;
1248 io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1249 if (i) {
1250 /* DSC 2 uses extra integer to indicate page order */
1251 /* DSC 3 uses %%PageOrder: */
1252 if (dsc->page_order == CDSC_ORDER_UNKNOWN)
1253 switch (io) {
1254 case -1:
1255 dsc->page_order = CDSC_DESCEND;
1256 break;
1257 case 0:
1258 dsc->page_order = CDSC_SPECIAL;
1259 break;
1260 case 1:
1261 dsc->page_order = CDSC_ASCEND;
1262 break;
1263 }
1264 }
1265 }
1266 else {
1267 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
1268 dsc->line_length);
1269 switch (rc) {
1270 case CDSC_RESPONSE_OK:
1271 case CDSC_RESPONSE_CANCEL:
1272 /* ignore it */
1273 break;
1274 case CDSC_RESPONSE_IGNORE_ALL:
1275 return CDSC_NOTDSC;
1276 }
1277 }
1278 }
1279 return CDSC_OK;
1280 }
1281
1282 dsc_private int
dsc_parse_bounding_box(CDSC * dsc,CDSCBBOX ** pbbox,int offset)1283 dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
1284 {
1285 unsigned int i, n;
1286 int llx, lly, urx, ury;
1287 float fllx, flly, furx, fury;
1288 char *p;
1289 /* Process first %%BoundingBox: in comments, and last in trailer */
1290 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1291 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1292 dsc->line_length);
1293 switch (rc) {
1294 case CDSC_RESPONSE_OK:
1295 case CDSC_RESPONSE_CANCEL:
1296 return CDSC_OK; /* ignore duplicate comments in header */
1297 case CDSC_RESPONSE_IGNORE_ALL:
1298 return CDSC_NOTDSC;
1299 }
1300 }
1301 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1302 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1303 dsc->line_length);
1304 switch (rc) {
1305 case CDSC_RESPONSE_OK:
1306 case CDSC_RESPONSE_CANCEL:
1307 return CDSC_OK; /* ignore duplicate comments in header */
1308 case CDSC_RESPONSE_IGNORE_ALL:
1309 return CDSC_NOTDSC;
1310 }
1311 }
1312 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1313 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1314 dsc->line_length);
1315 switch (rc) {
1316 case CDSC_RESPONSE_OK:
1317 case CDSC_RESPONSE_CANCEL:
1318 break; /* use duplicate comments in trailer */
1319 case CDSC_RESPONSE_IGNORE_ALL:
1320 return CDSC_NOTDSC;
1321 }
1322 }
1323 if (*pbbox != NULL) {
1324 dsc_memfree(dsc, *pbbox);
1325 *pbbox = NULL;
1326 }
1327
1328 /* should only process first %%BoundingBox: */
1329
1330 while (IS_WHITE(dsc->line[offset]))
1331 offset++;
1332 p = dsc->line + offset;
1333
1334 if (COMPARE(p, "atend")) {
1335 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1336 dsc->line_length);
1337 switch (rc) {
1338 case CDSC_RESPONSE_OK:
1339 /* assume (atend) */
1340 /* we should mark it as deferred */
1341 break;
1342 case CDSC_RESPONSE_CANCEL:
1343 /* ignore it */
1344 break;
1345 case CDSC_RESPONSE_IGNORE_ALL:
1346 return CDSC_NOTDSC;
1347 }
1348 }
1349 else if (COMPARE(p, "(atend)")) {
1350 /* do nothing */
1351 /* we should mark it as deferred */
1352 }
1353 else {
1354 /* llx = */ lly = urx = ury = 0;
1355 n = offset;
1356 llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1357 n += i;
1358 if (i)
1359 lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1360 n += i;
1361 if (i)
1362 urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1363 n += i;
1364 if (i)
1365 ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1366 if (i) {
1367 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1368 if (*pbbox == NULL)
1369 return CDSC_ERROR; /* no memory */
1370 (*pbbox)->llx = llx;
1371 (*pbbox)->lly = lly;
1372 (*pbbox)->urx = urx;
1373 (*pbbox)->ury = ury;
1374 }
1375 else {
1376 int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
1377 dsc->line_length);
1378 switch (rc) {
1379 case CDSC_RESPONSE_OK:
1380 /* fllx = */ flly = furx = fury = 0.0;
1381 n = offset;
1382 n += i;
1383 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1384 n += i;
1385 if (i)
1386 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1387 n += i;
1388 if (i)
1389 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1390 n += i;
1391 if (i)
1392 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1393 if (i) {
1394 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1395 if (*pbbox == NULL) {
1396 return CDSC_ERROR; /* no memory */
1397 }
1398 (*pbbox)->llx = (int)fllx;
1399 (*pbbox)->lly = (int)flly;
1400 (*pbbox)->urx = (int)(furx+0.999);
1401 (*pbbox)->ury = (int)(fury+0.999);
1402 }
1403 return CDSC_OK;
1404 case CDSC_RESPONSE_CANCEL:
1405 return CDSC_OK;
1406 case CDSC_RESPONSE_IGNORE_ALL:
1407 return CDSC_NOTDSC;
1408 }
1409 }
1410 }
1411 return CDSC_OK;
1412 }
1413
1414 dsc_private int
dsc_parse_float_bounding_box(CDSC * dsc,CDSCFBBOX ** pbbox,int offset)1415 dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
1416 {
1417 unsigned int i, n;
1418 float fllx, flly, furx, fury;
1419 char *p;
1420 /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1421 * and last in trailer.
1422 */
1423 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1424 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1425 dsc->line_length);
1426 switch (rc) {
1427 case CDSC_RESPONSE_OK:
1428 case CDSC_RESPONSE_CANCEL:
1429 return CDSC_OK; /* ignore duplicate comments in header */
1430 case CDSC_RESPONSE_IGNORE_ALL:
1431 return CDSC_NOTDSC;
1432 }
1433 }
1434 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1435 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1436 dsc->line_length);
1437 switch (rc) {
1438 case CDSC_RESPONSE_OK:
1439 case CDSC_RESPONSE_CANCEL:
1440 return CDSC_OK; /* ignore duplicate comments in header */
1441 case CDSC_RESPONSE_IGNORE_ALL:
1442 return CDSC_NOTDSC;
1443 }
1444 }
1445 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1446 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1447 dsc->line_length);
1448 switch (rc) {
1449 case CDSC_RESPONSE_OK:
1450 case CDSC_RESPONSE_CANCEL:
1451 break; /* use duplicate comments in trailer */
1452 case CDSC_RESPONSE_IGNORE_ALL:
1453 return CDSC_NOTDSC;
1454 }
1455 }
1456 if (*pbbox != NULL) {
1457 dsc_memfree(dsc, *pbbox);
1458 *pbbox = NULL;
1459 }
1460
1461 /* should only process first %%BoundingBox: */
1462
1463 while (IS_WHITE(dsc->line[offset]))
1464 offset++;
1465 p = dsc->line + offset;
1466
1467 if (COMPARE(p, "atend")) {
1468 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1469 dsc->line_length);
1470 switch (rc) {
1471 case CDSC_RESPONSE_OK:
1472 /* assume (atend) */
1473 /* we should mark it as deferred */
1474 break;
1475 case CDSC_RESPONSE_CANCEL:
1476 /* ignore it */
1477 break;
1478 case CDSC_RESPONSE_IGNORE_ALL:
1479 return CDSC_NOTDSC;
1480 }
1481 }
1482 else if (COMPARE(p, "(atend)")) {
1483 /* do nothing */
1484 /* we should mark it as deferred */
1485 }
1486 else {
1487 /* fllx = */ flly = furx = fury = 0.0;
1488 n = offset;
1489 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1490 n += i;
1491 if (i)
1492 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1493 n += i;
1494 if (i)
1495 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1496 n += i;
1497 if (i)
1498 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1499 if (i) {
1500 *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
1501 if (*pbbox == NULL)
1502 return CDSC_ERROR; /* no memory */
1503 (*pbbox)->fllx = fllx;
1504 (*pbbox)->flly = flly;
1505 (*pbbox)->furx = furx;
1506 (*pbbox)->fury = fury;
1507 }
1508 }
1509 return CDSC_OK;
1510 }
1511
1512 dsc_private int
dsc_parse_orientation(CDSC * dsc,unsigned int * porientation,int offset)1513 dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
1514 {
1515 char *p;
1516 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1517 (dsc->scan_section == scan_comments)) {
1518 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1519 dsc->line_length);
1520 switch (rc) {
1521 case CDSC_RESPONSE_OK:
1522 case CDSC_RESPONSE_CANCEL:
1523 return CDSC_OK; /* ignore duplicate comments in header */
1524 case CDSC_RESPONSE_IGNORE_ALL:
1525 return CDSC_NOTDSC;
1526 }
1527 }
1528 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1529 (dsc->scan_section == scan_trailer)) {
1530 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1531 dsc->line_length);
1532 switch (rc) {
1533 case CDSC_RESPONSE_OK:
1534 case CDSC_RESPONSE_CANCEL:
1535 break; /* use duplicate comments in header; */
1536 case CDSC_RESPONSE_IGNORE_ALL:
1537 return CDSC_NOTDSC;
1538 }
1539 }
1540 p = dsc->line + offset;
1541 while (IS_WHITE(*p))
1542 p++;
1543 if (COMPARE(p, "atend")) {
1544 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
1545 switch (rc) {
1546 case CDSC_RESPONSE_OK:
1547 /* assume (atend) */
1548 /* we should mark it as deferred */
1549 break;
1550 case CDSC_RESPONSE_CANCEL:
1551 /* ignore it */
1552 break;
1553 case CDSC_RESPONSE_IGNORE_ALL:
1554 return CDSC_NOTDSC;
1555 }
1556 }
1557 else if (COMPARE(p, "(atend)")) {
1558 /* do nothing */
1559 /* we should mark it as deferred */
1560 }
1561 else if (COMPARE(p, "Portrait")) {
1562 *porientation = CDSC_PORTRAIT;
1563 }
1564 else if (COMPARE(p, "Landscape")) {
1565 *porientation = CDSC_LANDSCAPE;
1566 }
1567 else {
1568 dsc_unknown(dsc);
1569 }
1570 return CDSC_OK;
1571 }
1572
1573 dsc_private int
dsc_parse_order(CDSC * dsc)1574 dsc_parse_order(CDSC *dsc)
1575 {
1576 char *p;
1577 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1578 (dsc->scan_section == scan_comments)) {
1579 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1580 dsc->line_length);
1581 switch (rc) {
1582 case CDSC_RESPONSE_OK:
1583 case CDSC_RESPONSE_CANCEL:
1584 return CDSC_OK; /* ignore duplicate comments in header */
1585 case CDSC_RESPONSE_IGNORE_ALL:
1586 return CDSC_NOTDSC;
1587 }
1588 }
1589 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1590 (dsc->scan_section == scan_trailer)) {
1591 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1592 dsc->line_length);
1593 switch (rc) {
1594 case CDSC_RESPONSE_OK:
1595 case CDSC_RESPONSE_CANCEL:
1596 break; /* use duplicate comments in trailer */
1597 case CDSC_RESPONSE_IGNORE_ALL:
1598 return CDSC_NOTDSC;
1599 }
1600 }
1601
1602 p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13);
1603 while (IS_WHITE(*p))
1604 p++;
1605 if (COMPARE(p, "atend")) {
1606 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1607 dsc->line_length);
1608 switch (rc) {
1609 case CDSC_RESPONSE_OK:
1610 /* assume (atend) */
1611 /* we should mark it as deferred */
1612 break;
1613 case CDSC_RESPONSE_CANCEL:
1614 /* ignore it */
1615 break;
1616 case CDSC_RESPONSE_IGNORE_ALL:
1617 return CDSC_NOTDSC;
1618 }
1619 }
1620 else if (COMPARE(p, "(atend)")) {
1621 /* do nothing */
1622 /* we should mark it as deferred */
1623 }
1624 else if (COMPARE(p, "Ascend")) {
1625 dsc->page_order = CDSC_ASCEND;
1626 }
1627 else if (COMPARE(p, "Descend")) {
1628 dsc->page_order = CDSC_DESCEND;
1629 }
1630 else if (COMPARE(p, "Special")) {
1631 dsc->page_order = CDSC_SPECIAL;
1632 }
1633 else {
1634 dsc_unknown(dsc);
1635 }
1636 return CDSC_OK;
1637 }
1638
1639
1640 dsc_private int
dsc_parse_media(CDSC * dsc,const CDSCMEDIA ** page_media)1641 dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media)
1642 {
1643 char media_name[MAXSTR];
1644 int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */
1645 unsigned int i;
1646
1647 if (dsc_copy_string(media_name, sizeof(media_name)-1,
1648 dsc->line+n, dsc->line_length-n, NULL)) {
1649 for (i=0; i<dsc->media_count; i++) {
1650 if (dsc->media[i]->name &&
1651 (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) {
1652 *page_media = dsc->media[i];
1653 return CDSC_OK;
1654 }
1655 }
1656 }
1657 dsc_unknown(dsc);
1658
1659 return CDSC_OK;
1660 }
1661
1662
1663 dsc_private int
dsc_parse_document_media(CDSC * dsc)1664 dsc_parse_document_media(CDSC *dsc)
1665 {
1666 unsigned int i, n;
1667 CDSCMEDIA lmedia;
1668 GSBOOL blank_line;
1669
1670 if (IS_DSC(dsc->line, "%%DocumentMedia:"))
1671 n = 16;
1672 else if (IS_DSC(dsc->line, "%%+"))
1673 n = 3;
1674 else
1675 return CDSC_ERROR; /* error */
1676
1677 /* check for blank remainder of line */
1678 blank_line = TRUE;
1679 for (i=n; i<dsc->line_length; i++) {
1680 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
1681 blank_line = FALSE;
1682 break;
1683 }
1684 }
1685
1686 if (!blank_line) {
1687 char name[MAXSTR];
1688 char colour[MAXSTR];
1689 char type[MAXSTR];
1690 lmedia.name = lmedia.colour = lmedia.type = (char *)NULL;
1691 lmedia.width = lmedia.height = lmedia.weight = 0;
1692 lmedia.mediabox = (CDSCBBOX *)NULL;
1693 lmedia.name = dsc_copy_string(name, sizeof(name)-1,
1694 dsc->line+n, dsc->line_length-n, &i);
1695 n+=i;
1696 if (i)
1697 lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1698 n+=i;
1699 if (i)
1700 lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1701 n+=i;
1702 if (i)
1703 lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1704 n+=i;
1705 if (i)
1706 lmedia.colour = dsc_copy_string(colour, sizeof(colour)-1,
1707 dsc->line+n, dsc->line_length-n, &i);
1708 n+=i;
1709 if (i)
1710 lmedia.type = dsc_copy_string(type, sizeof(type)-1,
1711 dsc->line+n, dsc->line_length-n, &i);
1712
1713 if (i==0)
1714 dsc_unknown(dsc); /* we didn't get all fields */
1715 else {
1716 if (dsc_add_media(dsc, &lmedia))
1717 return CDSC_ERROR; /* out of memory */
1718 }
1719 }
1720 return CDSC_OK;
1721 }
1722
1723 /* viewing orientation is believed to be the first four elements of
1724 * a CTM matrix
1725 */
1726 dsc_private int
dsc_parse_viewing_orientation(CDSC * dsc,CDSCCTM ** pctm)1727 dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm)
1728 {
1729 CDSCCTM ctm;
1730 unsigned int i, n;
1731
1732 if (*pctm != NULL) {
1733 dsc_memfree(dsc, *pctm);
1734 *pctm = NULL;
1735 }
1736
1737 n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
1738 while (IS_WHITE(dsc->line[n]))
1739 n++;
1740
1741 /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0;
1742 ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1743 n += i;
1744 if (i)
1745 ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1746 n += i;
1747 if (i)
1748 ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1749 n += i;
1750 if (i)
1751 ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1752 if (i==0) {
1753 dsc_unknown(dsc); /* we didn't get all fields */
1754 }
1755 else {
1756 *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM));
1757 if (*pctm == NULL)
1758 return CDSC_ERROR; /* no memory */
1759 **pctm = ctm;
1760 }
1761 return CDSC_OK;
1762 }
1763
1764
1765 /* This is called before dsc_read_line(), since we may
1766 * need to skip a binary header which contains a new line
1767 * character
1768 */
1769 dsc_private int
dsc_scan_type(CDSC * dsc)1770 dsc_scan_type(CDSC *dsc)
1771 {
1772 unsigned char *p;
1773 unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
1774 int length = dsc->data_length - dsc->data_index;
1775
1776 /* Types that should be known:
1777 * DSC
1778 * EPSF
1779 * PJL + any of above
1780 * ^D + any of above
1781 * DOS EPS
1782 * PDF
1783 * non-DSC
1784 */
1785
1786 /* First process any non PostScript headers */
1787 /* At this stage we do not have a complete line */
1788
1789 if (length == 0)
1790 return CDSC_NEEDMORE;
1791
1792 if (dsc->skip_pjl) {
1793 /* skip until first PostScript comment */
1794 while (length >= 2) {
1795 while (length && !IS_EOL(line[0])) {
1796 /* skip until EOL character */
1797 line++;
1798 dsc->data_index++;
1799 length--;
1800 }
1801 while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) {
1802 /* skip until EOL followed by non-EOL */
1803 line++;
1804 dsc->data_index++;
1805 length--;
1806 }
1807 if (length < 2)
1808 return CDSC_NEEDMORE;
1809
1810 if (IS_EOL(line[0]) && line[1]=='%') {
1811 line++;
1812 dsc->data_index++;
1813 length--;
1814 dsc->skip_pjl = FALSE;
1815 break;
1816 }
1817 else {
1818 /* line++; */
1819 dsc->data_index++;
1820 /* length--; */
1821 return CDSC_NEEDMORE;
1822 }
1823 }
1824 if (dsc->skip_pjl)
1825 return CDSC_NEEDMORE;
1826 }
1827
1828 if (length == 0)
1829 return CDSC_NEEDMORE;
1830
1831 if (line[0] == '\004') {
1832 line++;
1833 dsc->data_index++;
1834 length--;
1835 dsc->ctrld = TRUE;
1836 }
1837
1838 if (line[0] == '\033') {
1839 /* possibly PJL */
1840 if (length < 9)
1841 return CDSC_NEEDMORE;
1842 if (COMPARE(line, "\033%-12345X")) {
1843 dsc->skip_pjl = TRUE; /* skip until first PostScript comment */
1844 dsc->pjl = TRUE;
1845 dsc->data_index += 9;
1846 return dsc_scan_type(dsc);
1847 }
1848 }
1849
1850 if ((line[0]==0xc5) && (length < 4))
1851 return CDSC_NEEDMORE;
1852 if ((line[0]==0xc5) && (line[1]==0xd0) &&
1853 (line[2]==0xd3) && (line[3]==0xc6) ) {
1854 /* id is "EPSF" with bit 7 set */
1855 /* read DOS EPS header, then ignore all bytes until the PS section */
1856 if (length < 30)
1857 return CDSC_NEEDMORE;
1858 dsc->line = (char *)line;
1859 if (dsc_read_doseps(dsc))
1860 return CDSC_ERROR;
1861 }
1862 else {
1863 if (length < 2)
1864 return CDSC_NEEDMORE;
1865 if ((line[0] == '%') && (line[1] == 'P')) {
1866 if (length < 5)
1867 return CDSC_NEEDMORE;
1868 if (COMPARE(line, "%PDF-")) {
1869 dsc->pdf = TRUE;
1870 dsc->scan_section = scan_comments;
1871 return CDSC_OK;
1872 }
1873 }
1874 }
1875
1876 /* Finally process PostScript headers */
1877
1878 if (dsc_read_line(dsc) <= 0)
1879 return CDSC_NEEDMORE;
1880
1881 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
1882 if (COMPARE(dsc->line, "%!PS-Adobe")) {
1883 dsc->dsc = TRUE;
1884 dsc->begincomments = DSC_START(dsc);
1885 if (dsc->dsc_version == NULL)
1886 return CDSC_ERROR; /* no memory */
1887 p = (unsigned char *)dsc->line + 14;
1888 while (IS_WHITE(*p))
1889 p++;
1890 if (COMPARE(p, "EPSF-"))
1891 dsc->epsf = TRUE;
1892 dsc->scan_section = scan_comments;
1893 return CDSC_PSADOBE;
1894 }
1895 if (COMPARE(dsc->line, "%!")) {
1896 dsc->scan_section = scan_comments;
1897 return CDSC_NOTDSC;
1898 }
1899
1900 dsc->scan_section = scan_comments;
1901 return CDSC_NOTDSC; /* unrecognised */
1902 }
1903
1904
1905
1906 dsc_private int
dsc_scan_comments(CDSC * dsc)1907 dsc_scan_comments(CDSC *dsc)
1908 {
1909 /* Comments section ends at */
1910 /* %%EndComments */
1911 /* another section */
1912 /* line that does not start with %% */
1913 /* Save a few important lines */
1914
1915 char *line = dsc->line;
1916 GSBOOL continued = FALSE;
1917 dsc->id = CDSC_OK;
1918 if (IS_DSC(line, "%%EndComments")) {
1919 dsc->id = CDSC_ENDCOMMENTS;
1920 dsc->endcomments = DSC_END(dsc);
1921 dsc->scan_section = scan_pre_preview;
1922 return CDSC_OK;
1923 }
1924 else if (IS_DSC(line, "%%BeginComments")) {
1925 /* ignore because we are in this section */
1926 dsc->id = CDSC_BEGINCOMMENTS;
1927 }
1928 else if (dsc_is_section(line)) {
1929 dsc->endcomments = DSC_START(dsc);
1930 dsc->scan_section = scan_pre_preview;
1931 return CDSC_PROPAGATE;
1932 }
1933 else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) {
1934 dsc->endcomments = DSC_START(dsc);
1935 dsc->scan_section = scan_pre_preview;
1936 return CDSC_PROPAGATE;
1937 }
1938 else if (line[0] != '%') {
1939 dsc->id = CDSC_OK;
1940 dsc->endcomments = DSC_START(dsc);
1941 dsc->scan_section = scan_pre_preview;
1942 return CDSC_PROPAGATE;
1943 }
1944 else if (IS_DSC(line, "%%Begin")) {
1945 dsc->endcomments = DSC_START(dsc);
1946 dsc->scan_section = scan_pre_preview;
1947 return CDSC_PROPAGATE;
1948 }
1949
1950 /* Handle continuation lines.
1951 * To simply processing, we assume that contination lines
1952 * will only occur if repeat parameters are allowed and that
1953 * a complete set of these parameters appears on each line.
1954 * This is more restrictive than the DSC specification, but
1955 * is valid for the DSC comments understood by this parser
1956 * for all documents that we have seen.
1957 */
1958 if (IS_DSC(line, "%%+")) {
1959 line = dsc->last_line;
1960 continued = TRUE;
1961 }
1962 else
1963 dsc_save_line(dsc);
1964
1965 if (IS_DSC(line, "%%Pages:")) {
1966 dsc->id = CDSC_PAGES;
1967 if (dsc_parse_pages(dsc) != 0)
1968 return CDSC_ERROR;
1969 }
1970 else if (IS_DSC(line, "%%Creator:")) {
1971 dsc->id = CDSC_CREATOR;
1972 dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10);
1973 if (dsc->dsc_creator==NULL)
1974 return CDSC_ERROR;
1975 }
1976 else if (IS_DSC(line, "%%CreationDate:")) {
1977 dsc->id = CDSC_CREATIONDATE;
1978 dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15);
1979 if (dsc->dsc_date==NULL)
1980 return CDSC_ERROR;
1981 }
1982 else if (IS_DSC(line, "%%Title:")) {
1983 dsc->id = CDSC_TITLE;
1984 dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8);
1985 if (dsc->dsc_title==NULL)
1986 return CDSC_ERROR;
1987 }
1988 else if (IS_DSC(line, "%%For:")) {
1989 dsc->id = CDSC_FOR;
1990 dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6);
1991 if (dsc->dsc_for==NULL)
1992 return CDSC_ERROR;
1993 }
1994 else if (IS_DSC(line, "%%LanguageLevel:")) {
1995 unsigned int n = continued ? 3 : 16;
1996 unsigned int i;
1997 int ll;
1998 dsc->id = CDSC_LANGUAGELEVEL;
1999 ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
2000 if (i) {
2001 if ( (ll==1) || (ll==2) || (ll==3) )
2002 dsc->language_level = ll;
2003 else {
2004 dsc_unknown(dsc);
2005 }
2006 }
2007 else
2008 dsc_unknown(dsc);
2009 }
2010 else if (IS_DSC(line, "%%BoundingBox:")) {
2011 dsc->id = CDSC_BOUNDINGBOX;
2012 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
2013 return CDSC_ERROR;
2014 }
2015 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
2016 dsc->id = CDSC_HIRESBOUNDINGBOX;
2017 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
2018 continued ? 3 : 19))
2019 return CDSC_ERROR;
2020 }
2021 else if (IS_DSC(line, "%%CropBox:")) {
2022 dsc->id = CDSC_CROPBOX;
2023 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
2024 continued ? 3 : 10))
2025 return CDSC_ERROR;
2026 }
2027 else if (IS_DSC(line, "%%Orientation:")) {
2028 dsc->id = CDSC_ORIENTATION;
2029 if (dsc_parse_orientation(dsc, &(dsc->page_orientation),
2030 continued ? 3 : 14))
2031 return CDSC_ERROR;
2032 }
2033 else if (IS_DSC(line, "%%PageOrder:")) {
2034 dsc->id = CDSC_PAGEORDER;
2035 if (dsc_parse_order(dsc))
2036 return CDSC_ERROR;
2037 }
2038 else if (IS_DSC(line, "%%DocumentMedia:")) {
2039 dsc->id = CDSC_DOCUMENTMEDIA;
2040 if (dsc_parse_document_media(dsc))
2041 return CDSC_ERROR;
2042 }
2043 else if (IS_DSC(line, "%%DocumentPaperSizes:")) {
2044 /* DSC 2.1 */
2045 unsigned int n = continued ? 3 : 21;
2046 unsigned int count = 0;
2047 unsigned int i = 1;
2048 char name[MAXSTR];
2049 char *p;
2050 dsc->id = CDSC_DOCUMENTPAPERSIZES;
2051 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2052 p = dsc_copy_string(name, sizeof(name)-1,
2053 dsc->line+n, dsc->line_length-n, &i);
2054 if (i && p) {
2055 const CDSCMEDIA *m = dsc_known_media;
2056 if (count >= dsc->media_count) {
2057 /* set some default values */
2058 CDSCMEDIA lmedia;
2059 lmedia.name = p;
2060 lmedia.width = 595.0;
2061 lmedia.height = 842.0;
2062 lmedia.weight = 80.0;
2063 lmedia.colour = NULL;
2064 lmedia.type = NULL;
2065 lmedia.mediabox = NULL;
2066 if (dsc_add_media(dsc, &lmedia))
2067 return CDSC_ERROR;
2068 }
2069 else
2070 dsc->media[count]->name =
2071 dsc_alloc_string(dsc, p, strlen(p));
2072 /* find in list of known media */
2073 while (m && m->name) {
2074 if (dsc_stricmp(p, m->name)==0) {
2075 dsc->media[count]->width = m->width;
2076 dsc->media[count]->height = m->height;
2077 break;
2078 }
2079 m++;
2080 }
2081 }
2082 n+=i;
2083 count++;
2084 }
2085 }
2086 else if (IS_DSC(line, "%%DocumentPaperForms:")) {
2087 /* DSC 2.1 */
2088 unsigned int n = continued ? 3 : 21;
2089 unsigned int count = 0;
2090 unsigned int i = 1;
2091 char type[MAXSTR];
2092 char *p;
2093 dsc->id = CDSC_DOCUMENTPAPERFORMS;
2094 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2095 p = dsc_copy_string(type, sizeof(type)-1,
2096 dsc->line+n, dsc->line_length-n, &i);
2097 if (i && p) {
2098 if (count >= dsc->media_count) {
2099 /* set some default values */
2100 CDSCMEDIA lmedia;
2101 lmedia.name = NULL;
2102 lmedia.width = 595.0;
2103 lmedia.height = 842.0;
2104 lmedia.weight = 80.0;
2105 lmedia.colour = NULL;
2106 lmedia.type = p;
2107 lmedia.mediabox = NULL;
2108 if (dsc_add_media(dsc, &lmedia))
2109 return CDSC_ERROR;
2110 }
2111 else
2112 dsc->media[count]->type =
2113 dsc_alloc_string(dsc, p, strlen(p));
2114 }
2115 n+=i;
2116 count++;
2117 }
2118 }
2119 else if (IS_DSC(line, "%%DocumentPaperColors:")) {
2120 /* DSC 2.1 */
2121 unsigned int n = continued ? 3 : 22;
2122 unsigned int count = 0;
2123 unsigned int i = 1;
2124 char colour[MAXSTR];
2125 char *p;
2126 dsc->id = CDSC_DOCUMENTPAPERCOLORS;
2127 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2128 p = dsc_copy_string(colour, sizeof(colour)-1,
2129 dsc->line+n, dsc->line_length-n, &i);
2130 if (i && p) {
2131 if (count >= dsc->media_count) {
2132 /* set some default values */
2133 CDSCMEDIA lmedia;
2134 lmedia.name = NULL;
2135 lmedia.width = 595.0;
2136 lmedia.height = 842.0;
2137 lmedia.weight = 80.0;
2138 lmedia.colour = p;
2139 lmedia.type = NULL;
2140 lmedia.mediabox = NULL;
2141 if (dsc_add_media(dsc, &lmedia))
2142 return CDSC_ERROR;
2143 }
2144 else
2145 dsc->media[count]->colour =
2146 dsc_alloc_string(dsc, p, strlen(p));
2147 }
2148 n+=i;
2149 count++;
2150 }
2151 }
2152 else if (IS_DSC(line, "%%DocumentPaperWeights:")) {
2153 /* DSC 2.1 */
2154 unsigned int n = continued ? 3 : 23;
2155 unsigned int count = 0;
2156 unsigned int i = 1;
2157 float w;
2158 dsc->id = CDSC_DOCUMENTPAPERWEIGHTS;
2159 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2160 w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2161 if (i) {
2162 if (count >= dsc->media_count) {
2163 /* set some default values */
2164 CDSCMEDIA lmedia;
2165 lmedia.name = NULL;
2166 lmedia.width = 595.0;
2167 lmedia.height = 842.0;
2168 lmedia.weight = w;
2169 lmedia.colour = NULL;
2170 lmedia.type = NULL;
2171 lmedia.mediabox = NULL;
2172 if (dsc_add_media(dsc, &lmedia))
2173 return CDSC_ERROR;
2174 }
2175 else
2176 dsc->media[count]->weight = w;
2177 }
2178 n+=i;
2179 count++;
2180 }
2181 }
2182 else if (IS_DSC(line, "%%DocumentData:")) {
2183 unsigned int n = continued ? 3 : 15;
2184 char *p = dsc->line + n;
2185 while (IS_WHITE(*p))
2186 p++;
2187 dsc->id = CDSC_DOCUMENTDATA;
2188 if (COMPARE(p, "Clean7Bit"))
2189 dsc->document_data = CDSC_CLEAN7BIT;
2190 else if (COMPARE(p, "Clean8Bit"))
2191 dsc->document_data = CDSC_CLEAN8BIT;
2192 else if (COMPARE(p, "Binary"))
2193 dsc->document_data = CDSC_BINARY;
2194 else
2195 dsc_unknown(dsc);
2196 }
2197 else if (IS_DSC(line, "%%Requirements:")) {
2198 dsc->id = CDSC_REQUIREMENTS;
2199 /* ignore */
2200 }
2201 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
2202 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
2203 /* ignore */
2204 }
2205 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
2206 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
2207 /* ignore */
2208 }
2209 else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
2210 dsc->id = CDSC_OK;
2211 /* ignore */
2212 }
2213 else {
2214 dsc->id = CDSC_UNKNOWNDSC;
2215 dsc_unknown(dsc);
2216 }
2217
2218 dsc->endcomments = DSC_END(dsc);
2219 return CDSC_OK;
2220 }
2221
2222
2223 dsc_private int
dsc_scan_preview(CDSC * dsc)2224 dsc_scan_preview(CDSC *dsc)
2225 {
2226 /* Preview section ends at */
2227 /* %%EndPreview */
2228 /* another section */
2229 /* Preview section must start with %%BeginPreview */
2230 char *line = dsc->line;
2231 dsc->id = CDSC_OK;
2232
2233 if (dsc->scan_section == scan_pre_preview) {
2234 if (IS_BLANK(line))
2235 return CDSC_OK; /* ignore blank lines before preview */
2236 else if (IS_DSC(line, "%%BeginPreview")) {
2237 dsc->id = CDSC_BEGINPREVIEW;
2238 dsc->beginpreview = DSC_START(dsc);
2239 dsc->endpreview = DSC_END(dsc);
2240 dsc->scan_section = scan_preview;
2241 /* Don't mark the preview as EPSI if a DOS EPS header is present */
2242 if (dsc->preview == CDSC_NOPREVIEW)
2243 dsc->preview = CDSC_EPSI;
2244 return CDSC_OK;
2245 }
2246 else {
2247 dsc->scan_section = scan_pre_defaults;
2248 return CDSC_PROPAGATE;
2249 }
2250 }
2251
2252 if (IS_DSC(line, "%%BeginPreview")) {
2253 /* ignore because we are in this section */
2254 }
2255 else if (dsc_is_section(line)) {
2256 dsc->endpreview = DSC_START(dsc);
2257 dsc->scan_section = scan_pre_defaults;
2258 return CDSC_PROPAGATE;
2259 }
2260 else if (IS_DSC(line, "%%EndPreview")) {
2261 dsc->id = CDSC_ENDPREVIEW;
2262 dsc->endpreview = DSC_END(dsc);
2263 dsc->scan_section = scan_pre_defaults;
2264 return CDSC_OK;
2265 }
2266 else if (line[0] == '%' && line[1] != '%') {
2267 /* Ordinary comments are OK */
2268 }
2269 else {
2270 dsc->id = CDSC_UNKNOWNDSC;
2271 /* DSC comments should not occur in preview */
2272 dsc_unknown(dsc);
2273 }
2274
2275 dsc->endpreview = DSC_END(dsc);
2276 return CDSC_OK;
2277 }
2278
2279 dsc_private int
dsc_scan_defaults(CDSC * dsc)2280 dsc_scan_defaults(CDSC *dsc)
2281 {
2282 /* Defaults section ends at */
2283 /* %%EndDefaults */
2284 /* another section */
2285 /* Defaults section must start with %%BeginDefaults */
2286 char *line = dsc->line;
2287 dsc->id = CDSC_OK;
2288
2289 if (dsc->scan_section == scan_pre_defaults) {
2290 if (IS_BLANK(line))
2291 return CDSC_OK; /* ignore blank lines before defaults */
2292 else if (IS_DSC(line, "%%BeginDefaults")) {
2293 dsc->id = CDSC_BEGINDEFAULTS;
2294 dsc->begindefaults = DSC_START(dsc);
2295 dsc->enddefaults = DSC_END(dsc);
2296 dsc->scan_section = scan_defaults;
2297 return CDSC_OK;
2298 }
2299 else {
2300 dsc->scan_section = scan_pre_prolog;
2301 return CDSC_PROPAGATE;
2302 }
2303 }
2304
2305 if (NOT_DSC_LINE(line)) {
2306 /* ignore */
2307 }
2308 else if (IS_DSC(line, "%%BeginPreview")) {
2309 /* ignore because we have already processed this section */
2310 }
2311 else if (IS_DSC(line, "%%BeginDefaults")) {
2312 /* ignore because we are in this section */
2313 }
2314 else if (dsc_is_section(line)) {
2315 dsc->enddefaults = DSC_START(dsc);
2316 dsc->scan_section = scan_pre_prolog;
2317 return CDSC_PROPAGATE;
2318 }
2319 else if (IS_DSC(line, "%%EndDefaults")) {
2320 dsc->id = CDSC_ENDDEFAULTS;
2321 dsc->enddefaults = DSC_END(dsc);
2322 dsc->scan_section = scan_pre_prolog;
2323 return CDSC_OK;
2324 }
2325 else if (IS_DSC(line, "%%PageMedia:")) {
2326 dsc->id = CDSC_PAGEMEDIA;
2327 dsc_parse_media(dsc, &dsc->page_media);
2328 }
2329 else if (IS_DSC(line, "%%PageOrientation:")) {
2330 dsc->id = CDSC_PAGEORIENTATION;
2331 /* This can override %%Orientation: */
2332 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18))
2333 return CDSC_ERROR;
2334 }
2335 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2336 dsc->id = CDSC_PAGEBOUNDINGBOX;
2337 if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18))
2338 return CDSC_ERROR;
2339 }
2340 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2341 dsc->id = CDSC_VIEWINGORIENTATION;
2342 if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation))
2343 return CDSC_ERROR;
2344 }
2345 else {
2346 dsc->id = CDSC_UNKNOWNDSC;
2347 /* All other DSC comments are unknown, but not an error */
2348 dsc_unknown(dsc);
2349 }
2350 dsc->enddefaults = DSC_END(dsc);
2351 return CDSC_OK;
2352 }
2353
2354 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
2355 * mismatch (default) */
2356 dsc_private int
dsc_check_match_prompt(CDSC * dsc,const char * str,int count)2357 dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
2358 {
2359 if (count != 0) {
2360 char buf[MAXSTR+MAXSTR] = "";
2361 if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) {
2362 strncpy(buf, dsc->line, dsc->line_length);
2363 buf[dsc->line_length] = '\0';
2364 }
2365 sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
2366 return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, strlen(buf));
2367 }
2368 return CDSC_RESPONSE_CANCEL;
2369 }
2370
2371 dsc_private int
dsc_check_match_type(CDSC * dsc,const char * str,int count)2372 dsc_check_match_type(CDSC *dsc, const char *str, int count)
2373 {
2374 if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
2375 return CDSC_NOTDSC;
2376 return CDSC_OK;
2377 }
2378
2379 /* complain if Begin/End blocks didn't match */
2380 /* return non-zero if we should ignore all DSC */
2381 dsc_private int
dsc_check_match(CDSC * dsc)2382 dsc_check_match(CDSC *dsc)
2383 {
2384 int rc = 0;
2385 const char *font = "Font";
2386 const char *feature = "Feature";
2387 const char *resource = "Resource";
2388 const char *procset = "ProcSet";
2389
2390 if (!rc)
2391 rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
2392 if (!rc)
2393 rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
2394 if (!rc)
2395 rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
2396 if (!rc)
2397 rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
2398
2399 dsc->begin_font_count = 0;
2400 dsc->begin_feature_count = 0;
2401 dsc->begin_resource_count = 0;
2402 dsc->begin_procset_count = 0;
2403 return rc;
2404 }
2405
2406
2407 dsc_private int
dsc_scan_prolog(CDSC * dsc)2408 dsc_scan_prolog(CDSC *dsc)
2409 {
2410 /* Prolog section ends at */
2411 /* %%EndProlog */
2412 /* another section */
2413 /* Prolog section may start with %%BeginProlog or non-dsc line */
2414 char *line = dsc->line;
2415 dsc->id = CDSC_OK;
2416
2417 if (dsc->scan_section == scan_pre_prolog) {
2418 if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
2419 dsc->scan_section = scan_pre_setup;
2420 return CDSC_PROPAGATE;
2421 }
2422 dsc->id = CDSC_BEGINPROLOG;
2423 dsc->beginprolog = DSC_START(dsc);
2424 dsc->endprolog = DSC_END(dsc);
2425 dsc->scan_section = scan_prolog;
2426 if (IS_DSC(line, "%%BeginProlog"))
2427 return CDSC_OK;
2428 }
2429
2430 if (NOT_DSC_LINE(line)) {
2431 /* ignore */
2432 }
2433 else if (IS_DSC(line, "%%BeginPreview")) {
2434 /* ignore because we have already processed this section */
2435 }
2436 else if (IS_DSC(line, "%%BeginDefaults")) {
2437 /* ignore because we have already processed this section */
2438 }
2439 else if (IS_DSC(line, "%%BeginProlog")) {
2440 /* ignore because we are in this section */
2441 }
2442 else if (dsc_is_section(line)) {
2443 dsc->endprolog = DSC_START(dsc);
2444 dsc->scan_section = scan_pre_setup;
2445 if (dsc_check_match(dsc))
2446 return CDSC_NOTDSC;
2447 return CDSC_PROPAGATE;
2448 }
2449 else if (IS_DSC(line, "%%EndProlog")) {
2450 dsc->id = CDSC_ENDPROLOG;
2451 dsc->endprolog = DSC_END(dsc);
2452 dsc->scan_section = scan_pre_setup;
2453 if (dsc_check_match(dsc))
2454 return CDSC_NOTDSC;
2455 return CDSC_OK;
2456 }
2457 else if (IS_DSC(line, "%%BeginFont:")) {
2458 dsc->id = CDSC_BEGINFONT;
2459 /* ignore Begin/EndFont, apart form making sure */
2460 /* that they are matched. */
2461 dsc->begin_font_count++;
2462 }
2463 else if (IS_DSC(line, "%%EndFont")) {
2464 dsc->id = CDSC_ENDFONT;
2465 dsc->begin_font_count--;
2466 }
2467 else if (IS_DSC(line, "%%BeginFeature:")) {
2468 dsc->id = CDSC_BEGINFEATURE;
2469 /* ignore Begin/EndFeature, apart form making sure */
2470 /* that they are matched. */
2471 dsc->begin_feature_count++;
2472 }
2473 else if (IS_DSC(line, "%%EndFeature")) {
2474 dsc->id = CDSC_ENDFEATURE;
2475 dsc->begin_feature_count--;
2476 }
2477 else if (IS_DSC(line, "%%BeginResource:")) {
2478 dsc->id = CDSC_BEGINRESOURCE;
2479 /* ignore Begin/EndResource, apart form making sure */
2480 /* that they are matched. */
2481 dsc->begin_resource_count++;
2482 }
2483 else if (IS_DSC(line, "%%EndResource")) {
2484 dsc->id = CDSC_ENDRESOURCE;
2485 dsc->begin_resource_count--;
2486 }
2487 else if (IS_DSC(line, "%%BeginProcSet:")) {
2488 dsc->id = CDSC_BEGINPROCSET;
2489 /* ignore Begin/EndProcSet, apart form making sure */
2490 /* that they are matched. */
2491 dsc->begin_procset_count++;
2492 }
2493 else if (IS_DSC(line, "%%EndProcSet")) {
2494 dsc->id = CDSC_ENDPROCSET;
2495 dsc->begin_procset_count--;
2496 }
2497 else {
2498 /* All other DSC comments are unknown, but not an error */
2499 dsc->id = CDSC_UNKNOWNDSC;
2500 dsc_unknown(dsc);
2501 }
2502
2503 dsc->endprolog = DSC_END(dsc);
2504 return CDSC_OK;
2505 }
2506
2507 dsc_private int
dsc_scan_setup(CDSC * dsc)2508 dsc_scan_setup(CDSC *dsc)
2509 {
2510 /* Setup section ends at */
2511 /* %%EndSetup */
2512 /* another section */
2513 /* Setup section must start with %%BeginSetup */
2514
2515 char *line = dsc->line;
2516 dsc->id = CDSC_OK;
2517
2518 if (dsc->scan_section == scan_pre_setup) {
2519 if (IS_BLANK(line))
2520 return CDSC_OK; /* ignore blank lines before setup */
2521 else if (IS_DSC(line, "%%BeginSetup")) {
2522 dsc->id = CDSC_BEGINSETUP;
2523 dsc->beginsetup = DSC_START(dsc);
2524 dsc->endsetup = DSC_END(dsc);
2525 dsc->scan_section = scan_setup;
2526 return CDSC_OK;
2527 }
2528 else {
2529 dsc->scan_section = scan_pre_pages;
2530 return CDSC_PROPAGATE;
2531 }
2532 }
2533
2534 if (NOT_DSC_LINE(line)) {
2535 /* ignore */
2536 }
2537 else if (IS_DSC(line, "%%BeginPreview")) {
2538 /* ignore because we have already processed this section */
2539 }
2540 else if (IS_DSC(line, "%%BeginDefaults")) {
2541 /* ignore because we have already processed this section */
2542 }
2543 else if (IS_DSC(line, "%%BeginProlog")) {
2544 /* ignore because we have already processed this section */
2545 }
2546 else if (IS_DSC(line, "%%BeginSetup")) {
2547 /* ignore because we are in this section */
2548 }
2549 else if (dsc_is_section(line)) {
2550 dsc->endsetup = DSC_START(dsc);
2551 dsc->scan_section = scan_pre_pages;
2552 if (dsc_check_match(dsc))
2553 return CDSC_NOTDSC;
2554 return CDSC_PROPAGATE;
2555 }
2556 else if (IS_DSC(line, "%%EndSetup")) {
2557 dsc->id = CDSC_ENDSETUP;
2558 dsc->endsetup = DSC_END(dsc);
2559 dsc->scan_section = scan_pre_pages;
2560 if (dsc_check_match(dsc))
2561 return CDSC_NOTDSC;
2562 return CDSC_OK;
2563 }
2564 else if (IS_DSC(line, "%%BeginFeature:")) {
2565 dsc->id = CDSC_BEGINFEATURE;
2566 /* ignore Begin/EndFeature, apart form making sure */
2567 /* that they are matched. */
2568 dsc->begin_feature_count++;
2569 }
2570 else if (IS_DSC(line, "%%EndFeature")) {
2571 dsc->id = CDSC_ENDFEATURE;
2572 dsc->begin_feature_count--;
2573 }
2574 else if (IS_DSC(line, "%%Feature:")) {
2575 dsc->id = CDSC_FEATURE;
2576 /* ignore */
2577 }
2578 else if (IS_DSC(line, "%%BeginResource:")) {
2579 dsc->id = CDSC_BEGINRESOURCE;
2580 /* ignore Begin/EndResource, apart form making sure */
2581 /* that they are matched. */
2582 dsc->begin_resource_count++;
2583 }
2584 else if (IS_DSC(line, "%%EndResource")) {
2585 dsc->id = CDSC_ENDRESOURCE;
2586 dsc->begin_resource_count--;
2587 }
2588 else if (IS_DSC(line, "%%PaperColor:")) {
2589 dsc->id = CDSC_PAPERCOLOR;
2590 /* ignore */
2591 }
2592 else if (IS_DSC(line, "%%PaperForm:")) {
2593 dsc->id = CDSC_PAPERFORM;
2594 /* ignore */
2595 }
2596 else if (IS_DSC(line, "%%PaperWeight:")) {
2597 dsc->id = CDSC_PAPERWEIGHT;
2598 /* ignore */
2599 }
2600 else if (IS_DSC(line, "%%PaperSize:")) {
2601 /* DSC 2.1 */
2602 GSBOOL found_media = FALSE;
2603 int i;
2604 int n = 12;
2605 char buf[MAXSTR];
2606 buf[0] = '\0';
2607 dsc->id = CDSC_PAPERSIZE;
2608 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n,
2609 NULL);
2610 for (i=0; i<(int)dsc->media_count; i++) {
2611 if (dsc->media[i] && dsc->media[i]->name &&
2612 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2613 dsc->page_media = dsc->media[i];
2614 found_media = TRUE;
2615 break;
2616 }
2617 }
2618 if (!found_media) {
2619 /* It didn't match %%DocumentPaperSizes: */
2620 /* Try our known media */
2621 const CDSCMEDIA *m = dsc_known_media;
2622 while (m->name) {
2623 if (dsc_stricmp(buf, m->name)==0) {
2624 dsc->page_media = m;
2625 break;
2626 }
2627 m++;
2628 }
2629 if (m->name == NULL)
2630 dsc_unknown(dsc);
2631 }
2632 }
2633 else {
2634 /* All other DSC comments are unknown, but not an error */
2635 dsc->id = CDSC_UNKNOWNDSC;
2636 dsc_unknown(dsc);
2637 }
2638
2639 dsc->endsetup = DSC_END(dsc);
2640 return CDSC_OK;
2641 }
2642
2643 dsc_private int
dsc_scan_page(CDSC * dsc)2644 dsc_scan_page(CDSC *dsc)
2645 {
2646 /* Page section ends at */
2647 /* %%Page */
2648 /* %%Trailer */
2649 /* %%EOF */
2650 char *line = dsc->line;
2651 dsc->id = CDSC_OK;
2652
2653 if (dsc->scan_section == scan_pre_pages) {
2654 if (IS_DSC(line, "%%Page:")) {
2655 dsc->scan_section = scan_pages;
2656 /* fall through */
2657 }
2658 else {
2659 /* %%Page: didn't follow %%EndSetup
2660 * Keep reading until reach %%Page or %%Trailer
2661 * and add it to previous section.
2662 */
2663 unsigned long *last;
2664 if (dsc->endsetup != 0)
2665 last = &dsc->endsetup;
2666 else if (dsc->endprolog != 0)
2667 last = &dsc->endprolog;
2668 else if (dsc->enddefaults != 0)
2669 last = &dsc->enddefaults;
2670 else if (dsc->endpreview != 0)
2671 last = &dsc->endpreview;
2672 else if (dsc->endcomments != 0)
2673 last = &dsc->endcomments;
2674 else
2675 last = &dsc->begincomments;
2676 *last = DSC_START(dsc);
2677 if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
2678 dsc->scan_section = scan_pre_trailer;
2679 return CDSC_PROPAGATE;
2680 }
2681 return CDSC_OK;
2682 }
2683 }
2684
2685 if (NOT_DSC_LINE(line)) {
2686 /* ignore */
2687 }
2688 else if (IS_DSC(line, "%%Page:")) {
2689 dsc->id = CDSC_PAGE;
2690 if (dsc->page_count) {
2691 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
2692 if (dsc_check_match(dsc))
2693 return CDSC_NOTDSC;
2694 }
2695
2696 if (dsc_parse_page(dsc) != 0)
2697 return CDSC_ERROR;
2698
2699 return CDSC_OK;
2700 }
2701 else if (IS_DSC(line, "%%BeginPreview")) {
2702 /* ignore because we have already processed this section */
2703 }
2704 else if (IS_DSC(line, "%%BeginDefaults")) {
2705 /* ignore because we have already processed this section */
2706 }
2707 else if (IS_DSC(line, "%%BeginProlog")) {
2708 /* ignore because we have already processed this section */
2709 }
2710 else if (IS_DSC(line, "%%BeginSetup")) {
2711 /* ignore because we have already processed this section */
2712 }
2713 else if (dsc_is_section(line)) {
2714 if (IS_DSC(line, "%%Trailer")) {
2715 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
2716 if (dsc->file_length) {
2717 if ((!dsc->doseps &&
2718 ((DSC_END(dsc) + 32768) < dsc->file_length)) ||
2719 ((dsc->doseps) &&
2720 ((DSC_END(dsc) + 32768) < dsc->doseps_end))) {
2721 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER,
2722 dsc->line, dsc->line_length);
2723 switch (rc) {
2724 case CDSC_RESPONSE_OK:
2725 /* ignore early trailer */
2726 break;
2727 case CDSC_RESPONSE_CANCEL:
2728 /* this is the trailer */
2729 dsc->scan_section = scan_pre_trailer;
2730 if (dsc_check_match(dsc))
2731 return CDSC_NOTDSC;
2732 return CDSC_PROPAGATE;
2733 case CDSC_RESPONSE_IGNORE_ALL:
2734 return CDSC_NOTDSC;
2735 }
2736 }
2737 else {
2738 dsc->scan_section = scan_pre_trailer;
2739 if (dsc_check_match(dsc))
2740 return CDSC_NOTDSC;
2741 return CDSC_PROPAGATE;
2742 }
2743 }
2744 else {
2745 dsc->scan_section = scan_pre_trailer;
2746 if (dsc_check_match(dsc))
2747 return CDSC_NOTDSC;
2748 return CDSC_PROPAGATE;
2749 }
2750 }
2751 else if (IS_DSC(line, "%%EOF")) {
2752 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
2753 if (dsc->file_length) {
2754 if ((DSC_END(dsc)+100 < dsc->file_length) ||
2755 (dsc->doseps && (DSC_END(dsc) + 100 < dsc->doseps_end))) {
2756 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF,
2757 dsc->line, dsc->line_length);
2758 switch (rc) {
2759 case CDSC_RESPONSE_OK:
2760 /* %%EOF is wrong, ignore it */
2761 break;
2762 case CDSC_RESPONSE_CANCEL:
2763 /* %%EOF is correct */
2764 dsc->scan_section = scan_eof;
2765 dsc->eof = TRUE;
2766 if (dsc_check_match(dsc))
2767 return CDSC_NOTDSC;
2768 return CDSC_PROPAGATE;
2769 case CDSC_RESPONSE_IGNORE_ALL:
2770 return CDSC_NOTDSC;
2771 }
2772 }
2773 }
2774 else {
2775 /* ignore it */
2776 if (dsc_check_match(dsc))
2777 return CDSC_NOTDSC;
2778 return CDSC_OK;
2779 }
2780 }
2781 else {
2782 /* Section comment, probably from a badly */
2783 /* encapsulated EPS file. */
2784 int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION,
2785 dsc->line, dsc->line_length);
2786 if (rc == CDSC_RESPONSE_IGNORE_ALL)
2787 return CDSC_NOTDSC;
2788 }
2789 }
2790 else if (IS_DSC(line, "%%PageTrailer")) {
2791 dsc->id = CDSC_PAGETRAILER;
2792 /* ignore */
2793 }
2794 else if (IS_DSC(line, "%%BeginPageSetup")) {
2795 dsc->id = CDSC_BEGINPAGESETUP;
2796 /* ignore */
2797 }
2798 else if (IS_DSC(line, "%%EndPageSetup")) {
2799 dsc->id = CDSC_ENDPAGESETUP;
2800 /* ignore */
2801 }
2802 else if (IS_DSC(line, "%%PageMedia:")) {
2803 dsc->id = CDSC_PAGEMEDIA;
2804 dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media));
2805 }
2806 else if (IS_DSC(line, "%%PaperColor:")) {
2807 dsc->id = CDSC_PAPERCOLOR;
2808 /* ignore */
2809 }
2810 else if (IS_DSC(line, "%%PaperForm:")) {
2811 dsc->id = CDSC_PAPERFORM;
2812 /* ignore */
2813 }
2814 else if (IS_DSC(line, "%%PaperWeight:")) {
2815 dsc->id = CDSC_PAPERWEIGHT;
2816 /* ignore */
2817 }
2818 else if (IS_DSC(line, "%%PaperSize:")) {
2819 /* DSC 2.1 */
2820 GSBOOL found_media = FALSE;
2821 int i;
2822 int n = 12;
2823 char buf[MAXSTR];
2824 buf[0] = '\0';
2825 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n,
2826 dsc->line_length-n, NULL);
2827 for (i=0; i<(int)dsc->media_count; i++) {
2828 if (dsc->media[i] && dsc->media[i]->name &&
2829 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2830 dsc->page_media = dsc->media[i];
2831 found_media = TRUE;
2832 break;
2833 }
2834 }
2835 if (!found_media) {
2836 /* It didn't match %%DocumentPaperSizes: */
2837 /* Try our known media */
2838 const CDSCMEDIA *m = dsc_known_media;
2839 while (m->name) {
2840 if (dsc_stricmp(buf, m->name)==0) {
2841 dsc->page[dsc->page_count-1].media = m;
2842 break;
2843 }
2844 m++;
2845 }
2846 if (m->name == NULL)
2847 dsc_unknown(dsc);
2848 }
2849 }
2850 else if (IS_DSC(line, "%%PageOrientation:")) {
2851 dsc->id = CDSC_PAGEORIENTATION;
2852 if (dsc_parse_orientation(dsc,
2853 &(dsc->page[dsc->page_count-1].orientation) ,18))
2854 return CDSC_NOTDSC;
2855 }
2856 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2857 dsc->id = CDSC_PAGEBOUNDINGBOX;
2858 if (dsc_parse_bounding_box(dsc, &dsc->page[dsc->page_count-1].bbox, 18))
2859 return CDSC_NOTDSC;
2860 }
2861 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2862 dsc->id = CDSC_VIEWINGORIENTATION;
2863 if (dsc_parse_viewing_orientation(dsc,
2864 &dsc->page[dsc->page_count-1].viewing_orientation))
2865 return CDSC_ERROR;
2866 }
2867 else if (IS_DSC(line, "%%BeginFont:")) {
2868 dsc->id = CDSC_BEGINFONT;
2869 /* ignore Begin/EndFont, apart form making sure */
2870 /* that they are matched. */
2871 dsc->begin_font_count++;
2872 }
2873 else if (IS_DSC(line, "%%EndFont")) {
2874 dsc->id = CDSC_BEGINFONT;
2875 dsc->begin_font_count--;
2876 }
2877 else if (IS_DSC(line, "%%BeginFeature:")) {
2878 dsc->id = CDSC_BEGINFEATURE;
2879 /* ignore Begin/EndFeature, apart form making sure */
2880 /* that they are matched. */
2881 dsc->begin_feature_count++;
2882 }
2883 else if (IS_DSC(line, "%%EndFeature")) {
2884 dsc->id = CDSC_ENDFEATURE;
2885 dsc->begin_feature_count--;
2886 }
2887 else if (IS_DSC(line, "%%BeginResource:")) {
2888 dsc->id = CDSC_BEGINRESOURCE;
2889 /* ignore Begin/EndResource, apart form making sure */
2890 /* that they are matched. */
2891 dsc->begin_resource_count++;
2892 }
2893 else if (IS_DSC(line, "%%EndResource")) {
2894 dsc->id = CDSC_ENDRESOURCE;
2895 dsc->begin_resource_count--;
2896 }
2897 else if (IS_DSC(line, "%%BeginProcSet:")) {
2898 dsc->id = CDSC_BEGINPROCSET;
2899 /* ignore Begin/EndProcSet, apart form making sure */
2900 /* that they are matched. */
2901 dsc->begin_procset_count++;
2902 }
2903 else if (IS_DSC(line, "%%EndProcSet")) {
2904 dsc->id = CDSC_ENDPROCSET;
2905 dsc->begin_procset_count--;
2906 }
2907 else if (IS_DSC(line, "%%IncludeFont:")) {
2908 dsc->id = CDSC_INCLUDEFONT;
2909 /* ignore */
2910 }
2911 else {
2912 /* All other DSC comments are unknown, but not an error */
2913 dsc->id = CDSC_UNKNOWNDSC;
2914 dsc_unknown(dsc);
2915 }
2916
2917 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
2918 return CDSC_OK;
2919 }
2920
2921 /* Valid Trailer comments are
2922 * %%Trailer
2923 * %%EOF
2924 * or the following deferred with (atend)
2925 * %%BoundingBox:
2926 * %%DocumentCustomColors:
2927 * %%DocumentFiles:
2928 * %%DocumentFonts:
2929 * %%DocumentNeededFiles:
2930 * %%DocumentNeededFonts:
2931 * %%DocumentNeededProcSets:
2932 * %%DocumentNeededResources:
2933 * %%DocumentProcSets:
2934 * %%DocumentProcessColors:
2935 * %%DocumentSuppliedFiles:
2936 * %%DocumentSuppliedFonts:
2937 * %%DocumentSuppliedProcSets:
2938 * %%DocumentSuppliedResources:
2939 * %%Orientation:
2940 * %%Pages:
2941 * %%PageOrder:
2942 *
2943 * Our supported subset is
2944 * %%Trailer
2945 * %%EOF
2946 * %%BoundingBox:
2947 * %%Orientation:
2948 * %%Pages:
2949 * %%PageOrder:
2950 * In addition to these, we support
2951 * %%DocumentMedia:
2952 *
2953 * A %%PageTrailer can have the following:
2954 * %%PageBoundingBox:
2955 * %%PageCustomColors:
2956 * %%PageFiles:
2957 * %%PageFonts:
2958 * %%PageOrientation:
2959 * %%PageProcessColors:
2960 * %%PageResources:
2961 */
2962
2963 dsc_private int
dsc_scan_trailer(CDSC * dsc)2964 dsc_scan_trailer(CDSC *dsc)
2965 {
2966 /* Trailer section start at */
2967 /* %%Trailer */
2968 /* and ends at */
2969 /* %%EOF */
2970 char *line = dsc->line;
2971 GSBOOL continued = FALSE;
2972 dsc->id = CDSC_OK;
2973
2974 if (dsc->scan_section == scan_pre_trailer) {
2975 if (IS_DSC(line, "%%Trailer")) {
2976 dsc->id = CDSC_TRAILER;
2977 dsc->begintrailer = DSC_START(dsc);
2978 dsc->endtrailer = DSC_END(dsc);
2979 dsc->scan_section = scan_trailer;
2980 return CDSC_OK;
2981 }
2982 else if (IS_DSC(line, "%%EOF")) {
2983 dsc->id = CDSC_EOF;
2984 dsc->begintrailer = DSC_START(dsc);
2985 dsc->endtrailer = DSC_END(dsc);
2986 dsc->scan_section = scan_trailer;
2987 /* Continue, in case we found %%EOF in an embedded document */
2988 return CDSC_OK;
2989 }
2990 else {
2991 /* %%Page: didn't follow %%EndSetup
2992 * Keep reading until reach %%Page or %%Trailer
2993 * and add it to setup section
2994 */
2995 /* append to previous section */
2996 if (dsc->beginsetup)
2997 dsc->endsetup = DSC_END(dsc);
2998 else if (dsc->beginprolog)
2999 dsc->endprolog = DSC_END(dsc);
3000 else {
3001 /* horribly confused */
3002 }
3003 return CDSC_OK;
3004 }
3005 }
3006
3007 /* Handle continuation lines.
3008 * See comment above about our restrictive processing of
3009 * continuation lines
3010 */
3011 if (IS_DSC(line, "%%+")) {
3012 line = dsc->last_line;
3013 continued = TRUE;
3014 }
3015 else
3016 dsc_save_line(dsc);
3017
3018 if (NOT_DSC_LINE(line)) {
3019 /* ignore */
3020 }
3021 else if (IS_DSC(dsc->line, "%%EOF")) {
3022 /* Keep scanning, in case we have a false trailer */
3023 dsc->id = CDSC_EOF;
3024 }
3025 else if (IS_DSC(dsc->line, "%%Trailer")) {
3026 /* Cope with no pages with code after setup and before trailer. */
3027 /* Last trailer is the correct one. */
3028 dsc->id = CDSC_TRAILER;
3029 dsc->begintrailer = DSC_START(dsc);
3030 }
3031 else if (IS_DSC(line, "%%Pages:")) {
3032 dsc->id = CDSC_PAGES;
3033 if (dsc_parse_pages(dsc) != 0)
3034 return CDSC_ERROR;
3035 }
3036 else if (IS_DSC(line, "%%BoundingBox:")) {
3037 dsc->id = CDSC_BOUNDINGBOX;
3038 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
3039 return CDSC_ERROR;
3040 }
3041 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
3042 dsc->id = CDSC_HIRESBOUNDINGBOX;
3043 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
3044 continued ? 3 : 19))
3045 return CDSC_ERROR;
3046 }
3047 else if (IS_DSC(line, "%%CropBox:")) {
3048 dsc->id = CDSC_CROPBOX;
3049 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
3050 continued ? 3 : 10))
3051 return CDSC_ERROR;
3052 }
3053 else if (IS_DSC(line, "%%Orientation:")) {
3054 dsc->id = CDSC_ORIENTATION;
3055 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14))
3056 return CDSC_ERROR;
3057 }
3058 else if (IS_DSC(line, "%%PageOrder:")) {
3059 dsc->id = CDSC_PAGEORDER;
3060 if (dsc_parse_order(dsc))
3061 return CDSC_ERROR;
3062 }
3063 else if (IS_DSC(line, "%%DocumentMedia:")) {
3064 dsc->id = CDSC_DOCUMENTMEDIA;
3065 if (dsc_parse_document_media(dsc))
3066 return CDSC_ERROR;
3067 }
3068 else if (IS_DSC(dsc->line, "%%Page:")) {
3069 /* This should not occur in the trailer, but we might see
3070 * this if a document has been incorrectly embedded.
3071 */
3072 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER,
3073 dsc->line, dsc->line_length);
3074 switch (rc) {
3075 case CDSC_RESPONSE_OK:
3076 /* Assume that we are really in the previous */
3077 /* page, not the trailer */
3078 dsc->scan_section = scan_pre_pages;
3079 if (dsc->page_count)
3080 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3081 return CDSC_PROPAGATE; /* try again */
3082 case CDSC_RESPONSE_CANCEL:
3083 /* ignore pages in trailer */
3084 break;
3085 case CDSC_RESPONSE_IGNORE_ALL:
3086 return CDSC_NOTDSC;
3087 }
3088 }
3089 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
3090 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
3091 /* ignore */
3092 }
3093 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
3094 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
3095 /* ignore */
3096 }
3097 else {
3098 /* All other DSC comments are unknown, but not an error */
3099 dsc->id = CDSC_UNKNOWNDSC;
3100 dsc_unknown(dsc);
3101 }
3102
3103 dsc->endtrailer = DSC_END(dsc);
3104 return CDSC_OK;
3105 }
3106
3107
3108 dsc_private char *
dsc_alloc_string(CDSC * dsc,const char * str,int len)3109 dsc_alloc_string(CDSC *dsc, const char *str, int len)
3110 {
3111 char *p;
3112 if (dsc->string_head == NULL) {
3113 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3114 if (dsc->string_head == NULL)
3115 return NULL; /* no memory */
3116 dsc->string = dsc->string_head;
3117 dsc->string->next = NULL;
3118 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3119 if (dsc->string->data == NULL) {
3120 dsc_reset(dsc);
3121 return NULL; /* no memory */
3122 }
3123 dsc->string->index = 0;
3124 dsc->string->length = CDSC_STRING_CHUNK;
3125 }
3126 if ( dsc->string->index + len + 1 > dsc->string->length) {
3127 /* allocate another string block */
3128 CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3129 if (newstring == NULL) {
3130 dsc_debug_print(dsc, "Out of memory\n");
3131 return NULL;
3132 }
3133 newstring->next = NULL;
3134 newstring->length = 0;
3135 newstring->index = 0;
3136 newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3137 if (newstring->data == NULL) {
3138 dsc_memfree(dsc, newstring);
3139 dsc_debug_print(dsc, "Out of memory\n");
3140 return NULL; /* no memory */
3141 }
3142 newstring->length = CDSC_STRING_CHUNK;
3143 dsc->string->next = newstring;
3144 dsc->string = newstring;
3145 }
3146 if ( dsc->string->index + len + 1 > dsc->string->length)
3147 return NULL; /* failed */
3148 p = dsc->string->data + dsc->string->index;
3149 memcpy(p, str, len);
3150 *(p+len) = '\0';
3151 dsc->string->index += len + 1;
3152 return p;
3153 }
3154
3155 /* store line, ignoring leading spaces */
3156 dsc_private char *
dsc_add_line(CDSC * dsc,const char * line,unsigned int len)3157 dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
3158 {
3159 char *newline;
3160 unsigned int i;
3161 while (len && (IS_WHITE(*line))) {
3162 len--;
3163 line++;
3164 }
3165 newline = dsc_alloc_string(dsc, line, len);
3166 if (newline == NULL)
3167 return NULL;
3168
3169 for (i=0; i<len; i++) {
3170 if (newline[i] == '\r') {
3171 newline[i]='\0';
3172 break;
3173 }
3174 if (newline[i] == '\n') {
3175 newline[i]='\0';
3176 break;
3177 }
3178 }
3179 return newline;
3180 }
3181
3182
3183 /* Copy string on line to new allocated string str */
3184 /* String is always null terminated */
3185 /* String is no longer than len */
3186 /* Return pointer to string */
3187 /* Store number of used characters from line */
3188 /* Don't copy enclosing () */
3189 dsc_private char *
dsc_copy_string(char * str,unsigned int slen,char * line,unsigned int len,unsigned int * offset)3190 dsc_copy_string(char *str, unsigned int slen, char *line,
3191 unsigned int len, unsigned int *offset)
3192 {
3193 int quoted = FALSE;
3194 int instring=0;
3195 unsigned int newlength = 0;
3196 unsigned int i = 0;
3197 unsigned char ch;
3198 if (len > slen)
3199 len = slen-1;
3200 while ( (i<len) && IS_WHITE(line[i]))
3201 i++; /* skip leading spaces */
3202 if (line[i]=='(') {
3203 quoted = TRUE;
3204 instring++;
3205 i++; /* don't copy outside () */
3206 }
3207 while (i < len) {
3208 str[newlength] = ch = line[i];
3209 i++;
3210 if (quoted) {
3211 if (ch == '(')
3212 instring++;
3213 if (ch == ')')
3214 instring--;
3215 if (instring==0)
3216 break;
3217 }
3218 else if (ch == ' ')
3219 break;
3220
3221 if (ch == '\r')
3222 break;
3223 if (ch == '\n')
3224 break;
3225 else if ( (ch == '\\') && (i+1 < len) ) {
3226 ch = line[i];
3227 if ((ch >= '0') && (ch <= '9')) {
3228 /* octal coded character */
3229 int j = 3;
3230 ch = 0;
3231 while (j && (i < len) && line[i]>='0' && line[i]<='7') {
3232 ch = (unsigned char)((ch<<3) + (line[i]-'0'));
3233 i++;
3234 j--;
3235 }
3236 str[newlength] = ch;
3237 }
3238 else if (ch == '(') {
3239 str[newlength] = ch;
3240 i++;
3241 }
3242 else if (ch == ')') {
3243 str[newlength] = ch;
3244 i++;
3245 }
3246 else if (ch == 'b') {
3247 str[newlength] = '\b';
3248 i++;
3249 }
3250 else if (ch == 'f') {
3251 str[newlength] = '\b';
3252 i++;
3253 }
3254 else if (ch == 'n') {
3255 str[newlength] = '\n';
3256 i++;
3257 }
3258 else if (ch == 'r') {
3259 str[newlength] = '\r';
3260 i++;
3261 }
3262 else if (ch == 't') {
3263 str[newlength] = '\t';
3264 i++;
3265 }
3266 else if (ch == '\\') {
3267 str[newlength] = '\\';
3268 i++;
3269 }
3270 }
3271 newlength++;
3272 }
3273 str[newlength] = '\0';
3274 if (offset != (unsigned int *)NULL)
3275 *offset = i;
3276 return str;
3277 }
3278
3279 dsc_private int
dsc_get_int(const char * line,unsigned int len,unsigned int * offset)3280 dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
3281 {
3282 char newline[MAXSTR];
3283 int newlength = 0;
3284 unsigned int i = 0;
3285 unsigned char ch;
3286
3287 len = min(len, sizeof(newline)-1);
3288 while ((i<len) && IS_WHITE(line[i]))
3289 i++; /* skip leading spaces */
3290 while (i < len) {
3291 newline[newlength] = ch = line[i];
3292 if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
3293 break; /* not part of an integer number */
3294 i++;
3295 newlength++;
3296 }
3297 while ((i<len) && IS_WHITE(line[i]))
3298 i++; /* skip trailing spaces */
3299 newline[newlength] = '\0';
3300 if (offset != (unsigned int *)NULL)
3301 *offset = i;
3302 return atoi(newline);
3303 }
3304
3305 dsc_private float
dsc_get_real(const char * line,unsigned int len,unsigned int * offset)3306 dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
3307 {
3308 char newline[MAXSTR];
3309 int newlength = 0;
3310 unsigned int i = 0;
3311 unsigned char ch;
3312
3313 len = min(len, sizeof(newline)-1);
3314 while ((i<len) && IS_WHITE(line[i]))
3315 i++; /* skip leading spaces */
3316 while (i < len) {
3317 newline[newlength] = ch = line[i];
3318 if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
3319 || (ch=='e') || (ch=='E')))
3320 break; /* not part of a real number */
3321 i++;
3322 newlength++;
3323 }
3324 while ((i<len) && IS_WHITE(line[i]))
3325 i++; /* skip trailing spaces */
3326
3327 newline[newlength] = '\0';
3328
3329 if (offset != (unsigned int *)NULL)
3330 *offset = i;
3331 return (float)atof(newline);
3332 }
3333
3334 dsc_private int
dsc_stricmp(const char * s,const char * t)3335 dsc_stricmp(const char *s, const char *t)
3336 {
3337 while (toupper(*s) == toupper(*t)) {
3338 if (*s == '\0')
3339 return 0;
3340 s++;
3341 t++;
3342 }
3343 return (toupper(*s) - toupper(*t));
3344 }
3345
3346
3347 dsc_private int
dsc_parse_page(CDSC * dsc)3348 dsc_parse_page(CDSC *dsc)
3349 {
3350 char *p;
3351 unsigned int i;
3352 char page_label[MAXSTR];
3353 char *pl;
3354 int page_ordinal;
3355 int page_number;
3356
3357 p = dsc->line + 7;
3358 pl = dsc_copy_string(page_label, sizeof(page_label)-1, p, dsc->line_length-7, &i);
3359 if (pl == NULL)
3360 return CDSC_ERROR;
3361 p += i;
3362 page_ordinal = atoi(p);
3363
3364 if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
3365 (dsc->page_count &&
3366 (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
3367 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
3368 dsc->line_length);
3369 switch (rc) {
3370 case CDSC_RESPONSE_OK:
3371 /* ignore this page */
3372 return CDSC_OK;
3373 case CDSC_RESPONSE_CANCEL:
3374 /* accept the page */
3375 break;
3376 case CDSC_RESPONSE_IGNORE_ALL:
3377 return CDSC_NOTDSC;
3378 }
3379 }
3380
3381 page_number = dsc->page_count;
3382 dsc_add_page(dsc, page_ordinal, page_label);
3383 dsc->page[page_number].begin = DSC_START(dsc);
3384 dsc->page[page_number].end = DSC_START(dsc);
3385
3386 if (dsc->page[page_number].label == NULL)
3387 return CDSC_ERROR; /* no memory */
3388
3389 return CDSC_OK;
3390 }
3391
3392
3393
3394 /* DSC error reporting */
3395
3396 void
dsc_debug_print(CDSC * dsc,const char * str)3397 dsc_debug_print(CDSC *dsc, const char *str)
3398 {
3399 if (dsc->debug_print_fn)
3400 dsc->debug_print_fn(dsc->caller_data, str);
3401 }
3402
3403
3404 /* Display a message about a problem with the DSC comments.
3405 *
3406 * explanation = an index to to a multiline explanation in dsc_message[]
3407 * line = pointer to the offending DSC line (if any)
3408 * return code =
3409 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
3410 * was really meant.
3411 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
3412 * is misplaced.
3413 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
3414 */
3415 /* Silent operation. Don't display errors. */
3416 dsc_private int
dsc_error(CDSC * dsc,unsigned int explanation,char * line,unsigned int line_len)3417 dsc_error(CDSC *dsc, unsigned int explanation,
3418 char *line, unsigned int line_len)
3419 {
3420 /* if error function provided, use it */
3421 if (dsc->dsc_error_fn)
3422 return dsc->dsc_error_fn(dsc->caller_data, dsc,
3423 explanation, line, line_len);
3424
3425 /* treat DSC as being correct */
3426 return CDSC_RESPONSE_CANCEL;
3427 }
3428
3429
3430 // vim:sw=4:sts=4:ts=8:noet
3431