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