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