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