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