1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17
18 /*
19 * This is a DSC parser, based on the DSC 3.0 spec,
20 * with a few DSC 2.1 additions for page size.
21 *
22 * Current limitations:
23 * %%+ may be used after any comment in the comment or trailer,
24 * but is currently only supported by
25 * %%DocumentMedia
26 *
27 * DSC 2.1 additions (discontinued in DSC 3.0):
28 * %%DocumentPaperColors:
29 * %%DocumentPaperForms:
30 * %%DocumentPaperSizes:
31 * %%DocumentPaperWeights:
32 * %%PaperColor: (ignored)
33 * %%PaperForm: (ignored)
34 * %%PaperSize:
35 * %%PaperWeight: (ignored)
36 *
37 * Other additions for defaults or page section
38 % %%ViewingOrientation: xx xy yx yy
39 */
40
41 #include <stdio_.h> /* for sprintf(), not file I/O */
42 #include <stdlib.h>
43 #include <string_.h>
44 #include <ctype.h>
45
46 #define MAXSTR 256
47
48 #include "dscparse.h"
49
50 /* Macros for comparing string literals
51 * For maximum speed, the length of the second macro argument is
52 * computed at compile time.
53 * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
54 */
55 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
56 #define IS_DSC(line, str) (COMPARE((line), (str)))
57
58 /* Macros for comparing the first one or two characters */
59 #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
60 #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
61 #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
62 #define IS_BLANK(str) (IS_EOL(str[0]))
63 #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
64
65 /* Macros for document offset to start and end of line */
66 #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
67 #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
68
69 /* dsc_scan_SECTION() functions return one of
70 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
71 * or one of the following
72 */
73 /* The line should be passed on to the next section parser. */
74 #define CDSC_PROPAGATE 10
75
76 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
77 #define CDSC_NEEDMORE 11
78
79 /* local prototypes */
80 static void * dsc_memalloc(CDSC *dsc, size_t size);
81 static void dsc_memfree(CDSC*dsc, void *ptr);
82 static CDSC * dsc_init2(CDSC *dsc);
83 static void dsc_reset(CDSC *dsc);
84 static void dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast);
85 static int dsc_read_line(CDSC *dsc);
86 static int dsc_read_doseps(CDSC *dsc);
87 static int dsc_read_macbin(CDSC *dsc);
88 static int dsc_read_applesingle(CDSC *dsc);
89 static char * dsc_alloc_string(CDSC *dsc, const char *str, int len);
90 static char * dsc_add_line(CDSC *dsc, const char *line, unsigned int len);
91 static char * dsc_copy_string(char *str, unsigned int slen,
92 char *line, unsigned int len, unsigned int *offset);
93 static GSDWORD dsc_get_dword(const unsigned char *buf);
94 static GSWORD dsc_get_word(const unsigned char *buf);
95 static GSDWORD dsc_get_bigendian_dword(const unsigned char *buf);
96 static GSWORD dsc_get_bigendian_word(const unsigned char *buf);
97 static int dsc_get_int(const char *line, unsigned int len, unsigned int *offset);
98 static float dsc_get_real(const char *line, unsigned int len,
99 unsigned int *offset);
100 static void dsc_unknown(CDSC *dsc);
101 static GSBOOL dsc_is_section(char *line);
102 static int dsc_parse_pages(CDSC *dsc);
103 static int dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset);
104 static int dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pfbbox, int offset);
105 static int dsc_parse_orientation(CDSC *dsc, unsigned int *porientation,
106 int offset);
107 static int dsc_parse_order(CDSC *dsc);
108 static int dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media);
109 static int dsc_parse_document_media(CDSC *dsc);
110 static int dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm);
111 static int dsc_parse_page(CDSC *dsc);
112 static void dsc_save_line(CDSC *dsc);
113 static int dsc_scan_type(CDSC *dsc);
114 static int dsc_scan_comments(CDSC *dsc);
115 static int dsc_scan_preview(CDSC *dsc);
116 static int dsc_scan_defaults(CDSC *dsc);
117 static int dsc_scan_prolog(CDSC *dsc);
118 static int dsc_scan_setup(CDSC *dsc);
119 static int dsc_scan_page(CDSC *dsc);
120 static int dsc_scan_trailer(CDSC *dsc);
121 static int dsc_error(CDSC *dsc, unsigned int explanation,
122 char *line, unsigned int line_len);
123 static int dsc_dcs2_fixup(CDSC *dsc);
124 static int dsc_parse_platefile(CDSC *dsc);
125 static int dsc_parse_dcs1plate(CDSC *dsc);
126 static CDSCCOLOUR * dsc_find_colour(CDSC *dsc, const char *colourname);
127 static int dsc_parse_process_colours(CDSC *dsc);
128 static int dsc_parse_custom_colours(CDSC *dsc);
129 static int dsc_parse_cmyk_custom_colour(CDSC *dsc);
130 static int dsc_parse_rgb_custom_colour(CDSC *dsc);
131
132 /* DSC error reporting */
133 static const int dsc_severity[] = {
134 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */
135 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */
136 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */
137 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
138 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */
139 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */
140 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */
141 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */
142 CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */
143 CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */
144 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */
145 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */
146 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */
147 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */
148 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */
149 CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */
150 0
151 };
152
153 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
154
155 const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = {
156 /* These sizes taken from Ghostscript gs_statd.ps */
157 {"11x17", 792, 1224, 0, NULL, NULL},
158 {"A3", 842, 1190, 0, NULL, NULL},
159 {"A4", 595, 842, 0, NULL, NULL},
160 {"A5", 421, 595, 0, NULL, NULL},
161 {"B4", 709, 1002, 0, NULL, NULL}, /* ISO, but not Adobe standard */
162 {"B5", 501, 709, 0, NULL, NULL}, /* ISO, but not Adobe standard */
163 {"Ledger", 1224, 792, 0, NULL, NULL},
164 {"Legal", 612, 1008, 0, NULL, NULL},
165 {"Letter", 612, 792, 0, NULL, NULL},
166 {"Note", 612, 792, 0, NULL, NULL},
167 {NULL, 0, 0, 0, NULL, NULL}
168 };
169
170 /* parser state */
171 enum CDSC_SCAN_SECTION {
172 scan_none = 0,
173 scan_comments = 1,
174 scan_pre_preview = 2,
175 scan_preview = 3,
176 scan_pre_defaults = 4,
177 scan_defaults = 5,
178 scan_pre_prolog = 6,
179 scan_prolog = 7,
180 scan_pre_setup = 8,
181 scan_setup = 9,
182 scan_pre_pages = 10,
183 scan_pages = 11,
184 scan_pre_trailer = 12,
185 scan_trailer = 13,
186 scan_eof = 14
187 };
188
189 static const char * const dsc_scan_section_name[15] = {
190 "Type", "Comments",
191 "pre-Preview", "Preview",
192 "pre-Defaults", "Defaults",
193 "pre-Prolog", "Prolog",
194 "pre-Setup", "Setup",
195 "pre-Page", "Page",
196 "pre-Trailer", "Trailer",
197 "EOF"
198 };
199
200 /******************************************************************/
201 /* Public functions */
202 /******************************************************************/
203
204 /* constructor */
205 CDSC *
dsc_init(void * caller_data)206 dsc_init(void *caller_data)
207 {
208 CDSC *dsc = (CDSC *)malloc(sizeof(CDSC));
209 if (dsc == NULL)
210 return NULL;
211 memset(dsc, 0, sizeof(CDSC));
212 dsc->caller_data = caller_data;
213 dsc->ref_count = 0;
214 dsc_ref(dsc);
215
216 return dsc_init2(dsc);
217 }
218
219 /* constructor, with caller supplied memalloc */
220 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)221 dsc_init_with_alloc(
222 void *caller_data,
223 void *(*memalloc)(size_t size, void *closure_data),
224 void (*memfree)(void *ptr, void *closure_data),
225 void *closure_data)
226 {
227 CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
228 if (dsc == NULL)
229 return NULL;
230 memset(dsc, 0, sizeof(CDSC));
231 dsc->caller_data = caller_data;
232
233 dsc->memalloc = memalloc;
234 dsc->memfree = memfree;
235 dsc->mem_closure_data = closure_data;
236 dsc->ref_count = 0;
237 dsc_ref(dsc);
238
239 return dsc_init2(dsc);
240 }
241
242 /* destructor */
243 void
dsc_free(CDSC * dsc)244 dsc_free(CDSC *dsc)
245 {
246 if (dsc == NULL)
247 return;
248 dsc_reset(dsc);
249 dsc_memfree(dsc, dsc);
250 }
251
252 CDSC *
dsc_new(void * caller_data)253 dsc_new(void *caller_data)
254 {
255 return dsc_init(caller_data);
256 }
257
258 int
dsc_ref(CDSC * dsc)259 dsc_ref(CDSC *dsc)
260 {
261 return ++(dsc->ref_count);
262 }
263
264 int
dsc_unref(CDSC * dsc)265 dsc_unref(CDSC *dsc)
266 {
267 if (dsc->ref_count <= 0)
268 return -1;
269 dsc->ref_count--;
270 if (dsc->ref_count == 0) {
271 dsc_free(dsc);
272 return 0;
273 }
274 return dsc->ref_count;
275 }
276
277 /* Tell DSC parser how long document will be, to allow ignoring
278 * of early %%Trailer and %%EOF. This is optional.
279 */
280 void
dsc_set_length(CDSC * dsc,DSC_OFFSET len)281 dsc_set_length(CDSC *dsc, DSC_OFFSET len)
282 {
283 dsc->file_length = len;
284 }
285
286 /* Process a buffer containing DSC comments and PostScript */
287 /* Return value is < 0 for error, >=0 for OK.
288 * CDSC_ERROR
289 * CDSC_OK
290 * CDSC_NOTDSC (DSC will be ignored)
291 * other values indicate the last DSC comment read
292 */
293 int
dsc_scan_data(CDSC * dsc,const char * data,int length)294 dsc_scan_data(CDSC *dsc, const char *data, int length)
295 {
296 int bytes_read;
297 int code = 0;
298
299 if (dsc == NULL)
300 return CDSC_ERROR;
301
302 if (dsc->id == CDSC_NOTDSC)
303 return CDSC_NOTDSC;
304 dsc->id = CDSC_OK;
305 if (dsc->eof)
306 return CDSC_OK; /* ignore */
307
308 if (length == 0) {
309 /* EOF, so process what remains */
310 dsc->eof = TRUE;
311 }
312
313 do {
314 if (dsc->id == CDSC_NOTDSC)
315 break;
316
317 if (length != 0) {
318 /* move existing data if needed */
319 if (dsc->data_length > CDSC_DATA_LENGTH/2) {
320 memmove(dsc->data, dsc->data + dsc->data_index,
321 dsc->data_length - dsc->data_index);
322 dsc->data_offset += dsc->data_index;
323 dsc->data_length -= dsc->data_index;
324 dsc->data_index = 0;
325 }
326 /* append to buffer */
327 bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
328 memcpy(dsc->data + dsc->data_length, data, bytes_read);
329 dsc->data_length += bytes_read;
330 data += bytes_read;
331 length -= bytes_read;
332 }
333 if (dsc->scan_section == scan_none) {
334 code = dsc_scan_type(dsc);
335 if (code == CDSC_NEEDMORE) {
336 /* need more characters before we can identify type */
337 code = CDSC_OK;
338 break;
339 }
340 dsc->id = code;
341 }
342
343 if (code == CDSC_NOTDSC) {
344 dsc->id = CDSC_NOTDSC;
345 break;
346 }
347
348 while ((code = dsc_read_line(dsc)) > 0) {
349 if (dsc->id == CDSC_NOTDSC)
350 break;
351 if (dsc->file_length &&
352 (dsc->data_offset + dsc->data_index > dsc->file_length)) {
353 /* have read past end of where we need to parse. */
354 return CDSC_OK; /* ignore */
355 }
356 if (dsc->doseps_end &&
357 (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
358 /* have read past end of DOS EPS or Mac Binary
359 * PostScript section
360 */
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 DSC_OFFSET *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: EOF before end of %%BeginData */
449 if (dsc->eof &&
450 (dsc->skip_lines || dsc->skip_bytes || dsc->skip_document)) {
451 switch (dsc->scan_section) {
452 case scan_comments:
453 dsc->endcomments = DSC_END(dsc);
454 break;
455 case scan_preview:
456 dsc->endpreview = DSC_END(dsc);
457 break;
458 case scan_defaults:
459 dsc->enddefaults = DSC_END(dsc);
460 break;
461 case scan_prolog:
462 dsc->endprolog = DSC_END(dsc);
463 break;
464 case scan_setup:
465 dsc->endsetup = DSC_END(dsc);
466 break;
467 case scan_pages:
468 if (dsc->page_count)
469 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
470 break;
471 case scan_trailer:
472 case scan_eof:
473 dsc->endtrailer = DSC_END(dsc);
474 break;
475 }
476 }
477
478 /* Fix DSC error: code between %%EndSetup and %%Page */
479 if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup)
480 && (dsc->endsetup != dsc->beginsetup)) {
481 dsc->endsetup = dsc->page[0].begin;
482 dsc_debug_print(dsc, "Warning: code included between setup and first page\n");
483 }
484
485 /* Last page contained a false trailer, */
486 /* so extend last page to start of trailer */
487 if (dsc->page_count && (dsc->begintrailer != 0) &&
488 (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) {
489 dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n");
490 dsc_debug_print(dsc, "and extending last page to start of trailer\n");
491 dsc->page[dsc->page_count-1].end = dsc->begintrailer;
492 }
493
494 /*
495 * Join up all sections.
496 * There might be extra code between them, or we might have
497 * missed including the \n which followed \r.
498 */
499 last = &dsc->endcomments;
500 dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last);
501 dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last);
502 dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last);
503 dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
504 for (i=0; i<dsc->page_count; i++)
505 dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last);
506 if (dsc->begintrailer)
507 *last = dsc->begintrailer;
508
509 if ((dsc->page_pages == 0) && (dsc->page_count == 1)) {
510 /* don't flag an error if %%Pages absent but one %%Page found */
511 /* adjust incorrect page count */
512 dsc->page_pages = dsc->page_count;
513 }
514
515 /* Warnings and Errors that we can now identify */
516 if ((dsc->page_count != dsc->page_pages)) {
517 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0);
518 switch (rc) {
519 case CDSC_RESPONSE_OK:
520 /* adjust incorrect page count */
521 dsc->page_pages = dsc->page_count;
522 break;
523 case CDSC_RESPONSE_CANCEL:
524 break;;
525 case CDSC_RESPONSE_IGNORE_ALL:
526 return CDSC_NOTDSC;
527 }
528 }
529
530 if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) {
531 /* EPS files MUST include a BoundingBox */
532 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0);
533 switch (rc) {
534 case CDSC_RESPONSE_OK:
535 /* Assume that it is EPS */
536 break;
537 case CDSC_RESPONSE_CANCEL:
538 /* Is NOT an EPS file */
539 dsc->epsf = FALSE;
540 case CDSC_RESPONSE_IGNORE_ALL:
541 return CDSC_NOTDSC;
542 }
543 }
544
545 if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) {
546 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0);
547 switch (rc) {
548 case CDSC_RESPONSE_OK:
549 /* Is an EPS file */
550 break;
551 case CDSC_RESPONSE_CANCEL:
552 /* Is NOT an EPS file */
553 dsc->epsf = FALSE;
554 break;
555 case CDSC_RESPONSE_IGNORE_ALL:
556 return CDSC_NOTDSC;
557 }
558 }
559
560 /* convert single file DSC 2.0 into multiple pages */
561 dsc_dcs2_fixup(dsc);
562
563 if ((dsc->media_count == 1) && (dsc->page_media == NULL)) {
564 /* if one only media was specified, and default page media */
565 /* was not specified, assume that default is the only media. */
566 dsc->page_media = dsc->media[0];
567 }
568
569 if ((dsc->media_count != 0) && (dsc->page_media == NULL)) {
570 int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0);
571 switch (rc) {
572 case CDSC_RESPONSE_OK:
573 /* default media is first listed */
574 dsc->page_media = dsc->media[0];
575 break;
576 case CDSC_RESPONSE_CANCEL:
577 /* No default media */
578 break;
579 case CDSC_RESPONSE_IGNORE_ALL:
580 return CDSC_NOTDSC;
581 }
582 }
583
584 /* make sure all pages have a label */
585 for (i=0; i<dsc->page_count; i++) {
586 if (strlen(dsc->page[i].label) == 0) {
587 gs_sprintf(buf, "%d", i+1);
588 if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf)))
589 == (char *)NULL)
590 return CDSC_ERROR; /* no memory */
591 }
592 }
593 return CDSC_OK;
594 }
595
596 /* Install a function to be used for displaying messages about
597 * DSC errors and warnings, and to request advice from user.
598 * Installing an error function is optional.
599 */
600 void
dsc_set_error_function(CDSC * dsc,int (* fn)(void * caller_data,CDSC * dsc,unsigned int explanation,const char * line,unsigned int line_len))601 dsc_set_error_function(CDSC *dsc,
602 int (*fn)(void *caller_data, CDSC *dsc,
603 unsigned int explanation, const char *line, unsigned int line_len))
604 {
605 dsc->dsc_error_fn = fn;
606 }
607
608 /* Install a function for printing debug messages */
609 /* This is optional */
610 void
dsc_set_debug_function(CDSC * dsc,void (* debug_fn)(void * caller_data,const char * str))611 dsc_set_debug_function(CDSC *dsc,
612 void (*debug_fn)(void *caller_data, const char *str))
613 {
614 dsc->debug_print_fn = debug_fn;
615 }
616
617 /* Doesn't need to be public for PostScript documents */
618 /* Made public so GSview can add pages when processing PDF files */
619 int
dsc_add_page(CDSC * dsc,int ordinal,char * label)620 dsc_add_page(CDSC *dsc, int ordinal, char *label)
621 {
622 dsc->page[dsc->page_count].ordinal = ordinal;
623 dsc->page[dsc->page_count].label =
624 dsc_alloc_string(dsc, label, (int)strlen(label)+1);
625 dsc->page[dsc->page_count].begin = 0;
626 dsc->page[dsc->page_count].end = 0;
627 dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
628 dsc->page[dsc->page_count].media = NULL;
629 dsc->page[dsc->page_count].bbox = NULL;
630 dsc->page[dsc->page_count].viewing_orientation = NULL;
631 dsc->page[dsc->page_count].crop_box = NULL;
632
633 dsc->page_count++;
634 if (dsc->page_count >= dsc->page_chunk_length) {
635 CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc,
636 (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE));
637 if (new_page == NULL)
638 return CDSC_ERROR; /* out of memory */
639 memcpy(new_page, dsc->page,
640 dsc->page_count * sizeof(CDSCPAGE));
641 dsc_memfree(dsc, dsc->page);
642 dsc->page= new_page;
643 dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count;
644 }
645 return CDSC_OK;
646 }
647
648 /* Doesn't need to be public for PostScript documents */
649 /* Made public so GSview can store PDF MediaBox */
650 int
dsc_add_media(CDSC * dsc,CDSCMEDIA * media)651 dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
652 {
653 CDSCMEDIA **newmedia_array;
654 CDSCMEDIA *newmedia;
655
656 /* extend media array */
657 newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc,
658 (dsc->media_count + 1) * sizeof(CDSCMEDIA *));
659 if (newmedia_array == NULL)
660 return CDSC_ERROR; /* out of memory */
661 if (dsc->media != NULL) {
662 memcpy(newmedia_array, dsc->media,
663 dsc->media_count * sizeof(CDSCMEDIA *));
664 dsc_memfree(dsc, dsc->media);
665 }
666 dsc->media = newmedia_array;
667
668 /* allocate new media */
669 newmedia = dsc->media[dsc->media_count] =
670 (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA));
671 if (newmedia == NULL)
672 return CDSC_ERROR; /* out of memory */
673 newmedia->name = NULL;
674 newmedia->width = 595.0;
675 newmedia->height = 842.0;
676 newmedia->weight = 80.0;
677 newmedia->colour = NULL;
678 newmedia->type = NULL;
679 newmedia->mediabox = NULL;
680
681 dsc->media_count++;
682
683 if (media->name) {
684 newmedia->name = dsc_alloc_string(dsc, media->name,
685 (int)strlen(media->name));
686 if (newmedia->name == NULL)
687 return CDSC_ERROR; /* no memory */
688 }
689 newmedia->width = media->width;
690 newmedia->height = media->height;
691 newmedia->weight = media->weight;
692 if (media->colour) {
693 newmedia->colour = dsc_alloc_string(dsc, media->colour,
694 (int)strlen(media->colour));
695 if (newmedia->colour == NULL)
696 return CDSC_ERROR; /* no memory */
697 }
698 if (media->type) {
699 newmedia->type = dsc_alloc_string(dsc, media->type,
700 (int)strlen(media->type));
701 if (newmedia->type == NULL)
702 return CDSC_ERROR; /* no memory */
703 }
704 newmedia->mediabox = NULL;
705
706 if (media->mediabox) {
707 newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
708 if (newmedia->mediabox == NULL)
709 return CDSC_ERROR; /* no memory */
710 *newmedia->mediabox = *media->mediabox;
711 }
712 return CDSC_OK;
713 }
714
715 /* Doesn't need to be public for PostScript documents */
716 /* Made public so GSview can store PDF CropBox */
717 int
dsc_set_page_bbox(CDSC * dsc,unsigned int page_number,int llx,int lly,int urx,int ury)718 dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
719 int llx, int lly, int urx, int ury)
720 {
721 CDSCBBOX *bbox;
722 if (page_number >= dsc->page_count)
723 return CDSC_ERROR;
724 bbox = dsc->page[page_number].bbox;
725 if (bbox == NULL)
726 dsc->page[page_number].bbox = bbox =
727 (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
728 if (bbox == NULL)
729 return CDSC_ERROR;
730 bbox->llx = llx;
731 bbox->lly = lly;
732 bbox->urx = urx;
733 bbox->ury = ury;
734 return CDSC_OK;
735 }
736
737 /******************************************************************/
738 /* Private functions below here. */
739 /******************************************************************/
740
741 static void *
dsc_memalloc(CDSC * dsc,size_t size)742 dsc_memalloc(CDSC *dsc, size_t size)
743 {
744 if (dsc->memalloc)
745 return dsc->memalloc(size, dsc->mem_closure_data);
746 return malloc(size);
747 }
748
749 static void
dsc_memfree(CDSC * dsc,void * ptr)750 dsc_memfree(CDSC*dsc, void *ptr)
751 {
752 if (dsc->memfree)
753 dsc->memfree(ptr, dsc->mem_closure_data);
754 else
755 free(ptr);
756 }
757
758 /* private constructor */
759 static CDSC *
dsc_init2(CDSC * dsc)760 dsc_init2(CDSC *dsc)
761 {
762 dsc_reset(dsc);
763
764 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
765 if (dsc->string_head == NULL) {
766 dsc_free(dsc);
767 return NULL; /* no memory */
768 }
769 dsc->string = dsc->string_head;
770 dsc->string->next = NULL;
771 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
772 if (dsc->string->data == NULL) {
773 dsc_free(dsc);
774 return NULL; /* no memory */
775 }
776 dsc->string->index = 0;
777 dsc->string->length = CDSC_STRING_CHUNK;
778
779 dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
780 if (dsc->page == NULL) {
781 dsc_free(dsc);
782 return NULL; /* no memory */
783 }
784 dsc->page_chunk_length = CDSC_PAGE_CHUNK;
785 dsc->page_count = 0;
786
787 dsc->line = NULL;
788 dsc->data_length = 0;
789 dsc->data_index = dsc->data_length;
790
791 return dsc;
792 }
793
794 static void
dsc_reset(CDSC * dsc)795 dsc_reset(CDSC *dsc)
796 {
797 unsigned int i;
798 /* Clear public members */
799 dsc->dsc = FALSE;
800 dsc->ctrld = FALSE;
801 dsc->pjl = FALSE;
802 dsc->epsf = FALSE;
803 dsc->pdf = FALSE;
804 dsc->epsf = FALSE;
805 dsc->preview = CDSC_NOPREVIEW;
806 dsc->dsc_version = NULL; /* stored in dsc->string */
807 dsc->language_level = 0;
808 dsc->document_data = CDSC_DATA_UNKNOWN;
809 dsc->begincomments = 0;
810 dsc->endcomments = 0;
811 dsc->beginpreview = 0;
812 dsc->endpreview = 0;
813 dsc->begindefaults = 0;
814 dsc->enddefaults = 0;
815 dsc->beginprolog = 0;
816 dsc->endprolog = 0;
817 dsc->beginsetup = 0;
818 dsc->endsetup = 0;
819 dsc->begintrailer = 0;
820 dsc->endtrailer = 0;
821
822 for (i=0; i<dsc->page_count; i++) {
823 /* page media is pointer to an element of media or dsc_known_media */
824 /* do not free it. */
825
826 if (dsc->page[i].bbox)
827 dsc_memfree(dsc, dsc->page[i].bbox);
828 if (dsc->page[i].viewing_orientation)
829 dsc_memfree(dsc, dsc->page[i].viewing_orientation);
830 if (dsc->page[i].crop_box)
831 dsc_memfree(dsc, dsc->page[i].crop_box);
832 }
833 if (dsc->page)
834 dsc_memfree(dsc, dsc->page);
835 dsc->page = NULL;
836
837 dsc->page_count = 0;
838 dsc->page_pages = 0;
839 dsc->page_order = CDSC_ORDER_UNKNOWN;
840 dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
841 if (dsc->viewing_orientation)
842 dsc_memfree(dsc, dsc->viewing_orientation);
843 dsc->viewing_orientation = NULL;
844
845 if (dsc->media) {
846 for (i=0; i<dsc->media_count; i++) {
847 if (dsc->media[i]) {
848 if (dsc->media[i]->mediabox)
849 dsc_memfree(dsc, dsc->media[i]->mediabox);
850 dsc_memfree(dsc, dsc->media[i]);
851 }
852 }
853 dsc_memfree(dsc, dsc->media);
854 }
855 dsc->media_count = 0;
856 dsc->media = NULL;
857
858 /* page_media is pointer to an element of media or dsc_known_media */
859 /* do not free it. */
860 dsc->page_media = NULL;
861
862 if (dsc->bbox)
863 dsc_memfree(dsc, dsc->bbox);
864 dsc->bbox = NULL;
865 if (dsc->page_bbox)
866 dsc_memfree(dsc, dsc->page_bbox);
867 dsc->page_bbox = NULL;
868 if (dsc->doseps)
869 dsc_memfree(dsc, dsc->doseps);
870 dsc->doseps = NULL;
871
872 dsc->dsc_title = NULL;
873 dsc->dsc_creator = NULL;
874 dsc->dsc_date = NULL;
875 dsc->dsc_for = NULL;
876
877 dsc->max_error = DSC_MAX_ERROR;
878 dsc->severity = dsc_severity;
879
880 /* Clear private members */
881 /* Don't touch dsc->caller_data */
882 dsc->id = CDSC_OK;
883 dsc->scan_section = scan_none;
884 dsc->doseps_end = 0;
885 dsc->page_chunk_length = 0;
886 dsc->file_length = 0;
887 dsc->skip_document = 0;
888 dsc->skip_bytes = 0;
889 dsc->skip_lines = 0;
890 dsc->skip_pjl = 0;
891 dsc->begin_font_count = 0;
892 dsc->begin_feature_count = 0;
893 dsc->begin_resource_count = 0;
894 dsc->begin_procset_count = 0;
895
896 dsc->data_length = 0;
897 dsc->data_index = 0;
898 dsc->data_offset = 0;
899
900 dsc->eof = 0;
901
902 dsc->line = 0;
903 dsc->line_length = 0;
904 dsc->eol = 0;
905 dsc->last_cr = FALSE;
906 dsc->line_count = 1;
907 dsc->long_line = FALSE;
908 memset(dsc->last_line, 0, sizeof(dsc->last_line));
909
910 dsc->string = dsc->string_head;
911 while (dsc->string != (CDSCSTRING *)NULL) {
912 if (dsc->string->data)
913 dsc_memfree(dsc, dsc->string->data);
914 dsc->string_head = dsc->string;
915 dsc->string = dsc->string->next;
916 dsc_memfree(dsc, dsc->string_head);
917 }
918 dsc->string_head = NULL;
919 dsc->string = NULL;
920
921 /* don't touch caller functions */
922
923 /* public data */
924 if (dsc->hires_bbox)
925 dsc_memfree(dsc, dsc->hires_bbox);
926 dsc->hires_bbox = NULL;
927 if (dsc->crop_box)
928 dsc_memfree(dsc, dsc->crop_box);
929 dsc->crop_box = NULL;
930
931 if (dsc->dcs2) {
932 CDCS2 *this_dcs, *next_dcs;
933 this_dcs = dsc->dcs2;
934 while (this_dcs) {
935 next_dcs = this_dcs->next;
936 /* strings have already been freed */
937 dsc_memfree(dsc, this_dcs);
938 this_dcs = next_dcs;
939 }
940 dsc->dcs2 = NULL;
941 }
942 if (dsc->colours) {
943 CDSCCOLOUR *this_colour, *next_colour;
944 this_colour = dsc->colours;
945 while (this_colour) {
946 next_colour = this_colour->next;
947 /* strings have already been freed */
948 dsc_memfree(dsc, this_colour);
949 this_colour = next_colour;
950 }
951 dsc->colours = NULL;
952 }
953
954 if (dsc->macbin)
955 dsc_memfree(dsc, dsc->macbin);
956 dsc->macbin = NULL;
957 }
958
959 /*
960 * Join up all sections.
961 * There might be extra code between them, or we might have
962 * missed including the \n which followed \r.
963 * begin is the start of this section
964 * pend is a pointer to the end of this section
965 * pplast is a pointer to a pointer of the end of the previous section
966 */
967 static void
dsc_section_join(DSC_OFFSET begin,DSC_OFFSET * pend,DSC_OFFSET ** pplast)968 dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast)
969 {
970 if (begin)
971 **pplast = begin;
972 if (*pend > begin)
973 *pplast = pend;
974 }
975
976 /* return value is 0 if no line available, or length of line */
977 static int
dsc_read_line(CDSC * dsc)978 dsc_read_line(CDSC *dsc)
979 {
980 char *p, *last;
981 dsc->line = NULL;
982
983 if (dsc->eof) {
984 /* return all that remains, even if line incomplete */
985 dsc->line = dsc->data + dsc->data_index;
986 dsc->line_length = dsc->data_length - dsc->data_index;
987 dsc->data_index = dsc->data_length;
988 return dsc->line_length;
989 }
990
991 if (dsc->file_length &&
992 (dsc->data_offset + dsc->data_index >= dsc->file_length)) {
993 /* Have read past where we need to parse. */
994 /* Ignore all that remains. */
995 dsc->line = dsc->data + dsc->data_index;
996 dsc->line_length = dsc->data_length - dsc->data_index;
997 dsc->data_index = dsc->data_length;
998 return dsc->line_length;
999
1000 }
1001 if (dsc->doseps_end &&
1002 (dsc->data_offset + dsc->data_index >= dsc->doseps_end)) {
1003 /* Have read past end of DOS EPS PostScript section. */
1004 /* Ignore all that remains. */
1005 dsc->line = dsc->data + dsc->data_index;
1006 dsc->line_length = dsc->data_length - dsc->data_index;
1007 dsc->data_index = dsc->data_length;
1008 return dsc->line_length;
1009 }
1010
1011 /* ignore embedded bytes */
1012 if (dsc->skip_bytes) {
1013 int cnt = min(dsc->skip_bytes,
1014 (int)(dsc->data_length - dsc->data_index));
1015 dsc->skip_bytes -= cnt;
1016 dsc->data_index += cnt;
1017 if (dsc->skip_bytes != 0)
1018 return 0;
1019 }
1020
1021 do {
1022 dsc->line = dsc->data + dsc->data_index;
1023 last = dsc->data + dsc->data_length;
1024 if (dsc->data_index == dsc->data_length) {
1025 dsc->line_length = 0;
1026 return 0;
1027 }
1028 if (dsc->eol) {
1029 /* if previous line was complete, increment line count */
1030 dsc->line_count++;
1031 if (dsc->skip_lines)
1032 dsc->skip_lines--;
1033 }
1034
1035 /* skip over \n which followed \r */
1036 if (dsc->last_cr && dsc->line[0] == '\n') {
1037 dsc->data_index++;
1038 dsc->line++;
1039 }
1040 dsc->last_cr = FALSE;
1041
1042 /* look for EOL */
1043 dsc->eol = FALSE;
1044 for (p = dsc->line; p < last; p++) {
1045 if (*p == '\r') {
1046 p++;
1047 if ((p<last) && (*p == '\n'))
1048 p++; /* include line feed also */
1049 else
1050 dsc->last_cr = TRUE; /* we might need to skip \n */
1051 dsc->eol = TRUE; /* dsc->line is a complete line */
1052 break;
1053 }
1054 if (*p == '\n') {
1055 p++;
1056 dsc->eol = TRUE; /* dsc->line is a complete line */
1057 break;
1058 }
1059 if (*p == '\032') { /* MS-DOS Ctrl+Z */
1060 dsc->eol = TRUE;
1061 }
1062 }
1063 if (dsc->eol == FALSE) {
1064 /* we haven't got a complete line yet */
1065 if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) {
1066 /* buffer is less than half full, ask for some more */
1067 dsc->line_length = 0;
1068 return 0;
1069 }
1070 }
1071 dsc->data_index += dsc->line_length = (int)(p - dsc->line);
1072 } while (dsc->skip_lines && dsc->line_length);
1073
1074 if (dsc->line_length == 0)
1075 return 0;
1076
1077 if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) {
1078 /* handle recursive %%BeginDocument */
1079 if ((dsc->skip_document) && dsc->line_length &&
1080 COMPARE(dsc->line, "%%EndDocument")) {
1081 dsc->skip_document--;
1082 }
1083
1084 /* handle embedded lines or binary data */
1085 if (COMPARE(dsc->line, "%%BeginData:")) {
1086 /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
1087 * <numberof> ::= <uint> (Lines or physical bytes)
1088 * <type> ::= Hex | Binary | ASCII (Type of data)
1089 * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
1090 */
1091 char begindata[MAXSTR+1], *bdatalast = NULL;
1092 int cnt;
1093 const char *numberof, *bytesorlines;
1094 cnt = dsc->line_length;
1095 if (dsc->line_length > sizeof(begindata)-1)
1096 cnt = sizeof(begindata)-1;
1097 memcpy(begindata, dsc->line, cnt);
1098 begindata[cnt] = '\0';
1099 numberof = gs_strtok(begindata+12, " \r\n", &bdatalast);
1100 gs_strtok(NULL, " \r\n", &bdatalast); /* dump type */
1101 bytesorlines = gs_strtok(NULL, " \r\n", &bdatalast);
1102 if (bytesorlines == NULL)
1103 bytesorlines = "Bytes";
1104
1105 if ( (numberof == NULL) || (bytesorlines == NULL) ) {
1106 /* invalid usage of %%BeginData */
1107 /* ignore that we ever saw it */
1108 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE,
1109 dsc->line, dsc->line_length);
1110 switch (rc) {
1111 case CDSC_RESPONSE_OK:
1112 case CDSC_RESPONSE_CANCEL:
1113 break;
1114 case CDSC_RESPONSE_IGNORE_ALL:
1115 return 0;
1116 }
1117 }
1118 else {
1119 cnt = atoi(numberof);
1120 if (cnt) {
1121 if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) {
1122 /* skip cnt lines */
1123 if (dsc->skip_lines == 0) {
1124 /* we are not already skipping lines */
1125 dsc->skip_lines = cnt+1;
1126 }
1127 }
1128 else {
1129 /* byte count doesn't includes \n or \r\n */
1130 /* or \r of %%BeginData: */
1131 /* skip cnt bytes */
1132 if (dsc->skip_bytes == 0) {
1133 /* we are not already skipping lines */
1134 dsc->skip_bytes = cnt;
1135 }
1136
1137 }
1138 }
1139 }
1140 }
1141 else if (COMPARE(dsc->line, "%%BeginBinary:")) {
1142 /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
1143 int cnt = dsc_get_int(dsc->line + 14,
1144 dsc->line_length - 14, NULL);
1145 if (dsc->skip_bytes == 0) {
1146 /* we are not already skipping lines */
1147 dsc->skip_bytes = cnt;
1148 }
1149 }
1150 }
1151
1152 if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
1153 COMPARE(dsc->line, "%%BeginDocument:") ) {
1154 /* Skip over embedded document, recursively */
1155 dsc->skip_document++;
1156 }
1157
1158 if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
1159 dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
1160 dsc->long_line = TRUE;
1161 }
1162
1163 return dsc->line_length;
1164 }
1165
1166 /* Save last DSC line, for use with %%+ */
1167 static void
dsc_save_line(CDSC * dsc)1168 dsc_save_line(CDSC *dsc)
1169 {
1170 int len = min(sizeof(dsc->last_line), dsc->line_length);
1171 memcpy(dsc->last_line, dsc->line, len);
1172 }
1173
1174 /* display unknown DSC line */
1175 static void
dsc_unknown(CDSC * dsc)1176 dsc_unknown(CDSC *dsc)
1177 {
1178 if (dsc->debug_print_fn) {
1179 char line[DSC_LINE_LENGTH];
1180 unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
1181 gs_sprintf(line, "Unknown in %s section at line %d:\n ",
1182 dsc_scan_section_name[dsc->scan_section], dsc->line_count);
1183 dsc_debug_print(dsc, line);
1184 strncpy(line, dsc->line, length);
1185 line[length] = '\0';
1186 dsc_debug_print(dsc, line);
1187 dsc_debug_print(dsc, "\n");
1188 }
1189 }
1190
1191 static GSBOOL
dsc_is_section(char * line)1192 dsc_is_section(char *line)
1193 {
1194 if ( !((line[0]=='%') && (line[1]=='%')) )
1195 return FALSE;
1196 if (IS_DSC(line, "%%BeginPreview"))
1197 return TRUE;
1198 if (IS_DSC(line, "%%BeginDefaults"))
1199 return TRUE;
1200 if (IS_DSC(line, "%%BeginProlog"))
1201 return TRUE;
1202 if (IS_DSC(line, "%%BeginSetup"))
1203 return TRUE;
1204 if (IS_DSC(line, "%%Page:"))
1205 return TRUE;
1206 if (IS_DSC(line, "%%Trailer"))
1207 return TRUE;
1208 if (IS_DSC(line, "%%EOF"))
1209 return TRUE;
1210 return FALSE;
1211 }
1212
1213 /* Get little-endian DWORD, used for DOS EPS files */
1214 static GSDWORD
dsc_get_dword(const unsigned char * buf)1215 dsc_get_dword(const unsigned char *buf)
1216 {
1217 GSDWORD dw;
1218 dw = (GSDWORD)buf[0];
1219 dw += ((GSDWORD)buf[1])<<8;
1220 dw += ((GSDWORD)buf[2])<<16;
1221 dw += ((GSDWORD)buf[3])<<24;
1222 return dw;
1223 }
1224
1225 static GSWORD
dsc_get_word(const unsigned char * buf)1226 dsc_get_word(const unsigned char *buf)
1227 {
1228 GSWORD w;
1229 w = (GSWORD)buf[0];
1230 w |= (GSWORD)(buf[1]<<8);
1231 return w;
1232 }
1233
1234 /* Get big-endian DWORD, used for Mac Binary files */
1235 static GSDWORD
dsc_get_bigendian_dword(const unsigned char * buf)1236 dsc_get_bigendian_dword(const unsigned char *buf)
1237 {
1238 GSDWORD dw;
1239 dw = (GSDWORD)buf[3];
1240 dw += ((GSDWORD)buf[2])<<8;
1241 dw += ((GSDWORD)buf[1])<<16;
1242 dw += ((GSDWORD)buf[0])<<24;
1243 return dw;
1244 }
1245
1246 static GSWORD
dsc_get_bigendian_word(const unsigned char * buf)1247 dsc_get_bigendian_word(const unsigned char *buf)
1248 {
1249 GSWORD w;
1250 w = (GSWORD)buf[1];
1251 w |= (GSWORD)(buf[0]<<8);
1252 return w;
1253 }
1254
1255 static int
dsc_read_doseps(CDSC * dsc)1256 dsc_read_doseps(CDSC *dsc)
1257 {
1258 unsigned char *line = (unsigned char *)dsc->line;
1259 if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL)
1260 return CDSC_ERROR; /* no memory */
1261
1262 dsc->doseps->ps_begin = dsc_get_dword(line+4);
1263 dsc->doseps->ps_length = dsc_get_dword(line+8);
1264 dsc->doseps->wmf_begin = dsc_get_dword(line+12);
1265 dsc->doseps->wmf_length = dsc_get_dword(line+16);
1266 dsc->doseps->tiff_begin = dsc_get_dword(line+20);
1267 dsc->doseps->tiff_length = dsc_get_dword(line+24);
1268 dsc->doseps->checksum = dsc_get_word(line+28);
1269
1270 if (dsc->file_length &&
1271 (dsc->doseps->ps_begin + dsc->doseps->ps_length > dsc->file_length)) {
1272 /* Error in DOS EPS header.
1273 * Some files have been seen with a fixed large value as
1274 * the length of the PostScript section.
1275 * Correct for these erroneous files.
1276 */
1277 dsc->doseps->ps_length =
1278 (GSDWORD)(dsc->file_length - dsc->doseps->ps_begin);
1279 }
1280
1281 dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
1282
1283 /* move data_index backwards to byte after doseps header */
1284 dsc->data_index -= dsc->line_length - 30;
1285 /* we haven't read a line of PostScript code yet */
1286 dsc->line_count = 0;
1287 /* skip from current position to start of PostScript section */
1288 dsc->skip_bytes = dsc->doseps->ps_begin - 30;
1289
1290 if (dsc->doseps->tiff_begin)
1291 dsc->preview = CDSC_TIFF;
1292 if (dsc->doseps->wmf_begin)
1293 dsc->preview = CDSC_WMF;
1294
1295 return CDSC_OK;
1296 }
1297
1298 static int
dsc_read_macbin(CDSC * dsc)1299 dsc_read_macbin(CDSC *dsc)
1300 {
1301 unsigned char *line = (unsigned char *)dsc->line;
1302 if ((dsc->macbin =
1303 (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
1304 return CDSC_ERROR; /* no memory */
1305
1306 dsc->macbin->data_begin = 128;
1307 dsc->macbin->data_length = dsc_get_bigendian_dword(line+83);
1308 dsc->macbin->resource_begin =
1309 (dsc->macbin->data_begin + dsc->macbin->data_length + 127 ) & ~127;
1310 dsc->macbin->resource_length = dsc_get_bigendian_dword(line+87);
1311
1312 if (dsc->file_length &&
1313 (((dsc->macbin->resource_begin + dsc->macbin->resource_length
1314 + 127) & ~127) > dsc->file_length)) {
1315 return CDSC_ERROR;
1316 }
1317
1318 dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
1319
1320 /* move data_index to byte after Mac Binary header */
1321 dsc->data_index -= dsc->line_length - 128;
1322 /* we haven't read a line of PostScript code yet */
1323 dsc->line_count = 0;
1324
1325 dsc->preview = CDSC_PICT;
1326
1327 return CDSC_OK;
1328 }
1329
1330 static int
dsc_read_applesingle(CDSC * dsc)1331 dsc_read_applesingle(CDSC *dsc)
1332 {
1333 GSDWORD EntryID;
1334 GSDWORD Offset;
1335 GSDWORD Length;
1336 GSWORD entries;
1337 int index;
1338 int header;
1339 int i;
1340
1341 unsigned char *line = (unsigned char *)dsc->line;
1342 if ((dsc->macbin =
1343 (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
1344 return CDSC_ERROR; /* no memory */
1345 entries = dsc_get_bigendian_word(line+24);
1346 for (i=0; i<(int)entries; i++) {
1347 index = 26 + i * 12;
1348 EntryID = dsc_get_bigendian_dword(line+index);
1349 Offset = dsc_get_bigendian_dword(line+index+4);
1350 Length = dsc_get_bigendian_dword(line+index+8);
1351 if (EntryID == 1) {
1352 /* data fork */
1353 dsc->macbin->data_begin = Offset;
1354 dsc->macbin->data_length = Length;
1355 }
1356 else if (EntryID == 2) {
1357 /* resource fork */
1358 dsc->macbin->resource_begin = Offset;
1359 dsc->macbin->resource_length = Length;
1360 }
1361 }
1362
1363 if (dsc->file_length &&
1364 (dsc->macbin->resource_begin + dsc->macbin->resource_length
1365 > dsc->file_length)) {
1366 return CDSC_ERROR;
1367 }
1368 if (dsc->file_length &&
1369 (dsc->macbin->data_begin + dsc->macbin->data_length
1370 > dsc->file_length)) {
1371 return CDSC_ERROR;
1372 }
1373
1374 dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
1375
1376 header = 26 + entries * 12;
1377 /* move data_index to byte after AppleSingle/AppleDouble header */
1378 dsc->data_index -= dsc->line_length - header;
1379 /* we haven't read a line of PostScript code yet */
1380 dsc->line_count = 0;
1381 /* skip from current position to start of PostScript section */
1382 dsc->skip_bytes = dsc->macbin->data_begin - header;
1383
1384 dsc->preview = CDSC_PICT;
1385
1386 return CDSC_OK;
1387 }
1388
1389 static int
dsc_parse_pages(CDSC * dsc)1390 dsc_parse_pages(CDSC *dsc)
1391 {
1392 int ip, io;
1393 unsigned int i;
1394 char *p;
1395 int n;
1396 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
1397 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1398 dsc->line_length);
1399 switch (rc) {
1400 case CDSC_RESPONSE_OK:
1401 case CDSC_RESPONSE_CANCEL:
1402 return CDSC_OK; /* ignore duplicate comments in header */
1403 case CDSC_RESPONSE_IGNORE_ALL:
1404 return CDSC_NOTDSC;
1405 }
1406 }
1407 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
1408 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1409 dsc->line_length);
1410 switch (rc) {
1411 case CDSC_RESPONSE_OK:
1412 case CDSC_RESPONSE_CANCEL:
1413 break; /* use duplicate comments in header */
1414 case CDSC_RESPONSE_IGNORE_ALL:
1415 return CDSC_NOTDSC;
1416 }
1417 }
1418
1419 n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
1420 while (IS_WHITE(dsc->line[n]))
1421 n++;
1422 p = dsc->line + n;
1423 if (COMPARE(p, "atend")) {
1424 if (dsc->scan_section != scan_comments)
1425 dsc_unknown(dsc);
1426 else {
1427 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1428 dsc->line, dsc->line_length);
1429 switch (rc) {
1430 case CDSC_RESPONSE_OK:
1431 /* assume (atend) */
1432 /* we should mark it as deferred */
1433 break;
1434 case CDSC_RESPONSE_CANCEL:
1435 /* ignore it */
1436 break;
1437 case CDSC_RESPONSE_IGNORE_ALL:
1438 return CDSC_NOTDSC;
1439 }
1440 }
1441 }
1442 else if (COMPARE(p, "(atend)")) {
1443 if (dsc->scan_section != scan_comments)
1444 dsc_unknown(dsc);
1445 /* do nothing */
1446 /* we should mark it as deferred */
1447 }
1448 else {
1449 ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1450 if (i) {
1451 n+=i;
1452 dsc->page_pages = ip;
1453 io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1454 if (i) {
1455 /* DSC 2 uses extra integer to indicate page order */
1456 /* DSC 3 uses %%PageOrder: */
1457 if (dsc->page_order == CDSC_ORDER_UNKNOWN)
1458 switch (io) {
1459 case -1:
1460 dsc->page_order = CDSC_DESCEND;
1461 break;
1462 case 0:
1463 dsc->page_order = CDSC_SPECIAL;
1464 break;
1465 case 1:
1466 dsc->page_order = CDSC_ASCEND;
1467 break;
1468 }
1469 }
1470 }
1471 else {
1472 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
1473 dsc->line_length);
1474 switch (rc) {
1475 case CDSC_RESPONSE_OK:
1476 case CDSC_RESPONSE_CANCEL:
1477 /* ignore it */
1478 break;
1479 case CDSC_RESPONSE_IGNORE_ALL:
1480 return CDSC_NOTDSC;
1481 }
1482 }
1483 }
1484 return CDSC_OK;
1485 }
1486
1487 static int
dsc_parse_bounding_box(CDSC * dsc,CDSCBBOX ** pbbox,int offset)1488 dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
1489 {
1490 unsigned int i, n;
1491 int llx, lly, urx, ury;
1492 float fllx, flly, furx, fury;
1493 char *p;
1494 /* Process first %%BoundingBox: in comments, and last in trailer */
1495 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1496 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1497 dsc->line_length);
1498 switch (rc) {
1499 case CDSC_RESPONSE_OK:
1500 case CDSC_RESPONSE_CANCEL:
1501 return CDSC_OK; /* ignore duplicate comments in header */
1502 case CDSC_RESPONSE_IGNORE_ALL:
1503 return CDSC_NOTDSC;
1504 }
1505 }
1506 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1507 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1508 dsc->line_length);
1509 switch (rc) {
1510 case CDSC_RESPONSE_OK:
1511 case CDSC_RESPONSE_CANCEL:
1512 return CDSC_OK; /* ignore duplicate comments in header */
1513 case CDSC_RESPONSE_IGNORE_ALL:
1514 return CDSC_NOTDSC;
1515 }
1516 }
1517 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1518 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1519 dsc->line_length);
1520 switch (rc) {
1521 case CDSC_RESPONSE_OK:
1522 case CDSC_RESPONSE_CANCEL:
1523 break; /* use duplicate comments in trailer */
1524 case CDSC_RESPONSE_IGNORE_ALL:
1525 return CDSC_NOTDSC;
1526 }
1527 }
1528 if (*pbbox != NULL) {
1529 dsc_memfree(dsc, *pbbox);
1530 *pbbox = NULL;
1531 }
1532
1533 /* should only process first %%BoundingBox: */
1534
1535 while (IS_WHITE(dsc->line[offset]))
1536 offset++;
1537 p = dsc->line + offset;
1538
1539 if (COMPARE(p, "atend")) {
1540 if (dsc->scan_section == scan_trailer)
1541 dsc_unknown(dsc);
1542 else {
1543 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1544 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 }
1558 else if (COMPARE(p, "(atend)")) {
1559 if (dsc->scan_section == scan_trailer)
1560 dsc_unknown(dsc);
1561 /* do nothing */
1562 /* we should mark it as deferred */
1563 }
1564 else {
1565 /* llx = */ lly = urx = ury = 0;
1566 n = offset;
1567 llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1568 n += i;
1569 if (i)
1570 lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1571 n += i;
1572 if (i)
1573 urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1574 n += i;
1575 if (i)
1576 ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1577 if (i) {
1578 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1579 if (*pbbox == NULL)
1580 return CDSC_ERROR; /* no memory */
1581 (*pbbox)->llx = llx;
1582 (*pbbox)->lly = lly;
1583 (*pbbox)->urx = urx;
1584 (*pbbox)->ury = ury;
1585 }
1586 else {
1587 int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
1588 dsc->line_length);
1589 switch (rc) {
1590 case CDSC_RESPONSE_OK:
1591 /* fllx = */ flly = furx = fury = 0.0;
1592 n = offset;
1593 n += i;
1594 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1595 n += i;
1596 if (i)
1597 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1598 n += i;
1599 if (i)
1600 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1601 n += i;
1602 if (i)
1603 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1604 if (i) {
1605 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1606 if (*pbbox == NULL)
1607 return CDSC_ERROR; /* no memory */
1608 (*pbbox)->llx = (int)fllx;
1609 (*pbbox)->lly = (int)flly;
1610 (*pbbox)->urx = (int)(furx+0.999);
1611 (*pbbox)->ury = (int)(fury+0.999);
1612 }
1613 return CDSC_OK;
1614 case CDSC_RESPONSE_CANCEL:
1615 return CDSC_OK;
1616 case CDSC_RESPONSE_IGNORE_ALL:
1617 return CDSC_NOTDSC;
1618 }
1619 }
1620 }
1621 return CDSC_OK;
1622 }
1623
1624 static int
dsc_parse_float_bounding_box(CDSC * dsc,CDSCFBBOX ** pbbox,int offset)1625 dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
1626 {
1627 unsigned int i, n;
1628 float fllx, flly, furx, fury;
1629 char *p;
1630 /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1631 * and last in trailer.
1632 */
1633 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1634 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1635 dsc->line_length);
1636 switch (rc) {
1637 case CDSC_RESPONSE_OK:
1638 case CDSC_RESPONSE_CANCEL:
1639 return CDSC_OK; /* ignore duplicate comments in header */
1640 case CDSC_RESPONSE_IGNORE_ALL:
1641 return CDSC_NOTDSC;
1642 }
1643 }
1644 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1645 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1646 dsc->line_length);
1647 switch (rc) {
1648 case CDSC_RESPONSE_OK:
1649 case CDSC_RESPONSE_CANCEL:
1650 return CDSC_OK; /* ignore duplicate comments in header */
1651 case CDSC_RESPONSE_IGNORE_ALL:
1652 return CDSC_NOTDSC;
1653 }
1654 }
1655 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1656 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1657 dsc->line_length);
1658 switch (rc) {
1659 case CDSC_RESPONSE_OK:
1660 case CDSC_RESPONSE_CANCEL:
1661 break; /* use duplicate comments in trailer */
1662 case CDSC_RESPONSE_IGNORE_ALL:
1663 return CDSC_NOTDSC;
1664 }
1665 }
1666 if (*pbbox != NULL) {
1667 dsc_memfree(dsc, *pbbox);
1668 *pbbox = NULL;
1669 }
1670
1671 /* should only process first %%BoundingBox: */
1672
1673 while (IS_WHITE(dsc->line[offset]))
1674 offset++;
1675 p = dsc->line + offset;
1676
1677 if (COMPARE(p, "atend")) {
1678 if (dsc->scan_section == scan_trailer)
1679 dsc_unknown(dsc);
1680 else {
1681 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1682 dsc->line_length);
1683 switch (rc) {
1684 case CDSC_RESPONSE_OK:
1685 /* assume (atend) */
1686 /* we should mark it as deferred */
1687 break;
1688 case CDSC_RESPONSE_CANCEL:
1689 /* ignore it */
1690 break;
1691 case CDSC_RESPONSE_IGNORE_ALL:
1692 return CDSC_NOTDSC;
1693 }
1694 }
1695 }
1696 else if (COMPARE(p, "(atend)")) {
1697 if (dsc->scan_section == scan_trailer)
1698 dsc_unknown(dsc);
1699 /* do nothing */
1700 /* we should mark it as deferred */
1701 }
1702 else {
1703 /* fllx = */ flly = furx = fury = 0.0;
1704 n = offset;
1705 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1706 n += i;
1707 if (i)
1708 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1709 n += i;
1710 if (i)
1711 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1712 n += i;
1713 if (i)
1714 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1715 if (i) {
1716 *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
1717 if (*pbbox == NULL)
1718 return CDSC_ERROR; /* no memory */
1719 (*pbbox)->fllx = fllx;
1720 (*pbbox)->flly = flly;
1721 (*pbbox)->furx = furx;
1722 (*pbbox)->fury = fury;
1723 }
1724 }
1725 return CDSC_OK;
1726 }
1727
1728 static int
dsc_parse_orientation(CDSC * dsc,unsigned int * porientation,int offset)1729 dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
1730 {
1731 char *p;
1732 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1733 (dsc->scan_section == scan_comments)) {
1734 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1735 dsc->line_length);
1736 switch (rc) {
1737 case CDSC_RESPONSE_OK:
1738 case CDSC_RESPONSE_CANCEL:
1739 return CDSC_OK; /* ignore duplicate comments in header */
1740 case CDSC_RESPONSE_IGNORE_ALL:
1741 return CDSC_NOTDSC;
1742 }
1743 }
1744 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1745 (dsc->scan_section == scan_trailer)) {
1746 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1747 dsc->line_length);
1748 switch (rc) {
1749 case CDSC_RESPONSE_OK:
1750 case CDSC_RESPONSE_CANCEL:
1751 break; /* use duplicate comments in header; */
1752 case CDSC_RESPONSE_IGNORE_ALL:
1753 return CDSC_NOTDSC;
1754 }
1755 }
1756 p = dsc->line + offset;
1757 while (IS_WHITE(*p))
1758 p++;
1759 if (COMPARE(p, "atend")) {
1760 if (dsc->scan_section == scan_trailer)
1761 dsc_unknown(dsc);
1762 else {
1763 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1764 dsc->line, dsc->line_length);
1765 switch (rc) {
1766 case CDSC_RESPONSE_OK:
1767 /* assume (atend) */
1768 /* we should mark it as deferred */
1769 break;
1770 case CDSC_RESPONSE_CANCEL:
1771 /* ignore it */
1772 break;
1773 case CDSC_RESPONSE_IGNORE_ALL:
1774 return CDSC_NOTDSC;
1775 }
1776 }
1777 }
1778 else if (COMPARE(p, "(atend)")) {
1779 if (dsc->scan_section == scan_trailer)
1780 dsc_unknown(dsc);
1781 /* do nothing */
1782 /* we should mark it as deferred */
1783 }
1784 else if (COMPARE(p, "Portrait")) {
1785 *porientation = CDSC_PORTRAIT;
1786 }
1787 else if (COMPARE(p, "Landscape")) {
1788 *porientation = CDSC_LANDSCAPE;
1789 }
1790 else {
1791 dsc_unknown(dsc);
1792 }
1793 return CDSC_OK;
1794 }
1795
1796 static int
dsc_parse_order(CDSC * dsc)1797 dsc_parse_order(CDSC *dsc)
1798 {
1799 char *p;
1800 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1801 (dsc->scan_section == scan_comments)) {
1802 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1803 dsc->line_length);
1804 switch (rc) {
1805 case CDSC_RESPONSE_OK:
1806 case CDSC_RESPONSE_CANCEL:
1807 return CDSC_OK; /* ignore duplicate comments in header */
1808 case CDSC_RESPONSE_IGNORE_ALL:
1809 return CDSC_NOTDSC;
1810 }
1811 }
1812 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1813 (dsc->scan_section == scan_trailer)) {
1814 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1815 dsc->line_length);
1816 switch (rc) {
1817 case CDSC_RESPONSE_OK:
1818 case CDSC_RESPONSE_CANCEL:
1819 break; /* use duplicate comments in trailer */
1820 case CDSC_RESPONSE_IGNORE_ALL:
1821 return CDSC_NOTDSC;
1822 }
1823 }
1824
1825 p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13);
1826 while (IS_WHITE(*p))
1827 p++;
1828 if (COMPARE(p, "atend")) {
1829 if (dsc->scan_section == scan_trailer)
1830 dsc_unknown(dsc);
1831 else {
1832 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1833 dsc->line_length);
1834 switch (rc) {
1835 case CDSC_RESPONSE_OK:
1836 /* assume (atend) */
1837 /* we should mark it as deferred */
1838 break;
1839 case CDSC_RESPONSE_CANCEL:
1840 /* ignore it */
1841 break;
1842 case CDSC_RESPONSE_IGNORE_ALL:
1843 return CDSC_NOTDSC;
1844 }
1845 }
1846 }
1847 else if (COMPARE(p, "(atend)")) {
1848 if (dsc->scan_section == scan_trailer)
1849 dsc_unknown(dsc);
1850 /* do nothing */
1851 /* we should mark it as deferred */
1852 }
1853 else if (COMPARE(p, "Ascend")) {
1854 dsc->page_order = CDSC_ASCEND;
1855 }
1856 else if (COMPARE(p, "Descend")) {
1857 dsc->page_order = CDSC_DESCEND;
1858 }
1859 else if (COMPARE(p, "Special")) {
1860 dsc->page_order = CDSC_SPECIAL;
1861 }
1862 else {
1863 dsc_unknown(dsc);
1864 }
1865 return CDSC_OK;
1866 }
1867
1868 static int
dsc_parse_media(CDSC * dsc,const CDSCMEDIA ** page_media)1869 dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media)
1870 {
1871 char media_name[MAXSTR];
1872 int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */
1873 unsigned int i;
1874
1875 if (dsc_copy_string(media_name, sizeof(media_name)-1,
1876 dsc->line+n, dsc->line_length-n, NULL)) {
1877 for (i=0; i<dsc->media_count; i++) {
1878 if (dsc->media[i]->name &&
1879 (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) {
1880 *page_media = dsc->media[i];
1881 return CDSC_OK;
1882 }
1883 }
1884 }
1885 dsc_unknown(dsc);
1886
1887 return CDSC_OK;
1888 }
1889
1890 static int
dsc_parse_document_media(CDSC * dsc)1891 dsc_parse_document_media(CDSC *dsc)
1892 {
1893 unsigned int i, n;
1894 CDSCMEDIA lmedia;
1895 GSBOOL blank_line;
1896
1897 if (IS_DSC(dsc->line, "%%DocumentMedia:"))
1898 n = 16;
1899 else if (IS_DSC(dsc->line, "%%+"))
1900 n = 3;
1901 else
1902 return CDSC_ERROR; /* error */
1903
1904 /* check for blank remainder of line */
1905 blank_line = TRUE;
1906 for (i=n; i<dsc->line_length; i++) {
1907 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
1908 blank_line = FALSE;
1909 break;
1910 }
1911 }
1912
1913 if (!blank_line) {
1914 char name[MAXSTR];
1915 char colour[MAXSTR];
1916 char type[MAXSTR];
1917 lmedia.name = lmedia.colour = lmedia.type = (char *)NULL;
1918 lmedia.width = lmedia.height = lmedia.weight = 0;
1919 lmedia.mediabox = (CDSCBBOX *)NULL;
1920 lmedia.name = dsc_copy_string(name, sizeof(name),
1921 dsc->line+n, dsc->line_length-n, &i);
1922 n+=i;
1923 if (i)
1924 lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1925 n+=i;
1926 if (i)
1927 lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1928 n+=i;
1929 if (i)
1930 lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1931 n+=i;
1932 if (i)
1933 lmedia.colour = dsc_copy_string(colour, sizeof(colour),
1934 dsc->line+n, dsc->line_length-n, &i);
1935 n+=i;
1936 if (i)
1937 lmedia.type = dsc_copy_string(type, sizeof(type),
1938 dsc->line+n, dsc->line_length-n, &i);
1939
1940 if (i==0)
1941 dsc_unknown(dsc); /* we didn't get all fields */
1942 else {
1943 if (dsc_add_media(dsc, &lmedia))
1944 return CDSC_ERROR; /* out of memory */
1945 }
1946 }
1947 return CDSC_OK;
1948 }
1949
1950 /* viewing orientation is believed to be the first four elements of
1951 * a CTM matrix
1952 */
1953 static int
dsc_parse_viewing_orientation(CDSC * dsc,CDSCCTM ** pctm)1954 dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm)
1955 {
1956 CDSCCTM ctm;
1957 unsigned int i, n;
1958
1959 if (*pctm != NULL) {
1960 dsc_memfree(dsc, *pctm);
1961 *pctm = NULL;
1962 }
1963
1964 n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
1965 while (IS_WHITE(dsc->line[n]))
1966 n++;
1967
1968 /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0;
1969 ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1970 n += i;
1971 if (i)
1972 ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1973 n += i;
1974 if (i)
1975 ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1976 n += i;
1977 if (i)
1978 ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1979 if (i==0) {
1980 dsc_unknown(dsc); /* we didn't get all fields */
1981 }
1982 else {
1983 *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM));
1984 if (*pctm == NULL)
1985 return CDSC_ERROR; /* no memory */
1986 **pctm = ctm;
1987 }
1988 return CDSC_OK;
1989 }
1990
1991 /* This is called before dsc_read_line(), since we may
1992 * need to skip a binary header which contains a new line
1993 * character
1994 */
1995 static int
dsc_scan_type(CDSC * dsc)1996 dsc_scan_type(CDSC *dsc)
1997 {
1998 unsigned char *p;
1999 unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
2000 int length = dsc->data_length - dsc->data_index;
2001
2002 /* Types that should be known:
2003 * DSC
2004 * EPSF
2005 * PJL + any of above
2006 * ^D + any of above
2007 * DOS EPS
2008 * PDF
2009 * non-DSC
2010 */
2011
2012 /* First process any non PostScript headers */
2013 /* At this stage we do not have a complete line */
2014
2015 if (length == 0)
2016 return CDSC_NEEDMORE;
2017
2018 /* If we have already found a DOS EPS header, */
2019 /* ignore all until the PostScript section */
2020 if (dsc->skip_bytes) {
2021 int cnt = min(dsc->skip_bytes,
2022 (int)(dsc->data_length - dsc->data_index));
2023 dsc->skip_bytes -= cnt;
2024 dsc->data_index += cnt;
2025 length -= cnt;
2026 line += cnt;
2027 if (dsc->skip_bytes != 0)
2028 return CDSC_NEEDMORE;
2029 }
2030
2031 if (dsc->skip_pjl) {
2032 /* skip until first PostScript comment */
2033 while (length >= 2) {
2034 while (length && !IS_EOL(line[0])) {
2035 /* skip until EOL character */
2036 line++;
2037 dsc->data_index++;
2038 length--;
2039 }
2040 while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) {
2041 /* skip until EOL followed by non-EOL */
2042 line++;
2043 dsc->data_index++;
2044 length--;
2045 }
2046 if (length < 2)
2047 return CDSC_NEEDMORE;
2048
2049 if (IS_EOL(line[0]) && line[1]=='%') {
2050 line++;
2051 dsc->data_index++;
2052 length--;
2053 dsc->skip_pjl = FALSE;
2054 break;
2055 }
2056 else {
2057 line++;
2058 dsc->data_index++;
2059 length--;
2060 }
2061 }
2062 if (dsc->skip_pjl)
2063 return CDSC_NEEDMORE;
2064 }
2065
2066 if (length == 0)
2067 return CDSC_NEEDMORE;
2068
2069 if (line[0] == '\004') {
2070 line++;
2071 dsc->data_index++;
2072 length--;
2073 dsc->ctrld = TRUE;
2074 }
2075
2076 if (line[0] == '\033') {
2077 /* possibly PJL */
2078 if (length < 9)
2079 return CDSC_NEEDMORE;
2080 if (COMPARE(line, "\033%-12345X")) {
2081 dsc->skip_pjl = TRUE; /* skip until first PostScript comment */
2082 dsc->pjl = TRUE;
2083 dsc->data_index += 9;
2084 return dsc_scan_type(dsc);
2085 }
2086 }
2087
2088 if ((line[0]==0x0) && (length < 2))
2089 return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2090 if ((line[0]==0x0) && (line[1] >= 1) && (line[1] <= 63) && (length < 128))
2091 return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2092 if ((line[0]==0x0) && (line[1] == 0x5) && (length < 4))
2093 return CDSC_NEEDMORE; /* Could be Mac AppleSingle/AppleDouble */
2094 if ((line[0]==0xc5) && (length < 4))
2095 return CDSC_NEEDMORE; /* Could be DOS EPS */
2096
2097 if ((line[0]==0xc5) && (line[1]==0xd0) &&
2098 (line[2]==0xd3) && (line[3]==0xc6) ) {
2099 /* id is "EPSF" with bit 7 set */
2100 /* read DOS EPS header, then ignore all bytes until the PS section */
2101 if (length < 30)
2102 return CDSC_NEEDMORE;
2103 dsc->line = (char *)line;
2104 if (dsc_read_doseps(dsc))
2105 return CDSC_ERROR;
2106 }
2107 else if ((line[0]==0x0) && (line[1]==0x05) &&
2108 (line[2]==0x16) && ((line[3]==0x0) || (line[3] == 0x07))) {
2109 /* Mac AppleSingle or AppleDouble */
2110 GSDWORD version;
2111 GSWORD entries;
2112 if (length < 26)
2113 return CDSC_NEEDMORE;
2114 version = dsc_get_bigendian_dword(line+4);
2115 entries = dsc_get_bigendian_word(line+24);
2116 if ((version == 0x00010000) || (version == 0x00020000)) {
2117 if (length < (int)(26 + entries * 12))
2118 return CDSC_NEEDMORE;
2119 dsc->line = (char *)line;
2120 if (dsc_read_applesingle(dsc))
2121 return CDSC_ERROR;
2122 }
2123 }
2124 else if ((line[0]==0x0) &&
2125 (line[1] >= 1) && (line[1] <= 63) &&
2126 (line[74]==0x0) &&
2127 (line[65]=='E') && (line[66]=='P') &&
2128 (line[67]=='S') && (line[68]=='F')) {
2129 /* Mac Binary EPSF */
2130 dsc->line = (char *)line;
2131 if (dsc_read_macbin(dsc))
2132 return CDSC_ERROR;
2133 }
2134 else {
2135 if (length < 2)
2136 return CDSC_NEEDMORE;
2137 if ((line[0] == '%') && (line[1] == 'P')) {
2138 if (length < 5)
2139 return CDSC_NEEDMORE;
2140 if (COMPARE(line, "%PDF-")) {
2141 dsc->pdf = TRUE;
2142 dsc->scan_section = scan_comments;
2143 return CDSC_OK;
2144 }
2145 }
2146 }
2147
2148 /* Finally process PostScript headers */
2149
2150 if (dsc_read_line(dsc) <= 0)
2151 return CDSC_NEEDMORE;
2152
2153 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
2154 if (COMPARE(dsc->line, "%!PS-Adobe")) {
2155 dsc->dsc = TRUE;
2156 dsc->begincomments = DSC_START(dsc);
2157 if (dsc->dsc_version == NULL)
2158 return CDSC_ERROR; /* no memory */
2159 p = (unsigned char *)dsc->line + 14;
2160 while (IS_WHITE(*p))
2161 p++;
2162 if (COMPARE(p, "EPSF-"))
2163 dsc->epsf = TRUE;
2164 dsc->scan_section = scan_comments;
2165 return CDSC_PSADOBE;
2166 }
2167 if (COMPARE(dsc->line, "%!")) {
2168 dsc->scan_section = scan_comments;
2169 return CDSC_NOTDSC;
2170 }
2171
2172 dsc->scan_section = scan_comments;
2173 return CDSC_NOTDSC; /* unrecognised */
2174 }
2175
2176 static int
dsc_scan_comments(CDSC * dsc)2177 dsc_scan_comments(CDSC *dsc)
2178 {
2179 /* Comments section ends at */
2180 /* %%EndComments */
2181 /* another section */
2182 /* line that does not start with %% */
2183 /* Save a few important lines */
2184
2185 char *line = dsc->line;
2186 GSBOOL continued = FALSE;
2187 dsc->id = CDSC_OK;
2188 if (IS_DSC(line, "%%EndComments")) {
2189 dsc->id = CDSC_ENDCOMMENTS;
2190 dsc->endcomments = DSC_END(dsc);
2191 dsc->scan_section = scan_pre_preview;
2192 return CDSC_OK;
2193 }
2194 else if (IS_DSC(line, "%%BeginComments")) {
2195 /* ignore because we are in this section */
2196 dsc->id = CDSC_BEGINCOMMENTS;
2197 }
2198 else if (dsc_is_section(line)) {
2199 dsc->endcomments = DSC_START(dsc);
2200 dsc->scan_section = scan_pre_preview;
2201 return CDSC_PROPAGATE;
2202 }
2203 else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) {
2204 dsc->endcomments = DSC_START(dsc);
2205 dsc->scan_section = scan_pre_preview;
2206 return CDSC_PROPAGATE;
2207 }
2208 else if (line[0] != '%') {
2209 dsc->id = CDSC_OK;
2210 dsc->endcomments = DSC_START(dsc);
2211 dsc->scan_section = scan_pre_preview;
2212 return CDSC_PROPAGATE;
2213 }
2214 else if (IS_DSC(line, "%%Begin")) {
2215 dsc->endcomments = DSC_START(dsc);
2216 dsc->scan_section = scan_pre_preview;
2217 return CDSC_PROPAGATE;
2218 }
2219
2220 /* Handle continuation lines.
2221 * To simply processing, we assume that continuation lines
2222 * will only occur if repeat parameters are allowed and that
2223 * a complete set of these parameters appears on each line.
2224 * This is more restrictive than the DSC specification, but
2225 * is valid for the DSC comments understood by this parser
2226 * for all documents that we have seen.
2227 */
2228 if (IS_DSC(line, "%%+")) {
2229 line = dsc->last_line;
2230 continued = TRUE;
2231 }
2232 else
2233 dsc_save_line(dsc);
2234
2235 if (IS_DSC(line, "%%Pages:")) {
2236 dsc->id = CDSC_PAGES;
2237 if (dsc_parse_pages(dsc) != 0)
2238 return CDSC_ERROR;
2239 }
2240 else if (IS_DSC(line, "%%Creator:")) {
2241 unsigned int n = continued ? 3 : 10;
2242 dsc->id = CDSC_CREATOR;
2243 dsc->dsc_creator = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2244 if (dsc->dsc_creator==NULL)
2245 return CDSC_ERROR;
2246 }
2247 else if (IS_DSC(line, "%%CreationDate:")) {
2248 unsigned int n = continued ? 3 : 15;
2249 dsc->id = CDSC_CREATIONDATE;
2250 dsc->dsc_date = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2251 if (dsc->dsc_date==NULL)
2252 return CDSC_ERROR;
2253 }
2254 else if (IS_DSC(line, "%%Title:")) {
2255 unsigned int n = continued ? 3 : 8;
2256 dsc->id = CDSC_TITLE;
2257 dsc->dsc_title = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2258 if (dsc->dsc_title==NULL)
2259 return CDSC_ERROR;
2260 }
2261 else if (IS_DSC(line, "%%For:")) {
2262 unsigned int n = continued ? 3 : 6;
2263 dsc->id = CDSC_FOR;
2264 dsc->dsc_for = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2265 if (dsc->dsc_for==NULL)
2266 return CDSC_ERROR;
2267 }
2268 else if (IS_DSC(line, "%%LanguageLevel:")) {
2269 unsigned int n = continued ? 3 : 16;
2270 unsigned int i;
2271 int ll;
2272 dsc->id = CDSC_LANGUAGELEVEL;
2273 ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
2274 if (i) {
2275 if ( (ll==1) || (ll==2) || (ll==3) )
2276 dsc->language_level = ll;
2277 else {
2278 dsc_unknown(dsc);
2279 }
2280 }
2281 else
2282 dsc_unknown(dsc);
2283 }
2284 else if (IS_DSC(line, "%%BoundingBox:")) {
2285 dsc->id = CDSC_BOUNDINGBOX;
2286 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
2287 return CDSC_ERROR;
2288 }
2289 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
2290 dsc->id = CDSC_HIRESBOUNDINGBOX;
2291 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
2292 continued ? 3 : 19))
2293 return CDSC_ERROR;
2294 }
2295 else if (IS_DSC(line, "%%CropBox:")) {
2296 dsc->id = CDSC_CROPBOX;
2297 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
2298 continued ? 3 : 10))
2299 return CDSC_ERROR;
2300 }
2301 else if (IS_DSC(line, "%%Orientation:")) {
2302 dsc->id = CDSC_ORIENTATION;
2303 if (dsc_parse_orientation(dsc, &(dsc->page_orientation),
2304 continued ? 3 : 14))
2305 return CDSC_ERROR;
2306 }
2307 else if (IS_DSC(line, "%%PageOrder:")) {
2308 dsc->id = CDSC_PAGEORDER;
2309 if (dsc_parse_order(dsc))
2310 return CDSC_ERROR;
2311 }
2312 else if (IS_DSC(line, "%%DocumentMedia:")) {
2313 dsc->id = CDSC_DOCUMENTMEDIA;
2314 if (dsc_parse_document_media(dsc))
2315 return CDSC_ERROR;
2316 }
2317 else if (IS_DSC(line, "%%DocumentPaperSizes:")) {
2318 /* DSC 2.1 */
2319 unsigned int n = continued ? 3 : 21;
2320 unsigned int count = 0;
2321 unsigned int i = 1;
2322 char name[MAXSTR];
2323 char *p;
2324 dsc->id = CDSC_DOCUMENTPAPERSIZES;
2325 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2326 p = dsc_copy_string(name, sizeof(name)-1,
2327 dsc->line+n, dsc->line_length-n, &i);
2328 if (i && p) {
2329 const CDSCMEDIA *m = dsc_known_media;
2330 if (count >= dsc->media_count) {
2331 /* set some default values */
2332 CDSCMEDIA lmedia;
2333 lmedia.name = p;
2334 lmedia.width = 595.0;
2335 lmedia.height = 842.0;
2336 lmedia.weight = 80.0;
2337 lmedia.colour = NULL;
2338 lmedia.type = NULL;
2339 lmedia.mediabox = NULL;
2340 if (dsc_add_media(dsc, &lmedia))
2341 return CDSC_ERROR;
2342 }
2343 else
2344 dsc->media[count]->name =
2345 dsc_alloc_string(dsc, p, (int)strlen(p));
2346 /* find in list of known media */
2347 while (m && m->name) {
2348 if (dsc_stricmp(p, m->name)==0) {
2349 dsc->media[count]->width = m->width;
2350 dsc->media[count]->height = m->height;
2351 break;
2352 }
2353 m++;
2354 }
2355 }
2356 n+=i;
2357 count++;
2358 }
2359 }
2360 else if (IS_DSC(line, "%%DocumentPaperForms:")) {
2361 /* DSC 2.1 */
2362 unsigned int n = continued ? 3 : 21;
2363 unsigned int count = 0;
2364 unsigned int i = 1;
2365 char type[MAXSTR];
2366 char *p;
2367 dsc->id = CDSC_DOCUMENTPAPERFORMS;
2368 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2369 p = dsc_copy_string(type, sizeof(type)-1,
2370 dsc->line+n, dsc->line_length-n, &i);
2371 if (i && p) {
2372 if (count >= dsc->media_count) {
2373 /* set some default values */
2374 CDSCMEDIA lmedia;
2375 lmedia.name = NULL;
2376 lmedia.width = 595.0;
2377 lmedia.height = 842.0;
2378 lmedia.weight = 80.0;
2379 lmedia.colour = NULL;
2380 lmedia.type = p;
2381 lmedia.mediabox = NULL;
2382 if (dsc_add_media(dsc, &lmedia))
2383 return CDSC_ERROR;
2384 }
2385 else
2386 dsc->media[count]->type =
2387 dsc_alloc_string(dsc, p, (int)strlen(p));
2388 }
2389 n+=i;
2390 count++;
2391 }
2392 }
2393 else if (IS_DSC(line, "%%DocumentPaperColors:")) {
2394 /* DSC 2.1 */
2395 unsigned int n = continued ? 3 : 22;
2396 unsigned int count = 0;
2397 unsigned int i = 1;
2398 char colour[MAXSTR];
2399 char *p;
2400 dsc->id = CDSC_DOCUMENTPAPERCOLORS;
2401 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2402 p = dsc_copy_string(colour, sizeof(colour)-1,
2403 dsc->line+n, dsc->line_length-n, &i);
2404 if (i && p) {
2405 if (count >= dsc->media_count) {
2406 /* set some default values */
2407 CDSCMEDIA lmedia;
2408 lmedia.name = NULL;
2409 lmedia.width = 595.0;
2410 lmedia.height = 842.0;
2411 lmedia.weight = 80.0;
2412 lmedia.colour = p;
2413 lmedia.type = NULL;
2414 lmedia.mediabox = NULL;
2415 if (dsc_add_media(dsc, &lmedia))
2416 return CDSC_ERROR;
2417 }
2418 else
2419 dsc->media[count]->colour =
2420 dsc_alloc_string(dsc, p, (int)strlen(p));
2421 }
2422 n+=i;
2423 count++;
2424 }
2425 }
2426 else if (IS_DSC(line, "%%DocumentPaperWeights:")) {
2427 /* DSC 2.1 */
2428 unsigned int n = continued ? 3 : 23;
2429 unsigned int count = 0;
2430 unsigned int i = 1;
2431 float w;
2432 dsc->id = CDSC_DOCUMENTPAPERWEIGHTS;
2433 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2434 w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2435 if (i) {
2436 if (count >= dsc->media_count) {
2437 /* set some default values */
2438 CDSCMEDIA lmedia;
2439 lmedia.name = NULL;
2440 lmedia.width = 595.0;
2441 lmedia.height = 842.0;
2442 lmedia.weight = w;
2443 lmedia.colour = NULL;
2444 lmedia.type = NULL;
2445 lmedia.mediabox = NULL;
2446 if (dsc_add_media(dsc, &lmedia))
2447 return CDSC_ERROR;
2448 }
2449 else
2450 dsc->media[count]->weight = w;
2451 }
2452 n+=i;
2453 count++;
2454 }
2455 }
2456 else if (IS_DSC(line, "%%DocumentData:")) {
2457 unsigned int n = continued ? 3 : 15;
2458 char *p = dsc->line + n;
2459 while (IS_WHITE(*p))
2460 p++;
2461 dsc->id = CDSC_DOCUMENTDATA;
2462 if (COMPARE(p, "Clean7Bit"))
2463 dsc->document_data = CDSC_CLEAN7BIT;
2464 else if (COMPARE(p, "Clean8Bit"))
2465 dsc->document_data = CDSC_CLEAN8BIT;
2466 else if (COMPARE(p, "Binary"))
2467 dsc->document_data = CDSC_BINARY;
2468 else
2469 dsc_unknown(dsc);
2470 }
2471 else if (IS_DSC(line, "%%Requirements:")) {
2472 dsc->id = CDSC_REQUIREMENTS;
2473 /* ignore */
2474 }
2475 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
2476 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
2477 /* ignore */
2478 }
2479 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
2480 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
2481 /* ignore */
2482 }
2483 else if (IS_DSC(line, "%%PlateFile:")) {
2484 dsc->id = CDSC_PLATEFILE;
2485 if (dsc_parse_platefile(dsc) != CDSC_OK)
2486 dsc->id = CDSC_UNKNOWNDSC;
2487 }
2488 else if (IS_DSC(line, "%%CyanPlate:") ||
2489 IS_DSC(line, "%%MagentaPlate:") ||
2490 IS_DSC(line, "%%YellowPlate:") ||
2491 IS_DSC(line, "%%BlackPlate:")) {
2492 dsc->id = CDSC_PLATEFILE;
2493 if (dsc_parse_dcs1plate(dsc) != CDSC_OK)
2494 dsc->id = CDSC_UNKNOWNDSC;
2495 }
2496 else if (IS_DSC(line, "%%DocumentProcessColors:")) {
2497 dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
2498 if (dsc_parse_process_colours(dsc) != CDSC_OK)
2499 dsc->id = CDSC_UNKNOWNDSC;
2500 }
2501 else if (IS_DSC(line, "%%DocumentCustomColors:")) {
2502 dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
2503 if (dsc_parse_custom_colours(dsc) != CDSC_OK)
2504 dsc->id = CDSC_UNKNOWNDSC;
2505 }
2506 else if (IS_DSC(line, "%%CMYKCustomColor:")) {
2507 dsc->id = CDSC_CMYKCUSTOMCOLOR;
2508 if (dsc_parse_cmyk_custom_colour(dsc) != CDSC_OK)
2509 dsc->id = CDSC_UNKNOWNDSC;
2510 }
2511 else if (IS_DSC(line, "%%RGBCustomColor:")) {
2512 dsc->id = CDSC_RGBCUSTOMCOLOR;
2513 if (dsc_parse_rgb_custom_colour(dsc) != CDSC_OK)
2514 dsc->id = CDSC_UNKNOWNDSC;
2515 }
2516 else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
2517 dsc->id = CDSC_OK;
2518 /* ignore */
2519 }
2520 else {
2521 dsc->id = CDSC_UNKNOWNDSC;
2522 dsc_unknown(dsc);
2523 }
2524
2525 dsc->endcomments = DSC_END(dsc);
2526 return CDSC_OK;
2527 }
2528
2529 static int
dsc_scan_preview(CDSC * dsc)2530 dsc_scan_preview(CDSC *dsc)
2531 {
2532 /* Preview section ends at */
2533 /* %%EndPreview */
2534 /* another section */
2535 /* Preview section must start with %%BeginPreview */
2536 char *line = dsc->line;
2537 dsc->id = CDSC_OK;
2538
2539 if (dsc->scan_section == scan_pre_preview) {
2540 if (IS_BLANK(line))
2541 return CDSC_OK; /* ignore blank lines before preview */
2542 else if (IS_DSC(line, "%%BeginPreview")) {
2543 dsc->id = CDSC_BEGINPREVIEW;
2544 dsc->beginpreview = DSC_START(dsc);
2545 dsc->endpreview = DSC_END(dsc);
2546 dsc->scan_section = scan_preview;
2547 /* Don't mark the preview as EPSI if a DOS EPS header is present */
2548 if (dsc->preview == CDSC_NOPREVIEW)
2549 dsc->preview = CDSC_EPSI;
2550 return CDSC_OK;
2551 }
2552 else {
2553 dsc->scan_section = scan_pre_defaults;
2554 return CDSC_PROPAGATE;
2555 }
2556 }
2557
2558 if (IS_DSC(line, "%%BeginPreview")) {
2559 /* ignore because we are in this section */
2560 }
2561 else if (dsc_is_section(line)) {
2562 dsc->endpreview = DSC_START(dsc);
2563 dsc->scan_section = scan_pre_defaults;
2564 return CDSC_PROPAGATE;
2565 }
2566 else if (IS_DSC(line, "%%EndPreview")) {
2567 dsc->id = CDSC_ENDPREVIEW;
2568 dsc->endpreview = DSC_END(dsc);
2569 dsc->scan_section = scan_pre_defaults;
2570 return CDSC_OK;
2571 }
2572 else if (line[0] == '%' && line[1] != '%') {
2573 /* Ordinary comments are OK */
2574 }
2575 else {
2576 dsc->id = CDSC_UNKNOWNDSC;
2577 /* DSC comments should not occur in preview */
2578 dsc_unknown(dsc);
2579 }
2580
2581 dsc->endpreview = DSC_END(dsc);
2582 return CDSC_OK;
2583 }
2584
2585 static int
dsc_scan_defaults(CDSC * dsc)2586 dsc_scan_defaults(CDSC *dsc)
2587 {
2588 /* Defaults section ends at */
2589 /* %%EndDefaults */
2590 /* another section */
2591 /* Defaults section must start with %%BeginDefaults */
2592 char *line = dsc->line;
2593 dsc->id = CDSC_OK;
2594
2595 if (dsc->scan_section == scan_pre_defaults) {
2596 if (IS_BLANK(line))
2597 return CDSC_OK; /* ignore blank lines before defaults */
2598 else if (IS_DSC(line, "%%BeginDefaults")) {
2599 dsc->id = CDSC_BEGINDEFAULTS;
2600 dsc->begindefaults = DSC_START(dsc);
2601 dsc->enddefaults = DSC_END(dsc);
2602 dsc->scan_section = scan_defaults;
2603 return CDSC_OK;
2604 }
2605 else {
2606 dsc->scan_section = scan_pre_prolog;
2607 return CDSC_PROPAGATE;
2608 }
2609 }
2610
2611 if (NOT_DSC_LINE(line)) {
2612 /* ignore */
2613 }
2614 else if (IS_DSC(line, "%%BeginPreview")) {
2615 /* ignore because we have already processed this section */
2616 }
2617 else if (IS_DSC(line, "%%BeginDefaults")) {
2618 /* ignore because we are in this section */
2619 }
2620 else if (dsc_is_section(line)) {
2621 dsc->enddefaults = DSC_START(dsc);
2622 dsc->scan_section = scan_pre_prolog;
2623 return CDSC_PROPAGATE;
2624 }
2625 else if (IS_DSC(line, "%%EndDefaults")) {
2626 dsc->id = CDSC_ENDDEFAULTS;
2627 dsc->enddefaults = DSC_END(dsc);
2628 dsc->scan_section = scan_pre_prolog;
2629 return CDSC_OK;
2630 }
2631 else if (IS_DSC(line, "%%PageMedia:")) {
2632 dsc->id = CDSC_PAGEMEDIA;
2633 dsc_parse_media(dsc, &dsc->page_media);
2634 }
2635 else if (IS_DSC(line, "%%PageOrientation:")) {
2636 dsc->id = CDSC_PAGEORIENTATION;
2637 /* This can override %%Orientation: */
2638 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18))
2639 return CDSC_ERROR;
2640 }
2641 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2642 dsc->id = CDSC_PAGEBOUNDINGBOX;
2643 if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18))
2644 return CDSC_ERROR;
2645 }
2646 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2647 dsc->id = CDSC_VIEWINGORIENTATION;
2648 if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation))
2649 return CDSC_ERROR;
2650 }
2651 else if (IS_DSC(line, "%%PageCropBox:")) {
2652 dsc->id = CDSC_PAGECROPBOX;
2653 if (dsc_parse_float_bounding_box(dsc, &dsc->crop_box, 14))
2654 return CDSC_ERROR;
2655 }
2656 else {
2657 dsc->id = CDSC_UNKNOWNDSC;
2658 /* All other DSC comments are unknown, but not an error */
2659 dsc_unknown(dsc);
2660 }
2661 dsc->enddefaults = DSC_END(dsc);
2662 return CDSC_OK;
2663 }
2664
2665 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
2666 * mismatch (default) */
2667 static int
dsc_check_match_prompt(CDSC * dsc,const char * str,int count)2668 dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
2669 {
2670 if (count != 0) {
2671 char buf[MAXSTR+MAXSTR];
2672
2673 memset(buf, 0x00, MAXSTR+MAXSTR);
2674 if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1))
2675 strncpy(buf, dsc->line, dsc->line_length);
2676
2677 gs_sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
2678 return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, (int)strlen(buf));
2679 }
2680 return CDSC_RESPONSE_CANCEL;
2681 }
2682
2683 static int
dsc_check_match_type(CDSC * dsc,const char * str,int count)2684 dsc_check_match_type(CDSC *dsc, const char *str, int count)
2685 {
2686 if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
2687 return CDSC_NOTDSC;
2688 return CDSC_OK;
2689 }
2690
2691 /* complain if Begin/End blocks didn't match */
2692 /* return non-zero if we should ignore all DSC */
2693 static int
dsc_check_match(CDSC * dsc)2694 dsc_check_match(CDSC *dsc)
2695 {
2696 int rc = 0;
2697 const char *font = "Font";
2698 const char *feature = "Feature";
2699 const char *resource = "Resource";
2700 const char *procset = "ProcSet";
2701
2702 if (!rc)
2703 rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
2704 if (!rc)
2705 rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
2706 if (!rc)
2707 rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
2708 if (!rc)
2709 rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
2710
2711 dsc->begin_font_count = 0;
2712 dsc->begin_feature_count = 0;
2713 dsc->begin_resource_count = 0;
2714 dsc->begin_procset_count = 0;
2715 return rc;
2716 }
2717
2718 static int
dsc_scan_prolog(CDSC * dsc)2719 dsc_scan_prolog(CDSC *dsc)
2720 {
2721 /* Prolog section ends at */
2722 /* %%EndProlog */
2723 /* another section */
2724 /* Prolog section may start with %%BeginProlog or non-dsc line */
2725 char *line = dsc->line;
2726 dsc->id = CDSC_OK;
2727
2728 if (dsc->scan_section == scan_pre_prolog) {
2729 if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
2730 dsc->scan_section = scan_pre_setup;
2731 return CDSC_PROPAGATE;
2732 }
2733 dsc->id = CDSC_BEGINPROLOG;
2734 dsc->beginprolog = DSC_START(dsc);
2735 dsc->endprolog = DSC_END(dsc);
2736 dsc->scan_section = scan_prolog;
2737 if (IS_DSC(line, "%%BeginProlog"))
2738 return CDSC_OK;
2739 }
2740
2741 if (NOT_DSC_LINE(line)) {
2742 /* ignore */
2743 }
2744 else if (IS_DSC(line, "%%BeginPreview")) {
2745 /* ignore because we have already processed this section */
2746 }
2747 else if (IS_DSC(line, "%%BeginDefaults")) {
2748 /* ignore because we have already processed this section */
2749 }
2750 else if (IS_DSC(line, "%%BeginProlog")) {
2751 /* ignore because we are in this section */
2752 }
2753 else if (dsc_is_section(line)) {
2754 dsc->endprolog = DSC_START(dsc);
2755 dsc->scan_section = scan_pre_setup;
2756 if (dsc_check_match(dsc))
2757 return CDSC_NOTDSC;
2758 return CDSC_PROPAGATE;
2759 }
2760 else if (IS_DSC(line, "%%EndProlog")) {
2761 dsc->id = CDSC_ENDPROLOG;
2762 dsc->endprolog = DSC_END(dsc);
2763 dsc->scan_section = scan_pre_setup;
2764 if (dsc_check_match(dsc))
2765 return CDSC_NOTDSC;
2766 return CDSC_OK;
2767 }
2768 else if (IS_DSC(line, "%%BeginFont:")) {
2769 dsc->id = CDSC_BEGINFONT;
2770 /* ignore Begin/EndFont, apart form making sure */
2771 /* that they are matched. */
2772 dsc->begin_font_count++;
2773 }
2774 else if (IS_DSC(line, "%%EndFont")) {
2775 dsc->id = CDSC_ENDFONT;
2776 dsc->begin_font_count--;
2777 }
2778 else if (IS_DSC(line, "%%BeginFeature:")) {
2779 dsc->id = CDSC_BEGINFEATURE;
2780 /* ignore Begin/EndFeature, apart form making sure */
2781 /* that they are matched. */
2782 dsc->begin_feature_count++;
2783 }
2784 else if (IS_DSC(line, "%%EndFeature")) {
2785 dsc->id = CDSC_ENDFEATURE;
2786 dsc->begin_feature_count--;
2787 }
2788 else if (IS_DSC(line, "%%BeginResource:")) {
2789 dsc->id = CDSC_BEGINRESOURCE;
2790 /* ignore Begin/EndResource, apart form making sure */
2791 /* that they are matched. */
2792 dsc->begin_resource_count++;
2793 }
2794 else if (IS_DSC(line, "%%EndResource")) {
2795 dsc->id = CDSC_ENDRESOURCE;
2796 dsc->begin_resource_count--;
2797 }
2798 else if (IS_DSC(line, "%%BeginProcSet:")) {
2799 dsc->id = CDSC_BEGINPROCSET;
2800 /* ignore Begin/EndProcSet, apart form making sure */
2801 /* that they are matched. */
2802 dsc->begin_procset_count++;
2803 }
2804 else if (IS_DSC(line, "%%EndProcSet")) {
2805 dsc->id = CDSC_ENDPROCSET;
2806 dsc->begin_procset_count--;
2807 }
2808 else {
2809 /* All other DSC comments are unknown, but not an error */
2810 dsc->id = CDSC_UNKNOWNDSC;
2811 dsc_unknown(dsc);
2812 }
2813
2814 dsc->endprolog = DSC_END(dsc);
2815 return CDSC_OK;
2816 }
2817
2818 static int
dsc_scan_setup(CDSC * dsc)2819 dsc_scan_setup(CDSC *dsc)
2820 {
2821 /* Setup section ends at */
2822 /* %%EndSetup */
2823 /* another section */
2824 /* Setup section must start with %%BeginSetup */
2825
2826 char *line = dsc->line;
2827 dsc->id = CDSC_OK;
2828
2829 if (dsc->scan_section == scan_pre_setup) {
2830 if (IS_BLANK(line))
2831 return CDSC_OK; /* ignore blank lines before setup */
2832 else if (IS_DSC(line, "%%BeginSetup")) {
2833 dsc->id = CDSC_BEGINSETUP;
2834 dsc->beginsetup = DSC_START(dsc);
2835 dsc->endsetup = DSC_END(dsc);
2836 dsc->scan_section = scan_setup;
2837 return CDSC_OK;
2838 }
2839 else {
2840 dsc->scan_section = scan_pre_pages;
2841 return CDSC_PROPAGATE;
2842 }
2843 }
2844
2845 if (NOT_DSC_LINE(line)) {
2846 /* ignore */
2847 }
2848 else if (IS_DSC(line, "%%BeginPreview")) {
2849 /* ignore because we have already processed this section */
2850 }
2851 else if (IS_DSC(line, "%%BeginDefaults")) {
2852 /* ignore because we have already processed this section */
2853 }
2854 else if (IS_DSC(line, "%%BeginProlog")) {
2855 /* ignore because we have already processed this section */
2856 }
2857 else if (IS_DSC(line, "%%BeginSetup")) {
2858 /* ignore because we are in this section */
2859 }
2860 else if (dsc_is_section(line)) {
2861 dsc->endsetup = DSC_START(dsc);
2862 dsc->scan_section = scan_pre_pages;
2863 if (dsc_check_match(dsc))
2864 return CDSC_NOTDSC;
2865 return CDSC_PROPAGATE;
2866 }
2867 else if (IS_DSC(line, "%%EndSetup")) {
2868 dsc->id = CDSC_ENDSETUP;
2869 dsc->endsetup = DSC_END(dsc);
2870 dsc->scan_section = scan_pre_pages;
2871 if (dsc_check_match(dsc))
2872 return CDSC_NOTDSC;
2873 return CDSC_OK;
2874 }
2875 else if (IS_DSC(line, "%%BeginFeature:")) {
2876 dsc->id = CDSC_BEGINFEATURE;
2877 /* ignore Begin/EndFeature, apart form making sure */
2878 /* that they are matched. */
2879 dsc->begin_feature_count++;
2880 }
2881 else if (IS_DSC(line, "%%EndFeature")) {
2882 dsc->id = CDSC_ENDFEATURE;
2883 dsc->begin_feature_count--;
2884 }
2885 else if (IS_DSC(line, "%%Feature:")) {
2886 dsc->id = CDSC_FEATURE;
2887 /* ignore */
2888 }
2889 else if (IS_DSC(line, "%%BeginResource:")) {
2890 dsc->id = CDSC_BEGINRESOURCE;
2891 /* ignore Begin/EndResource, apart form making sure */
2892 /* that they are matched. */
2893 dsc->begin_resource_count++;
2894 }
2895 else if (IS_DSC(line, "%%EndResource")) {
2896 dsc->id = CDSC_ENDRESOURCE;
2897 dsc->begin_resource_count--;
2898 }
2899 else if (IS_DSC(line, "%%PaperColor:")) {
2900 dsc->id = CDSC_PAPERCOLOR;
2901 /* ignore */
2902 }
2903 else if (IS_DSC(line, "%%PaperForm:")) {
2904 dsc->id = CDSC_PAPERFORM;
2905 /* ignore */
2906 }
2907 else if (IS_DSC(line, "%%PaperWeight:")) {
2908 dsc->id = CDSC_PAPERWEIGHT;
2909 /* ignore */
2910 }
2911 else if (IS_DSC(line, "%%PaperSize:")) {
2912 /* DSC 2.1 */
2913 GSBOOL found_media = FALSE;
2914 int i;
2915 int n = 12;
2916 char buf[MAXSTR];
2917 buf[0] = '\0';
2918 dsc->id = CDSC_PAPERSIZE;
2919 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n,
2920 NULL);
2921 for (i=0; i<(int)dsc->media_count; i++) {
2922 if (dsc->media[i] && dsc->media[i]->name &&
2923 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2924 dsc->page_media = dsc->media[i];
2925 found_media = TRUE;
2926 break;
2927 }
2928 }
2929 if (!found_media) {
2930 /* It didn't match %%DocumentPaperSizes: */
2931 /* Try our known media */
2932 const CDSCMEDIA *m = dsc_known_media;
2933 while (m->name) {
2934 if (dsc_stricmp(buf, m->name)==0) {
2935 dsc->page_media = m;
2936 break;
2937 }
2938 m++;
2939 }
2940 if (m->name == NULL)
2941 dsc_unknown(dsc);
2942 }
2943 }
2944 else {
2945 /* All other DSC comments are unknown, but not an error */
2946 dsc->id = CDSC_UNKNOWNDSC;
2947 dsc_unknown(dsc);
2948 }
2949
2950 dsc->endsetup = DSC_END(dsc);
2951 return CDSC_OK;
2952 }
2953
2954 static int
dsc_scan_page(CDSC * dsc)2955 dsc_scan_page(CDSC *dsc)
2956 {
2957 /* Page section ends at */
2958 /* %%Page */
2959 /* %%Trailer */
2960 /* %%EOF */
2961 char *line = dsc->line;
2962 dsc->id = CDSC_OK;
2963
2964 if (dsc->scan_section == scan_pre_pages) {
2965 if (IS_DSC(line, "%%Page:")) {
2966 dsc->scan_section = scan_pages;
2967 /* fall through */
2968 }
2969 else {
2970 /* %%Page: didn't follow %%EndSetup
2971 * Keep reading until reach %%Page or %%Trailer
2972 * and add it to previous section.
2973 */
2974 DSC_OFFSET *last;
2975 if (dsc->endsetup != 0)
2976 last = &dsc->endsetup;
2977 else if (dsc->endprolog != 0)
2978 last = &dsc->endprolog;
2979 else if (dsc->enddefaults != 0)
2980 last = &dsc->enddefaults;
2981 else if (dsc->endpreview != 0)
2982 last = &dsc->endpreview;
2983 else if (dsc->endcomments != 0)
2984 last = &dsc->endcomments;
2985 else
2986 last = &dsc->begincomments;
2987 *last = DSC_START(dsc);
2988 if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
2989 dsc->scan_section = scan_pre_trailer;
2990 return CDSC_PROPAGATE;
2991 }
2992 *last = DSC_END(dsc);
2993 return CDSC_OK;
2994 }
2995 }
2996
2997 if (NOT_DSC_LINE(line)) {
2998 /* ignore */
2999 }
3000 else if (IS_DSC(line, "%%Page:")) {
3001 int code;
3002 dsc->id = CDSC_PAGE;
3003 if (dsc->page_count) {
3004 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3005 if (dsc_check_match(dsc))
3006 return CDSC_NOTDSC;
3007 }
3008
3009 if ( (code = dsc_parse_page(dsc)) != CDSC_OK)
3010 return code;
3011 if (dsc->page_count == 0)
3012 dsc->scan_section = scan_pre_pages;
3013 }
3014 else if (IS_DSC(line, "%%BeginPreview")) {
3015 /* ignore because we have already processed this section */
3016 }
3017 else if (IS_DSC(line, "%%BeginDefaults")) {
3018 /* ignore because we have already processed this section */
3019 }
3020 else if (IS_DSC(line, "%%BeginProlog")) {
3021 /* ignore because we have already processed this section */
3022 }
3023 else if (IS_DSC(line, "%%BeginSetup")) {
3024 /* ignore because we have already processed this section */
3025 }
3026 else if (dsc_is_section(line)) {
3027 if (IS_DSC(line, "%%Trailer")) {
3028 if (dsc->page_count)
3029 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3030 if (dsc->file_length) {
3031 if ((!dsc->doseps_end &&
3032 ((DSC_END(dsc) + 32768) < dsc->file_length)) ||
3033 ((dsc->doseps_end) &&
3034 ((DSC_END(dsc) + 32768) < dsc->doseps_end))) {
3035 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER,
3036 dsc->line, dsc->line_length);
3037 switch (rc) {
3038 case CDSC_RESPONSE_OK:
3039 /* ignore early trailer */
3040 break;
3041 case CDSC_RESPONSE_CANCEL:
3042 /* this is the trailer */
3043 dsc->scan_section = scan_pre_trailer;
3044 if (dsc_check_match(dsc))
3045 return CDSC_NOTDSC;
3046 return CDSC_PROPAGATE;
3047 case CDSC_RESPONSE_IGNORE_ALL:
3048 return CDSC_NOTDSC;
3049 }
3050 }
3051 else {
3052 dsc->scan_section = scan_pre_trailer;
3053 if (dsc_check_match(dsc))
3054 return CDSC_NOTDSC;
3055 return CDSC_PROPAGATE;
3056 }
3057 }
3058 else {
3059 dsc->scan_section = scan_pre_trailer;
3060 if (dsc_check_match(dsc))
3061 return CDSC_NOTDSC;
3062 return CDSC_PROPAGATE;
3063 }
3064 }
3065 else if (IS_DSC(line, "%%EOF")) {
3066 if (dsc->page_count)
3067 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3068 if (dsc->file_length) {
3069 if ((!dsc->doseps_end &&
3070 ((DSC_END(dsc) + 100) < dsc->file_length)) ||
3071 ((dsc->doseps_end) &&
3072 ((DSC_END(dsc) + 100) < dsc->doseps_end))) {
3073 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF,
3074 dsc->line, dsc->line_length);
3075 switch (rc) {
3076 case CDSC_RESPONSE_OK:
3077 /* %%EOF is wrong, ignore it */
3078 break;
3079 case CDSC_RESPONSE_CANCEL:
3080 /* %%EOF is correct */
3081 dsc->scan_section = scan_eof;
3082 dsc->eof = TRUE;
3083 if (dsc_check_match(dsc))
3084 return CDSC_NOTDSC;
3085 return CDSC_PROPAGATE;
3086 case CDSC_RESPONSE_IGNORE_ALL:
3087 return CDSC_NOTDSC;
3088 }
3089 }
3090 }
3091 else {
3092 /* ignore it */
3093 if (dsc_check_match(dsc))
3094 return CDSC_NOTDSC;
3095 return CDSC_OK;
3096 }
3097 }
3098 else {
3099 /* Section comment, probably from a badly */
3100 /* encapsulated EPS file. */
3101 int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION,
3102 dsc->line, dsc->line_length);
3103 if (rc == CDSC_RESPONSE_IGNORE_ALL)
3104 return CDSC_NOTDSC;
3105 }
3106 }
3107 else if (IS_DSC(line, "%%PageTrailer")) {
3108 dsc->id = CDSC_PAGETRAILER;
3109 /* ignore */
3110 }
3111 else if (IS_DSC(line, "%%BeginPageSetup")) {
3112 dsc->id = CDSC_BEGINPAGESETUP;
3113 /* ignore */
3114 }
3115 else if (IS_DSC(line, "%%EndPageSetup")) {
3116 dsc->id = CDSC_ENDPAGESETUP;
3117 /* ignore */
3118 }
3119 else if (IS_DSC(line, "%%PageMedia:")) {
3120 dsc->id = CDSC_PAGEMEDIA;
3121 if (dsc->page_count)
3122 dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media));
3123 }
3124 else if (IS_DSC(line, "%%PaperColor:")) {
3125 dsc->id = CDSC_PAPERCOLOR;
3126 /* ignore */
3127 }
3128 else if (IS_DSC(line, "%%PaperForm:")) {
3129 dsc->id = CDSC_PAPERFORM;
3130 /* ignore */
3131 }
3132 else if (IS_DSC(line, "%%PaperWeight:")) {
3133 dsc->id = CDSC_PAPERWEIGHT;
3134 /* ignore */
3135 }
3136 else if (IS_DSC(line, "%%PaperSize:")) {
3137 /* DSC 2.1 */
3138 GSBOOL found_media = FALSE;
3139 int i;
3140 int n = 12;
3141 char buf[MAXSTR];
3142 buf[0] = '\0';
3143 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n,
3144 dsc->line_length-n, NULL);
3145 for (i=0; i<(int)dsc->media_count; i++) {
3146 if (dsc->media[i] && dsc->media[i]->name &&
3147 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
3148 if (dsc->page_count)
3149 dsc->page[dsc->page_count-1].media = dsc->media[i];
3150 found_media = TRUE;
3151 break;
3152 }
3153 }
3154 if (!found_media) {
3155 /* It didn't match %%DocumentPaperSizes: */
3156 /* Try our known media */
3157 const CDSCMEDIA *m = dsc_known_media;
3158 while (m->name) {
3159 if (dsc_stricmp(buf, m->name)==0) {
3160 if (dsc->page_count)
3161 dsc->page[dsc->page_count-1].media = m;
3162 break;
3163 }
3164 m++;
3165 }
3166 if (m->name == NULL)
3167 dsc_unknown(dsc);
3168 }
3169 }
3170 else if (IS_DSC(line, "%%PageOrientation:")) {
3171 if (dsc->page_count) {
3172 dsc->id = CDSC_PAGEORIENTATION;
3173 if (dsc_parse_orientation(dsc,
3174 &(dsc->page[dsc->page_count-1].orientation) ,18))
3175 return CDSC_NOTDSC;
3176 }
3177 }
3178 else if (IS_DSC(line, "%%PageBoundingBox:")) {
3179 if (dsc->page_count) {
3180 dsc->id = CDSC_PAGEBOUNDINGBOX;
3181 if (dsc_parse_bounding_box(dsc,
3182 &dsc->page[dsc->page_count-1].bbox, 18))
3183 return CDSC_NOTDSC;
3184 }
3185 }
3186 else if (IS_DSC(line, "%%ViewingOrientation:")) {
3187 if (dsc->page_count) {
3188 dsc->id = CDSC_VIEWINGORIENTATION;
3189 if (dsc_parse_viewing_orientation(dsc,
3190 &dsc->page[dsc->page_count-1].viewing_orientation))
3191 return CDSC_ERROR;
3192 }
3193 }
3194 else if (IS_DSC(line, "%%PageCropBox:")) {
3195 if (dsc->page_count) {
3196 dsc->id = CDSC_PAGECROPBOX;
3197 if (dsc_parse_float_bounding_box(dsc,
3198 &(dsc->page[dsc->page_count-1].crop_box), 14))
3199 return CDSC_ERROR;
3200 }
3201 }
3202 else if (IS_DSC(line, "%%BeginFont:")) {
3203 dsc->id = CDSC_BEGINFONT;
3204 /* ignore Begin/EndFont, apart form making sure */
3205 /* that they are matched. */
3206 dsc->begin_font_count++;
3207 }
3208 else if (IS_DSC(line, "%%EndFont")) {
3209 dsc->id = CDSC_BEGINFONT;
3210 dsc->begin_font_count--;
3211 }
3212 else if (IS_DSC(line, "%%BeginFeature:")) {
3213 dsc->id = CDSC_BEGINFEATURE;
3214 /* ignore Begin/EndFeature, apart form making sure */
3215 /* that they are matched. */
3216 dsc->begin_feature_count++;
3217 }
3218 else if (IS_DSC(line, "%%EndFeature")) {
3219 dsc->id = CDSC_ENDFEATURE;
3220 dsc->begin_feature_count--;
3221 }
3222 else if (IS_DSC(line, "%%BeginResource:")) {
3223 dsc->id = CDSC_BEGINRESOURCE;
3224 /* ignore Begin/EndResource, apart form making sure */
3225 /* that they are matched. */
3226 dsc->begin_resource_count++;
3227 }
3228 else if (IS_DSC(line, "%%EndResource")) {
3229 dsc->id = CDSC_ENDRESOURCE;
3230 dsc->begin_resource_count--;
3231 }
3232 else if (IS_DSC(line, "%%BeginProcSet:")) {
3233 dsc->id = CDSC_BEGINPROCSET;
3234 /* ignore Begin/EndProcSet, apart form making sure */
3235 /* that they are matched. */
3236 dsc->begin_procset_count++;
3237 }
3238 else if (IS_DSC(line, "%%EndProcSet")) {
3239 dsc->id = CDSC_ENDPROCSET;
3240 dsc->begin_procset_count--;
3241 }
3242 else if (IS_DSC(line, "%%IncludeFont:")) {
3243 dsc->id = CDSC_INCLUDEFONT;
3244 /* ignore */
3245 }
3246 else {
3247 /* All other DSC comments are unknown, but not an error */
3248 dsc->id = CDSC_UNKNOWNDSC;
3249 dsc_unknown(dsc);
3250 }
3251
3252 if (dsc->page_count)
3253 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
3254 return CDSC_OK;
3255 }
3256
3257 /* Valid Trailer comments are
3258 * %%Trailer
3259 * %%EOF
3260 * or the following deferred with (atend)
3261 * %%BoundingBox:
3262 * %%DocumentCustomColors:
3263 * %%DocumentFiles:
3264 * %%DocumentFonts:
3265 * %%DocumentNeededFiles:
3266 * %%DocumentNeededFonts:
3267 * %%DocumentNeededProcSets:
3268 * %%DocumentNeededResources:
3269 * %%DocumentProcSets:
3270 * %%DocumentProcessColors:
3271 * %%DocumentSuppliedFiles:
3272 * %%DocumentSuppliedFonts:
3273 * %%DocumentSuppliedProcSets:
3274 * %%DocumentSuppliedResources:
3275 * %%Orientation:
3276 * %%Pages:
3277 * %%PageOrder:
3278 *
3279 * Our supported subset is
3280 * %%Trailer
3281 * %%EOF
3282 * %%BoundingBox:
3283 * %%CropBox:
3284 * %%HiResBoundingBox:
3285 * %%DocumentCustomColors:
3286 * %%DocumentProcessColors:
3287 * %%Orientation:
3288 * %%Pages:
3289 * %%PageOrder:
3290 * In addition to these, we support
3291 * %%DocumentMedia:
3292 *
3293 * A %%PageTrailer can have the following:
3294 * %%PageBoundingBox:
3295 * %%PageCustomColors:
3296 * %%PageFiles:
3297 * %%PageFonts:
3298 * %%PageOrientation:
3299 * %%PageProcessColors:
3300 * %%PageResources:
3301 */
3302
3303 static int
dsc_scan_trailer(CDSC * dsc)3304 dsc_scan_trailer(CDSC *dsc)
3305 {
3306 /* Trailer section start at */
3307 /* %%Trailer */
3308 /* and ends at */
3309 /* %%EOF */
3310 char *line = dsc->line;
3311 GSBOOL continued = FALSE;
3312
3313 if (dsc->endtrailer && IS_DSC(line, "%!PS-Adobe")) {
3314 unsigned char *p = (unsigned char *)dsc->line;
3315
3316 dsc->endtrailer = 0;
3317 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
3318 if (COMPARE(p, "%!PS-Adobe")) {
3319 dsc->dsc = TRUE;
3320 dsc->begincomments = DSC_START(dsc);
3321 if (dsc->dsc_version == NULL)
3322 return CDSC_ERROR; /* no memory */
3323 p = (unsigned char *)dsc->line + 14;
3324 while (IS_WHITE(*p))
3325 p++;
3326 if (COMPARE(p, "EPSF-"))
3327 dsc->epsf = TRUE;
3328 dsc->scan_section = scan_comments;
3329 return CDSC_PSADOBE;
3330 }
3331 }
3332
3333 dsc->id = CDSC_OK;
3334
3335 if (dsc->scan_section == scan_pre_trailer) {
3336 if (IS_DSC(line, "%%Trailer")) {
3337 dsc->id = CDSC_TRAILER;
3338 dsc->begintrailer = DSC_START(dsc);
3339 dsc->endtrailer = DSC_END(dsc);
3340 dsc->scan_section = scan_trailer;
3341 return CDSC_OK;
3342 }
3343 else if (IS_DSC(line, "%%EOF")) {
3344 dsc->id = CDSC_EOF;
3345 dsc->begintrailer = DSC_START(dsc);
3346 dsc->endtrailer = DSC_END(dsc);
3347 dsc->scan_section = scan_trailer;
3348 /* Continue, in case we found %%EOF in an embedded document */
3349 return CDSC_OK;
3350 }
3351 else {
3352 /* %%Page: didn't follow %%EndSetup
3353 * Keep reading until reach %%Page or %%Trailer
3354 * and add it to setup section
3355 */
3356 /* append to previous section */
3357 if (dsc->beginsetup)
3358 dsc->endsetup = DSC_END(dsc);
3359 else if (dsc->beginprolog)
3360 dsc->endprolog = DSC_END(dsc);
3361 else {
3362 /* horribly confused */
3363 }
3364 return CDSC_OK;
3365 }
3366 }
3367
3368 /* Handle continuation lines.
3369 * See comment above about our restrictive processing of
3370 * continuation lines
3371 */
3372 if (IS_DSC(line, "%%+")) {
3373 line = dsc->last_line;
3374 continued = TRUE;
3375 }
3376 else
3377 dsc_save_line(dsc);
3378
3379 if (NOT_DSC_LINE(line)) {
3380 /* ignore */
3381 }
3382 else if (IS_DSC(dsc->line, "%%EOF")) {
3383 /* Keep scanning, in case we have a false trailer */
3384 dsc->id = CDSC_EOF;
3385 }
3386 else if (IS_DSC(dsc->line, "%%Trailer")) {
3387 /* Cope with no pages with code after setup and before trailer. */
3388 /* Last trailer is the correct one. */
3389 dsc->id = CDSC_TRAILER;
3390 dsc->begintrailer = DSC_START(dsc);
3391 }
3392 else if (IS_DSC(line, "%%Pages:")) {
3393 dsc->id = CDSC_PAGES;
3394 if (dsc_parse_pages(dsc) != 0)
3395 return CDSC_ERROR;
3396 }
3397 else if (IS_DSC(line, "%%BoundingBox:")) {
3398 dsc->id = CDSC_BOUNDINGBOX;
3399 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
3400 return CDSC_ERROR;
3401 }
3402 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
3403 dsc->id = CDSC_HIRESBOUNDINGBOX;
3404 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
3405 continued ? 3 : 19))
3406 return CDSC_ERROR;
3407 }
3408 else if (IS_DSC(line, "%%CropBox:")) {
3409 dsc->id = CDSC_CROPBOX;
3410 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
3411 continued ? 3 : 10))
3412 return CDSC_ERROR;
3413 }
3414 else if (IS_DSC(line, "%%Orientation:")) {
3415 dsc->id = CDSC_ORIENTATION;
3416 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14))
3417 return CDSC_ERROR;
3418 }
3419 else if (IS_DSC(line, "%%PageOrder:")) {
3420 dsc->id = CDSC_PAGEORDER;
3421 if (dsc_parse_order(dsc))
3422 return CDSC_ERROR;
3423 }
3424 else if (IS_DSC(line, "%%DocumentMedia:")) {
3425 dsc->id = CDSC_DOCUMENTMEDIA;
3426 if (dsc_parse_document_media(dsc))
3427 return CDSC_ERROR;
3428 }
3429 else if (IS_DSC(dsc->line, "%%Page:")) {
3430 /* This should not occur in the trailer, but we might see
3431 * this if a document has been incorrectly embedded.
3432 */
3433 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER,
3434 dsc->line, dsc->line_length);
3435 switch (rc) {
3436 case CDSC_RESPONSE_OK:
3437 /* Assume that we are really in the previous */
3438 /* page, not the trailer */
3439 dsc->scan_section = scan_pre_pages;
3440 if (dsc->page_count)
3441 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3442 return CDSC_PROPAGATE; /* try again */
3443 case CDSC_RESPONSE_CANCEL:
3444 /* ignore pages in trailer */
3445 break;
3446 case CDSC_RESPONSE_IGNORE_ALL:
3447 return CDSC_NOTDSC;
3448 }
3449 }
3450 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
3451 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
3452 /* ignore */
3453 }
3454 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
3455 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
3456 /* ignore */
3457 }
3458 else if (IS_DSC(line, "%%DocumentProcessColors:")) {
3459 dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
3460 if (dsc_parse_process_colours(dsc) != CDSC_OK)
3461 dsc->id = CDSC_UNKNOWNDSC;
3462 }
3463 else if (IS_DSC(line, "%%DocumentCustomColors:")) {
3464 dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
3465 if (dsc_parse_custom_colours(dsc) != CDSC_OK)
3466 dsc->id = CDSC_UNKNOWNDSC;
3467 }
3468 else {
3469 /* All other DSC comments are unknown, but not an error */
3470 dsc->id = CDSC_UNKNOWNDSC;
3471 dsc_unknown(dsc);
3472 }
3473
3474 dsc->endtrailer = DSC_END(dsc);
3475 return CDSC_OK;
3476 }
3477
3478 static char *
dsc_alloc_string(CDSC * dsc,const char * str,int len)3479 dsc_alloc_string(CDSC *dsc, const char *str, int len)
3480 {
3481 char *p;
3482 if (dsc->string_head == NULL) {
3483 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3484 if (dsc->string_head == NULL)
3485 return NULL; /* no memory */
3486 dsc->string = dsc->string_head;
3487 dsc->string->next = NULL;
3488 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3489 if (dsc->string->data == NULL) {
3490 dsc_reset(dsc);
3491 return NULL; /* no memory */
3492 }
3493 dsc->string->index = 0;
3494 dsc->string->length = CDSC_STRING_CHUNK;
3495 }
3496 if ( dsc->string->index + len + 1 > dsc->string->length) {
3497 /* allocate another string block */
3498 CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3499 if (newstring == NULL) {
3500 dsc_debug_print(dsc, "Out of memory\n");
3501 return NULL;
3502 }
3503 newstring->next = NULL;
3504 newstring->length = 0;
3505 newstring->index = 0;
3506 newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3507 if (newstring->data == NULL) {
3508 dsc_memfree(dsc, newstring);
3509 dsc_debug_print(dsc, "Out of memory\n");
3510 return NULL; /* no memory */
3511 }
3512 newstring->length = CDSC_STRING_CHUNK;
3513 dsc->string->next = newstring;
3514 dsc->string = newstring;
3515 }
3516 if ( dsc->string->index + len + 1 > dsc->string->length)
3517 return NULL; /* failed */
3518 p = dsc->string->data + dsc->string->index;
3519 memcpy(p, str, len);
3520 *(p+len) = '\0';
3521 dsc->string->index += len + 1;
3522 return p;
3523 }
3524
3525 /* store line, ignoring leading spaces */
3526 static char *
dsc_add_line(CDSC * dsc,const char * line,unsigned int len)3527 dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
3528 {
3529 char *newline;
3530 unsigned int i;
3531 while (len && (IS_WHITE(*line))) {
3532 len--;
3533 line++;
3534 }
3535 newline = dsc_alloc_string(dsc, line, len);
3536 if (newline == NULL)
3537 return NULL;
3538
3539 for (i=0; i<len; i++) {
3540 if (newline[i] == '\r') {
3541 newline[i]='\0';
3542 break;
3543 }
3544 if (newline[i] == '\n') {
3545 newline[i]='\0';
3546 break;
3547 }
3548 }
3549 return newline;
3550 }
3551
3552 /* Copy string on line to new allocated string str */
3553 /* String is always null terminated */
3554 /* String is no longer than len */
3555 /* Return pointer to string */
3556 /* Store number of used characters from line */
3557 /* Don't copy enclosing () */
3558 static char *
dsc_copy_string(char * str,unsigned int slen,char * line,unsigned int len,unsigned int * offset)3559 dsc_copy_string(char *str, unsigned int slen, char *line,
3560 unsigned int len, unsigned int *offset)
3561 {
3562 int quoted = FALSE;
3563 int instring=0;
3564 unsigned int newlength = 0;
3565 unsigned int i = 0;
3566 unsigned char ch;
3567 if (len > slen)
3568 len = slen-1;
3569 while ( (i<len) && IS_WHITE(line[i]))
3570 i++; /* skip leading spaces */
3571 if ((i < len) && (line[i]=='(')) {
3572 quoted = TRUE;
3573 instring++;
3574 i++; /* don't copy outside () */
3575 }
3576 while (i < len) {
3577 str[newlength] = ch = line[i];
3578 i++;
3579 if (quoted) {
3580 if (ch == '(')
3581 instring++;
3582 if (ch == ')')
3583 instring--;
3584 if (instring==0)
3585 break;
3586 }
3587 else if (ch == ' ')
3588 break;
3589
3590 if (ch == '\r')
3591 break;
3592 if (ch == '\n')
3593 break;
3594 else if ( (ch == '\\') && (i+1 < len) ) {
3595 ch = line[i];
3596 if ((ch >= '0') && (ch <= '9')) {
3597 /* octal coded character */
3598 int j = 3;
3599 ch = 0;
3600 while (j && (i < len) && line[i]>='0' && line[i]<='7') {
3601 ch = (unsigned char)((ch<<3) + (line[i]-'0'));
3602 i++;
3603 j--;
3604 }
3605 str[newlength] = ch;
3606 }
3607 else if (ch == '(') {
3608 str[newlength] = ch;
3609 i++;
3610 }
3611 else if (ch == ')') {
3612 str[newlength] = ch;
3613 i++;
3614 }
3615 else if (ch == 'b') {
3616 str[newlength] = '\b';
3617 i++;
3618 }
3619 else if (ch == 'f') {
3620 str[newlength] = '\b';
3621 i++;
3622 }
3623 else if (ch == 'n') {
3624 str[newlength] = '\n';
3625 i++;
3626 }
3627 else if (ch == 'r') {
3628 str[newlength] = '\r';
3629 i++;
3630 }
3631 else if (ch == 't') {
3632 str[newlength] = '\t';
3633 i++;
3634 }
3635 else if (ch == '\\') {
3636 str[newlength] = '\\';
3637 i++;
3638 }
3639 }
3640 newlength++;
3641 }
3642 str[newlength] = '\0';
3643 if (offset != (unsigned int *)NULL)
3644 *offset = i;
3645 return str;
3646 }
3647
3648 static int
dsc_get_int(const char * line,unsigned int len,unsigned int * offset)3649 dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
3650 {
3651 char newline[MAXSTR];
3652 int newlength = 0;
3653 unsigned int i = 0;
3654 unsigned char ch;
3655
3656 len = min(len, sizeof(newline)-1);
3657 while ((i<len) && IS_WHITE(line[i]))
3658 i++; /* skip leading spaces */
3659 while (i < len) {
3660 newline[newlength] = ch = line[i];
3661 if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
3662 break; /* not part of an integer number */
3663 i++;
3664 newlength++;
3665 }
3666 while ((i<len) && IS_WHITE(line[i]))
3667 i++; /* skip trailing spaces */
3668 newline[newlength] = '\0';
3669 if (offset != (unsigned int *)NULL)
3670 *offset = i;
3671 return atoi(newline);
3672 }
3673
3674 static float
dsc_get_real(const char * line,unsigned int len,unsigned int * offset)3675 dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
3676 {
3677 char newline[MAXSTR];
3678 int newlength = 0;
3679 unsigned int i = 0;
3680 unsigned char ch;
3681
3682 len = min(len, sizeof(newline)-1);
3683 while ((i<len) && IS_WHITE(line[i]))
3684 i++; /* skip leading spaces */
3685 while (i < len) {
3686 newline[newlength] = ch = line[i];
3687 if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
3688 || (ch=='e') || (ch=='E')))
3689 break; /* not part of a real number */
3690 i++;
3691 newlength++;
3692 }
3693 while ((i<len) && IS_WHITE(line[i]))
3694 i++; /* skip trailing spaces */
3695
3696 newline[newlength] = '\0';
3697
3698 if (offset != (unsigned int *)NULL)
3699 *offset = i;
3700 return (float)atof(newline);
3701 }
3702
3703 int
dsc_stricmp(const char * s,const char * t)3704 dsc_stricmp(const char *s, const char *t)
3705 {
3706 while (toupper((unsigned char)*s) == toupper((unsigned char)*t)) {
3707 if (*s == '\0')
3708 return 0;
3709 s++;
3710 t++;
3711 }
3712 return (toupper((unsigned char)*s) - toupper((unsigned char)*t));
3713 }
3714
3715 static int
dsc_parse_page(CDSC * dsc)3716 dsc_parse_page(CDSC *dsc)
3717 {
3718 char *p;
3719 unsigned int i;
3720 char page_label[MAXSTR];
3721 char *pl;
3722 int page_ordinal;
3723 int page_number;
3724
3725 p = dsc->line + 7;
3726 pl = dsc_copy_string(page_label, sizeof(page_label), p, dsc->line_length-7, &i);
3727 if (pl == NULL)
3728 return CDSC_ERROR;
3729 p += i;
3730 if (dsc->line_length - 7 - i == 0) {
3731 /* Ordinal missing, or parentheses not matched in label */
3732 /* Try to find ordinal at end of line */
3733 while (i > 0) {
3734 if (!IS_WHITE_OR_EOL(p[-1]))
3735 break;
3736 p--;
3737 i--;
3738 }
3739 while (i > 0) {
3740 if (!isdigit((int)p[-1]))
3741 break;
3742 p--;
3743 i--;
3744 }
3745 }
3746 page_ordinal = dsc_get_int(p, dsc->line_length - 7 - i, NULL);
3747
3748 if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
3749 (dsc->page_count &&
3750 (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
3751 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
3752 dsc->line_length);
3753 switch (rc) {
3754 case CDSC_RESPONSE_OK:
3755 /* ignore this page */
3756 return CDSC_OK;
3757 case CDSC_RESPONSE_CANCEL:
3758 /* accept the page */
3759 break;
3760 case CDSC_RESPONSE_IGNORE_ALL:
3761 return CDSC_NOTDSC;
3762 }
3763 }
3764
3765 page_number = dsc->page_count;
3766 dsc_add_page(dsc, page_ordinal, page_label);
3767 dsc->page[page_number].begin = DSC_START(dsc);
3768 dsc->page[page_number].end = DSC_START(dsc);
3769
3770 if (dsc->page[page_number].label == NULL)
3771 return CDSC_ERROR; /* no memory */
3772
3773 return CDSC_OK;
3774 }
3775
3776 /* DSC error reporting */
3777
3778 void
dsc_debug_print(CDSC * dsc,const char * str)3779 dsc_debug_print(CDSC *dsc, const char *str)
3780 {
3781 if (dsc->debug_print_fn)
3782 dsc->debug_print_fn(dsc->caller_data, str);
3783 }
3784
3785 /* Display a message about a problem with the DSC comments.
3786 *
3787 * explanation = an index to to a multiline explanation in dsc_message[]
3788 * line = pointer to the offending DSC line (if any)
3789 * return code =
3790 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
3791 * was really meant.
3792 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
3793 * is misplaced.
3794 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
3795 */
3796 /* Silent operation. Don't display errors. */
3797 static int
dsc_error(CDSC * dsc,unsigned int explanation,char * line,unsigned int line_len)3798 dsc_error(CDSC *dsc, unsigned int explanation,
3799 char *line, unsigned int line_len)
3800 {
3801 /* if error function provided, use it */
3802 if (dsc->dsc_error_fn)
3803 return dsc->dsc_error_fn(dsc->caller_data, dsc,
3804 explanation, line, line_len);
3805
3806 /* treat DSC as being correct */
3807 return CDSC_RESPONSE_CANCEL;
3808 }
3809
3810 /* Fixup if DCS 2.0 was used */
3811 static int
dsc_dcs2_fixup(CDSC * dsc)3812 dsc_dcs2_fixup(CDSC *dsc)
3813 {
3814 char composite[] = "Composite";
3815 /* If DCS 2.0 single file format found, expose the separations
3816 * as multiple pages. Treat the initial EPS file as a single
3817 * page without comments, prolog or trailer.
3818 */
3819 if (dsc->dcs2) {
3820 int code = CDSC_OK;
3821 int page_number;
3822 DSC_OFFSET *pbegin;
3823 DSC_OFFSET *pend;
3824 DSC_OFFSET end;
3825 CDCS2 *pdcs = NULL;
3826 /* Now treat the initial EPS file as a single page without
3827 * headers or trailer, so page extraction will fetch the
3828 * the correct separation. */
3829 if (dsc->page_count == 0)
3830 code = dsc_add_page(dsc, 1, composite);
3831 else if (dsc->page_count == 1)
3832 dsc->page[0].label =
3833 dsc_alloc_string(dsc, composite, (int)strlen(composite)+1);
3834 if (code != CDSC_OK)
3835 return code;
3836 page_number = dsc->page_count - 1;
3837 pbegin = &dsc->page[page_number].begin;
3838 pend = &dsc->page[page_number].end;
3839 if (*pbegin == *pend) {
3840 /* no page, so force it to conform to the following sections */
3841 *pbegin = 999999999;
3842 *pend = 0;
3843 }
3844
3845 if (dsc->begincomments != dsc->endcomments) {
3846 *pbegin = min(dsc->begincomments, *pbegin);
3847 dsc->begincomments = 0;
3848 *pend = max(dsc->endcomments, *pend);
3849 dsc->endcomments = 0;
3850 }
3851
3852 if (dsc->beginpreview != dsc->endpreview) {
3853 *pbegin = min(dsc->beginpreview, *pbegin);
3854 dsc->beginpreview = 0;
3855 *pend = max(dsc->endpreview, *pend);
3856 dsc->endpreview = 0;
3857 }
3858
3859 if (dsc->begindefaults != dsc->enddefaults) {
3860 *pbegin = min(dsc->begindefaults, *pbegin);
3861 dsc->begindefaults = 0;
3862 *pend = max(dsc->enddefaults, *pend);
3863 dsc->enddefaults = 0;
3864 }
3865
3866 if (dsc->beginprolog != dsc->endprolog) {
3867 *pbegin = min(dsc->beginprolog, *pbegin);
3868 dsc->beginprolog = 0;
3869 *pend = max(dsc->endprolog, *pend);
3870 dsc->endprolog = 0;
3871 }
3872
3873 if (dsc->beginsetup != dsc->endsetup) {
3874 *pbegin = min(dsc->beginsetup, *pbegin);
3875 dsc->beginsetup = 0;
3876 *pend = max(dsc->endsetup, *pend);
3877 dsc->endsetup = 0;
3878 }
3879
3880 if (dsc->begintrailer != dsc->endtrailer) {
3881 *pbegin = min(dsc->begintrailer, *pbegin);
3882 dsc->begintrailer = 0;
3883 *pend = max(dsc->endtrailer, *pend);
3884 dsc->endtrailer = 0;
3885 }
3886
3887 if (*pbegin == 999999999)
3888 *pbegin = *pend;
3889 end = 0; /* end of composite is start of first separation */
3890
3891 /* we used to do this where the pointer is declared, but Coverity points out
3892 * that dsc_alloc_string can call dsc_reset which can free dsc and dsc->dcs2.
3893 * By deferring the initialisation to here we can ensure we don't have a
3894 * dangling pointer. This makes me suspiciouos that DCS (not DSC!) comments
3895 * have never worked properly.
3896 */
3897 pdcs = dsc->dcs2;
3898
3899 while (pdcs) {
3900 page_number = dsc->page_count;
3901 if ((pdcs->begin) && (pdcs->colourname != NULL)) {
3902 /* Single file DCS 2.0 */
3903 code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3904 if (code)
3905 return code;
3906 dsc->page[page_number].begin = pdcs->begin;
3907 dsc->page[page_number].end = pdcs->end;
3908 if (end != 0)
3909 end = min(end, pdcs->begin);
3910 else
3911 end = pdcs->begin; /* first separation */
3912 }
3913 else {
3914 /* Multiple file DCS 2.0 */
3915 if ((pdcs->location != NULL) &&
3916 (pdcs->filetype != NULL) &&
3917 (pdcs->colourname != NULL) &&
3918 (dsc_stricmp(pdcs->location, "Local") == 0) &&
3919 ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
3920 (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
3921 code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3922 if (code)
3923 return code;
3924 dsc->page[page_number].begin = 0;
3925 dsc->page[page_number].end = 0;
3926 }
3927 }
3928 pdcs = pdcs->next;
3929 }
3930 /* end of composite is start of first separation */
3931 if (end != 0)
3932 *pend = end;
3933 /* According to the DCS2 specification, the size of the composite
3934 * section can be determined by the smallest #offset.
3935 * Some incorrect DCS2 files don't put the separations inside
3936 * the DOS EPS PostScript section, and have a TIFF separation
3937 * between the composite and the first separation. This
3938 * contravenes the DCS2 specification. If we see one of these
3939 * files, bring the end of the composite back to the end of
3940 * the DOS EPS PostScript section.
3941 */
3942 if (dsc->doseps_end && (*pend > dsc->doseps_end))
3943 *pend = dsc->doseps_end;
3944 }
3945 return 0;
3946 }
3947
3948 static int
dsc_parse_platefile(CDSC * dsc)3949 dsc_parse_platefile(CDSC *dsc)
3950 {
3951 unsigned int i, n;
3952 CDCS2 dcs2;
3953 CDCS2 *pdcs2;
3954 char colourname[MAXSTR];
3955 char filetype[MAXSTR];
3956 char location[MAXSTR];
3957 char *filename = NULL;
3958 int filename_length = 0;
3959 GSBOOL blank_line;
3960 GSBOOL single = FALSE;
3961 if (IS_DSC(dsc->line, "%%PlateFile:"))
3962 n = 12;
3963 else if (IS_DSC(dsc->line, "%%+"))
3964 n = 3;
3965 else
3966 return CDSC_ERROR; /* error */
3967
3968 memset(&dcs2, 0, sizeof(dcs2));
3969 memset(&colourname, 0, sizeof(colourname));
3970 memset(&filetype, 0, sizeof(filetype));
3971 memset(&location, 0, sizeof(location));
3972 memset(&filename, 0, sizeof(filename));
3973
3974 /* check for blank remainder of line */
3975 blank_line = TRUE;
3976 for (i=n; i<dsc->line_length; i++) {
3977 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
3978 blank_line = FALSE;
3979 break;
3980 }
3981 }
3982
3983 if (!blank_line) {
3984 dsc_copy_string(colourname, sizeof(colourname),
3985 dsc->line+n, dsc->line_length-n, &i);
3986 n+=i;
3987 if (i)
3988 dsc_copy_string(filetype, sizeof(filetype),
3989 dsc->line+n, dsc->line_length-n, &i);
3990 n+=i;
3991 while (IS_WHITE_OR_EOL(dsc->line[n]))
3992 n++;
3993 if (dsc->line[n] == '#') {
3994 /* single file DCS 2.0 */
3995 single = TRUE;
3996 n++;
3997 if (i)
3998 dcs2.begin= dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
3999 n+=i;
4000 if (i)
4001 dcs2.end= dcs2.begin +
4002 dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
4003 }
4004 else {
4005 /* multiple file DCS 2.0 */
4006 if (i)
4007 dsc_copy_string(location, sizeof(location),
4008 dsc->line+n, dsc->line_length-n, &i);
4009 n+=i;
4010 if (i) {
4011 filename = dsc->line+n;
4012 filename_length = dsc->line_length-n;
4013 }
4014 }
4015 if (i==0)
4016 dsc_unknown(dsc); /* we didn't get all fields */
4017 else {
4018 /* Allocate strings */
4019 if (strlen(colourname))
4020 dcs2.colourname = dsc_alloc_string(dsc,
4021 colourname, (int)strlen(colourname));
4022 if (strlen(filetype))
4023 dcs2.filetype = dsc_alloc_string(dsc,
4024 filetype, (int)strlen(filetype));
4025 if (strlen(location))
4026 dcs2.location = dsc_alloc_string(dsc,
4027 location, (int)strlen(location));
4028 if (filename)
4029 dcs2.filename = dsc_add_line(dsc, filename, filename_length);
4030
4031 /* Prevent parser from reading separations */
4032 if (single)
4033 dsc->file_length = min(dsc->file_length, dcs2.begin);
4034 /* Allocate it */
4035 pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4036 if (pdcs2 == NULL)
4037 return CDSC_ERROR; /* out of memory */
4038 memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4039 /* Then add to list of separations */
4040 if (dsc->dcs2 == NULL)
4041 dsc->dcs2 = pdcs2;
4042 else {
4043 CDCS2 *this_dcs2 = dsc->dcs2;
4044 while (this_dcs2->next)
4045 this_dcs2 = this_dcs2->next;
4046 this_dcs2->next = pdcs2;
4047 }
4048 }
4049 }
4050 return CDSC_OK;
4051 }
4052
4053 /* Parse a DCS 1.0 plate comment, storing like a multi file DSC 2.0 */
4054 static int
dsc_parse_dcs1plate(CDSC * dsc)4055 dsc_parse_dcs1plate(CDSC *dsc)
4056 {
4057 unsigned int i, n = 0;
4058 CDCS2 dcs2;
4059 CDCS2 *pdcs2;
4060 const char *colourname;
4061 char filename[MAXSTR];
4062 GSBOOL blank_line;
4063 GSBOOL continued = FALSE;
4064 char *line = dsc->line;
4065
4066 memset(&dcs2, 0, sizeof(dcs2));
4067 memset(&filename, 0, sizeof(filename));
4068
4069 if (IS_DSC(line, "%%+")) {
4070 n = 3;
4071 line = dsc->last_line;
4072 continued = TRUE;
4073 }
4074
4075 if (IS_DSC(line, "%%CyanPlate:")) {
4076 colourname = "Cyan";
4077 if (!continued)
4078 n = 12;
4079 }
4080 else if (IS_DSC(line, "%%MagentaPlate:")) {
4081 colourname = "Magenta";
4082 if (!continued)
4083 n = 15;
4084 }
4085 else if (IS_DSC(line, "%%YellowPlate:")) {
4086 colourname = "Yellow";
4087 if (!continued)
4088 n = 14;
4089 }
4090 else if (IS_DSC(line, "%%BlackPlate:")) {
4091 colourname = "Black";
4092 if (!continued)
4093 n = 13;
4094 }
4095 else
4096 return CDSC_ERROR; /* error */
4097
4098 /* check for blank remainder of line */
4099 blank_line = TRUE;
4100 for (i=n; i<dsc->line_length; i++) {
4101 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4102 blank_line = FALSE;
4103 break;
4104 }
4105 }
4106
4107 if (!blank_line) {
4108 dsc_copy_string(filename, sizeof(filename),
4109 dsc->line+n, dsc->line_length-n, &i);
4110 if (i==0)
4111 dsc_unknown(dsc); /* we didn't get all fields */
4112 else {
4113 /* Allocate strings */
4114 dcs2.colourname = dsc_alloc_string(dsc,
4115 colourname, (int)strlen(colourname));
4116 dcs2.filetype = dsc_alloc_string(dsc, "EPS", 3);
4117 dcs2.location = dsc_alloc_string(dsc, "Local", 5);
4118 if (strlen(filename))
4119 dcs2.filename = dsc_alloc_string(dsc,
4120 filename, (int)strlen(filename));
4121 /* Allocate it */
4122 pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4123 if (pdcs2 == NULL)
4124 return CDSC_ERROR; /* out of memory */
4125 memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4126 /* Then add to list of separations */
4127 if (dsc->dcs2 == NULL)
4128 dsc->dcs2 = pdcs2;
4129 else {
4130 CDCS2 *this_dcs2 = dsc->dcs2;
4131 while (this_dcs2->next)
4132 this_dcs2 = this_dcs2->next;
4133 this_dcs2->next = pdcs2;
4134 }
4135 }
4136 }
4137 return CDSC_OK;
4138 }
4139
4140 /* Find the filename which corresponds to this separation.
4141 * Used with multiple file DCS 2.0.
4142 * Returns NULL if there is no filename, or not DCS 2.0,
4143 * or single file DCS 2.0.
4144 * Caller will need to obtain the filesize from the file.
4145 */
4146 const char *
dsc_find_platefile(CDSC * dsc,int page)4147 dsc_find_platefile(CDSC *dsc, int page)
4148 {
4149 CDCS2 *pdcs = dsc->dcs2;
4150 int i = 1;
4151 while (pdcs) {
4152 if (pdcs->begin != pdcs->end)
4153 return NULL; /* Single file DCS 2.0 */
4154 if (pdcs->location && pdcs->filetype && pdcs->colourname
4155 && (dsc_stricmp(pdcs->location, "Local") == 0)
4156 && ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
4157 (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
4158 if (i == page)
4159 return pdcs->filename;
4160 i++;
4161 }
4162 pdcs = pdcs->next;
4163 }
4164 return NULL;
4165 }
4166
4167 static CDSCCOLOUR *
dsc_find_colour(CDSC * dsc,const char * colourname)4168 dsc_find_colour(CDSC *dsc, const char *colourname)
4169 {
4170 CDSCCOLOUR *colour = dsc->colours;
4171 while (colour) {
4172 if (colour->name && (dsc_stricmp(colour->name, colourname)==0))
4173 return colour;
4174 colour = colour->next;
4175 }
4176 return 0;
4177 }
4178
4179 static int
dsc_parse_process_colours(CDSC * dsc)4180 dsc_parse_process_colours(CDSC *dsc)
4181 {
4182 unsigned int i, n;
4183 CDSCCOLOUR *pcolour;
4184 char colourname[MAXSTR];
4185 GSBOOL blank_line;
4186 if (IS_DSC(dsc->line, "%%DocumentProcessColors:"))
4187 n = 24;
4188 else if (IS_DSC(dsc->line, "%%+"))
4189 n = 3;
4190 else
4191 return CDSC_ERROR; /* error */
4192
4193 memset(&colourname, 0, sizeof(colourname));
4194
4195 /* check for blank remainder of line */
4196 blank_line = TRUE;
4197 for (i=n; i<dsc->line_length; i++) {
4198 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4199 blank_line = FALSE;
4200 break;
4201 }
4202 }
4203 while (IS_WHITE(dsc->line[n]))
4204 n++;
4205 if (COMPARE(dsc->line+n, "(atend)")) {
4206 if (dsc->scan_section == scan_comments)
4207 blank_line = TRUE;
4208 else {
4209 dsc_unknown(dsc);
4210 return CDSC_NOTDSC;
4211 }
4212 }
4213
4214 if (!blank_line) {
4215 do {
4216 dsc_copy_string(colourname, sizeof(colourname),
4217 dsc->line+n, dsc->line_length-n, &i);
4218 n+=i;
4219 if (i && strlen(colourname)) {
4220 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4221 pcolour = (CDSCCOLOUR *)
4222 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4223 if (pcolour == NULL)
4224 return CDSC_ERROR; /* out of memory */
4225 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4226 pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4227 pcolour->name = dsc_alloc_string(dsc,
4228 colourname, (int)strlen(colourname));
4229 if (dsc->colours == NULL)
4230 dsc->colours = pcolour;
4231 else {
4232 CDSCCOLOUR *this_colour = dsc->colours;
4233 while (this_colour->next)
4234 this_colour = this_colour->next;
4235 this_colour->next = pcolour;
4236 }
4237 }
4238 pcolour->type = CDSC_COLOUR_PROCESS;
4239 if (dsc_stricmp(colourname, "Cyan")==0) {
4240 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4241 pcolour->cyan = 1.0;
4242 pcolour->magenta = pcolour->yellow = pcolour->black = 0.0;
4243 }
4244 else if (dsc_stricmp(colourname, "Magenta")==0) {
4245 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4246 pcolour->magenta = 1.0;
4247 pcolour->cyan = pcolour->yellow = pcolour->black = 0.0;
4248 }
4249 else if (dsc_stricmp(colourname, "Yellow")==0) {
4250 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4251 pcolour->yellow = 1.0;
4252 pcolour->cyan = pcolour->magenta = pcolour->black = 0.0;
4253 }
4254 else if (dsc_stricmp(colourname, "Black")==0) {
4255 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4256 pcolour->black = 1.0;
4257 pcolour->cyan = pcolour->magenta = pcolour->yellow = 0.0;
4258 }
4259 else if (dsc_stricmp(colourname, "Red")==0) {
4260 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4261 pcolour->red = 1.0;
4262 pcolour->green = pcolour->blue = 0.0;
4263 }
4264 else if (dsc_stricmp(colourname, "Green")==0) {
4265 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4266 pcolour->green = 1.0;
4267 pcolour->red = pcolour->blue = 0.0;
4268 }
4269 else if (dsc_stricmp(colourname, "Blue")==0) {
4270 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4271 pcolour->blue = 1.0;
4272 pcolour->red = pcolour->green = 0.0;
4273 }
4274 }
4275 } while (i != 0);
4276 }
4277 return CDSC_OK;
4278 }
4279
4280 static int
dsc_parse_custom_colours(CDSC * dsc)4281 dsc_parse_custom_colours(CDSC *dsc)
4282 {
4283 unsigned int i, n;
4284 CDSCCOLOUR *pcolour;
4285 char colourname[MAXSTR];
4286 GSBOOL blank_line;
4287 if (IS_DSC(dsc->line, "%%DocumentCustomColors:"))
4288 n = 23;
4289 else if (IS_DSC(dsc->line, "%%+"))
4290 n = 3;
4291 else
4292 return CDSC_ERROR; /* error */
4293
4294 memset(&colourname, 0, sizeof(colourname));
4295
4296 /* check for blank remainder of line */
4297 blank_line = TRUE;
4298 for (i=n; i<dsc->line_length; i++) {
4299 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4300 blank_line = FALSE;
4301 break;
4302 }
4303 }
4304 while (IS_WHITE(dsc->line[n]))
4305 n++;
4306 if (COMPARE(dsc->line+n, "(atend)")) {
4307 if (dsc->scan_section == scan_comments)
4308 blank_line = TRUE;
4309 else {
4310 dsc_unknown(dsc);
4311 return CDSC_NOTDSC;
4312 }
4313 }
4314
4315 if (!blank_line) {
4316 do {
4317 dsc_copy_string(colourname, sizeof(colourname),
4318 dsc->line+n, dsc->line_length-n, &i);
4319 n+=i;
4320 if (i && strlen(colourname)) {
4321 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4322 pcolour = (CDSCCOLOUR *)
4323 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4324 if (pcolour == NULL)
4325 return CDSC_ERROR; /* out of memory */
4326 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4327 pcolour->name = dsc_alloc_string(dsc,
4328 colourname, (int)strlen(colourname));
4329 pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4330 if (dsc->colours == NULL)
4331 dsc->colours = pcolour;
4332 else {
4333 CDSCCOLOUR *this_colour = dsc->colours;
4334 while (this_colour->next)
4335 this_colour = this_colour->next;
4336 this_colour->next = pcolour;
4337 }
4338 }
4339 pcolour->type = CDSC_COLOUR_CUSTOM;
4340 }
4341 } while (i != 0);
4342 }
4343 return CDSC_OK;
4344 }
4345
4346 static int
dsc_parse_cmyk_custom_colour(CDSC * dsc)4347 dsc_parse_cmyk_custom_colour(CDSC *dsc)
4348 {
4349 unsigned int i, n;
4350 CDSCCOLOUR *pcolour;
4351 char colourname[MAXSTR];
4352 float cyan, magenta, yellow, black;
4353 GSBOOL blank_line;
4354 if (IS_DSC(dsc->line, "%%CMYKCustomColor:"))
4355 n = 18;
4356 else if (IS_DSC(dsc->line, "%%+"))
4357 n = 3;
4358 else
4359 return CDSC_ERROR; /* error */
4360
4361 memset(&colourname, 0, sizeof(colourname));
4362
4363 /* check for blank remainder of line */
4364
4365 do {
4366 blank_line = TRUE;
4367 for (i=n; i<dsc->line_length; i++) {
4368 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4369 blank_line = FALSE;
4370 break;
4371 }
4372 }
4373 if (blank_line)
4374 break;
4375 else {
4376 magenta = yellow = black = 0.0;
4377 cyan = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4378 n += i;
4379 if (i)
4380 magenta = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4381 n += i;
4382 if (i)
4383 yellow = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4384 n += i;
4385 if (i)
4386 black = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4387 n += i;
4388 if (i)
4389 dsc_copy_string(colourname, sizeof(colourname),
4390 dsc->line+n, dsc->line_length-n, &i);
4391 n+=i;
4392 if (i && strlen(colourname)) {
4393 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4394 pcolour = (CDSCCOLOUR *)
4395 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4396 if (pcolour == NULL)
4397 return CDSC_ERROR; /* out of memory */
4398 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4399 pcolour->name = dsc_alloc_string(dsc,
4400 colourname, (int)strlen(colourname));
4401 pcolour->type = CDSC_COLOUR_UNKNOWN;
4402 if (dsc->colours == NULL)
4403 dsc->colours = pcolour;
4404 else {
4405 CDSCCOLOUR *this_colour = dsc->colours;
4406 while (this_colour->next)
4407 this_colour = this_colour->next;
4408 this_colour->next = pcolour;
4409 }
4410 }
4411 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4412 pcolour->cyan = cyan;
4413 pcolour->magenta = magenta;
4414 pcolour->yellow = yellow;
4415 pcolour->black = black;
4416 }
4417 }
4418 } while (i != 0);
4419 return CDSC_OK;
4420 }
4421
4422 static int
dsc_parse_rgb_custom_colour(CDSC * dsc)4423 dsc_parse_rgb_custom_colour(CDSC *dsc)
4424 {
4425 unsigned int i, n;
4426 CDSCCOLOUR *pcolour;
4427 char colourname[MAXSTR];
4428 float red, green, blue;
4429 GSBOOL blank_line;
4430 if (IS_DSC(dsc->line, "%%RGBCustomColor:"))
4431 n = 17;
4432 else if (IS_DSC(dsc->line, "%%+"))
4433 n = 3;
4434 else
4435 return CDSC_ERROR; /* error */
4436
4437 memset(&colourname, 0, sizeof(colourname));
4438
4439 /* check for blank remainder of line */
4440
4441 do {
4442 blank_line = TRUE;
4443 for (i=n; i<dsc->line_length; i++) {
4444 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4445 blank_line = FALSE;
4446 break;
4447 }
4448 }
4449 if (blank_line)
4450 break;
4451 else {
4452 green = blue = 0.0;
4453 red = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4454 n += i;
4455 if (i)
4456 green = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4457 n += i;
4458 if (i)
4459 blue = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4460 n += i;
4461 if (i)
4462 dsc_copy_string(colourname, sizeof(colourname),
4463 dsc->line+n, dsc->line_length-n, &i);
4464 n+=i;
4465 if (i && strlen(colourname)) {
4466 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4467 pcolour = (CDSCCOLOUR *)
4468 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4469 if (pcolour == NULL)
4470 return CDSC_ERROR; /* out of memory */
4471 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4472 pcolour->name = dsc_alloc_string(dsc,
4473 colourname, (int)strlen(colourname));
4474 pcolour->type = CDSC_COLOUR_UNKNOWN;
4475 if (dsc->colours == NULL)
4476 dsc->colours = pcolour;
4477 else {
4478 CDSCCOLOUR *this_colour = dsc->colours;
4479 while (this_colour->next)
4480 this_colour = this_colour->next;
4481 this_colour->next = pcolour;
4482 }
4483 }
4484 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4485 pcolour->red = red;
4486 pcolour->green = green;
4487 pcolour->blue = blue;
4488 }
4489 }
4490 } while (i != 0);
4491 return CDSC_OK;
4492 }
4493