update
[kdegraphics.git] / strigi-analyzer / ps / dscparse.cpp
blobc1f68bd8dca79f5c9dabb344df95fc0d4bd5773d
1 /* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved.
3 This file is part of GSview.
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.
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.
20 /* $Id$ */
22 /* dscparse.c - DSC parser */
25 * This is a DSC parser, based on the DSC 3.0 spec,
26 * with a few DSC 2.1 additions for page size.
28 * Current limitations:
29 * %%+ may be used after any comment in the comment or trailer,
30 * but is currently only supported by
31 * %%DocumentMedia
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)
43 * Other additions for defaults or page section
44 % %%ViewingOrientation: xx xy yx yy
47 #include <stdio.h> /* for sprintf(), not file I/O */
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ctype.h>
52 #define MAXSTR 256
54 #include "dscparse.h"
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.
61 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
62 #define IS_DSC(line, str) (COMPARE((line), (str)))
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]!='%'))
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)
75 /* dsc_scan_SECTION() functions return one of
76 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
77 * or one of the following
79 /* The line should be passed on to the next section parser. */
80 #define CDSC_PROPAGATE 10
82 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
83 #define CDSC_NEEDMORE 11
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));
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 */
148 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
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}
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
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"
233 /******************************************************************/
234 /* Public functions */
235 /******************************************************************/
237 /* constructor */
238 CDSC *
239 dsc_init(void *caller_data)
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;
247 return dsc_init2(dsc);
250 /* constructor, with caller supplied memalloc */
251 CDSC *
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)
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;
264 dsc->memalloc = memalloc;
265 dsc->memfree = memfree;
266 dsc->mem_closure_data = closure_data;
268 return dsc_init2(dsc);
273 /* destructor */
274 void
275 dsc_free(CDSC *dsc)
277 if (dsc == NULL)
278 return;
279 dsc_reset(dsc);
280 dsc_memfree(dsc, dsc);
284 /* Tell DSC parser how long document will be, to allow ignoring
285 * of early %%Trailer and %%EOF. This is optional.
287 void
288 dsc_set_length(CDSC *dsc, unsigned long len)
290 dsc->file_length = len;
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
301 dsc_scan_data(CDSC *dsc, const char *data, int length)
303 int bytes_read;
304 int code = 0;
306 if (dsc == NULL)
307 return CDSC_ERROR;
309 if (dsc->id == CDSC_NOTDSC)
310 return CDSC_NOTDSC;
311 dsc->id = CDSC_OK;
312 if (dsc->eof)
313 return CDSC_OK; /* ignore */
315 if (length == 0) {
316 /* EOF, so process what remains */
317 dsc->eof = TRUE;
320 do {
321 if (dsc->id == CDSC_NOTDSC)
322 break;
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;
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;
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;
347 dsc->id = code;
350 if (code == CDSC_NOTDSC) {
351 dsc->id = CDSC_NOTDSC;
352 break;
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 */
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;
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;
416 /* repeat if line is start of next section */
417 } while (code == CDSC_PROPAGATE);
419 /* if DOS EPS header not complete, ask for more */
420 if (code == CDSC_NEEDMORE) {
421 code = CDSC_OK;
422 break;
424 if (code == CDSC_NOTDSC) {
425 dsc->id = CDSC_NOTDSC;
426 break;
429 } while (length != 0);
431 return (code < 0) ? code : dsc->id;
434 /* Tidy up from incorrect DSC comments */
435 int
436 dsc_fixup(CDSC *dsc)
438 unsigned int i;
439 char buf[32];
440 unsigned long *last;
442 if (dsc->id == CDSC_NOTDSC)
443 return 0;
445 /* flush last partial line */
446 dsc_scan_data(dsc, NULL, 0);
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");
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;
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.
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;
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;
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;
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;
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;
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];
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;
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 */
560 return CDSC_OK;
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.
567 void
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)))
572 dsc->dsc_error_fn = fn;
576 /* Install a function for printing debug messages */
577 /* This is optional */
578 void
579 dsc_set_debug_function(CDSC *dsc,
580 void (*debug_fn)(P2(void *caller_data, const char *str)))
582 dsc->debug_print_fn = debug_fn;
585 /* Doesn't need to be public for PostScript documents */
586 /* Made public so GSview can add pages when processing PDF files */
587 int
588 dsc_add_page(CDSC *dsc, int ordinal, char *label)
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;
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;
612 return CDSC_OK;
615 /* Doesn't need to be public for PostScript documents */
616 /* Made public so GSview can store PDF MediaBox */
618 dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
620 CDSCMEDIA **newmedia_array;
621 CDSCMEDIA *newmedia;
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);
633 dsc->media = newmedia_array;
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;
648 dsc->media_count++;
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 */
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 */
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 */
671 newmedia->mediabox = NULL;
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;
679 return CDSC_OK;
682 /* Doesn't need to be public for PostScript documents */
683 /* Made public so GSview can store PDF CropBox */
685 dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
686 int llx, int lly, int urx, int ury)
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;
705 /******************************************************************/
706 /* Private functions below here. */
707 /******************************************************************/
709 dsc_private void *
710 dsc_memalloc(CDSC *dsc, size_t size)
712 if (dsc->memalloc)
713 return dsc->memalloc(size, dsc->mem_closure_data);
714 return malloc(size);
717 dsc_private void
718 dsc_memfree(CDSC*dsc, void *ptr)
720 if (dsc->memfree)
721 dsc->memfree(ptr, dsc->mem_closure_data);
722 else
723 free(ptr);
726 /* private constructor */
727 dsc_private CDSC *
728 dsc_init2(CDSC *dsc)
730 dsc_reset(dsc);
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 */
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 */
744 dsc->string->index = 0;
745 dsc->string->length = CDSC_STRING_CHUNK;
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 */
752 dsc->page_chunk_length = CDSC_PAGE_CHUNK;
753 dsc->page_count = 0;
755 dsc->line = NULL;
756 dsc->data_length = 0;
757 dsc->data_index = dsc->data_length;
759 return dsc;
763 dsc_private void
764 dsc_reset(CDSC *dsc)
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;
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. */
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);
800 if (dsc->page)
801 dsc_memfree(dsc, dsc->page);
802 dsc->page = NULL;
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;
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]);
820 dsc_memfree(dsc, dsc->media);
822 dsc->media_count = 0;
823 dsc->media = NULL;
825 /* page_media is pointer to an element of media or dsc_known_media */
826 /* do not free it. */
827 dsc->page_media = NULL;
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;
839 dsc->dsc_title = NULL;
840 dsc->dsc_creator = NULL;
841 dsc->dsc_date = NULL;
842 dsc->dsc_for = NULL;
845 dsc->max_error = DSC_MAX_ERROR;
846 dsc->severity = dsc_severity;
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;
864 dsc->data_length = 0;
865 dsc->data_index = 0;
866 dsc->data_offset = 0;
868 dsc->eof = 0;
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));
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);
886 dsc->string_head = NULL;
887 dsc->string = NULL;
889 /* don't touch caller functions */
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;
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
908 dsc_private void
909 dsc_section_join(unsigned long begin, unsigned long *pend, unsigned long **pplast)
911 if (begin)
912 **pplast = begin;
913 if (*pend > begin)
914 *pplast = pend;
918 /* return value is 0 if no line available, or length of line */
919 dsc_private int
920 dsc_read_line(CDSC *dsc)
922 char *p, *last;
923 dsc->line = NULL;
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;
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;
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;
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--;
957 /* skip over \n which followed \r */
958 if (dsc->last_cr && dsc->line[0] == '\n') {
959 dsc->data_index++;
960 dsc->line++;
962 dsc->last_cr = FALSE;
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;
976 if (*p == '\n') {
977 p++;
978 dsc->eol = TRUE; /* dsc->line is a complete line */
979 break;
981 if (*p == '\032') { /* MS-DOS Ctrl+Z */
982 dsc->eol = TRUE;
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;
993 dsc->data_index += dsc->line_length = (p - dsc->line);
994 } while (dsc->skip_lines && dsc->line_length);
996 if (dsc->line_length == 0)
997 return 0;
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--;
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)
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;
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";
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;
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;
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;
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;
1074 if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
1075 COMPARE(dsc->line, "%%BeginDocument:") ) {
1076 /* Skip over embedded document, recursively */
1077 dsc->skip_document++;
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;
1085 return dsc->line_length;
1089 /* Save last DSC line, for use with %%+ */
1090 dsc_private void
1091 dsc_save_line(CDSC *dsc)
1093 int len = min(sizeof(dsc->last_line), dsc->line_length);
1094 memcpy(dsc->last_line, dsc->line, len);
1097 /* display unknown DSC line */
1098 dsc_private void
1099 dsc_unknown(CDSC *dsc)
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);
1114 dsc_private GSBOOL
1115 dsc_is_section(char *line)
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;
1137 dsc_private GSDWORD
1138 dsc_get_dword(const unsigned char *buf)
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;
1148 dsc_private GSWORD
1149 dsc_get_word(const unsigned char *buf)
1151 GSWORD w;
1152 w = (GSWORD)buf[0];
1153 w |= (GSWORD)(buf[1]<<8);
1154 return w;
1157 dsc_private int
1158 dsc_read_doseps(CDSC *dsc)
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 */
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);
1172 dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
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;
1181 if (dsc->doseps->tiff_begin)
1182 dsc->preview = CDSC_TIFF;
1183 if (dsc->doseps->wmf_begin)
1184 dsc->preview = CDSC_WMF;
1186 return CDSC_OK;
1191 dsc_private int
1192 dsc_parse_pages(CDSC *dsc)
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;
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;
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;
1239 else if (COMPARE(p, "(atend)")) {
1240 /* do nothing */
1241 /* we should mark it as deferred */
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;
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;
1279 return CDSC_OK;
1282 dsc_private int
1283 dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
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;
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;
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;
1323 if (*pbbox != NULL) {
1324 dsc_memfree(dsc, *pbbox);
1325 *pbbox = NULL;
1328 /* should only process first %%BoundingBox: */
1330 while (IS_WHITE(dsc->line[offset]))
1331 offset++;
1332 p = dsc->line + offset;
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;
1349 else if (COMPARE(p, "(atend)")) {
1350 /* do nothing */
1351 /* we should mark it as deferred */
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;
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 (*pbbox)->llx = (int)fllx;
1398 (*pbbox)->lly = (int)flly;
1399 (*pbbox)->urx = (int)(furx+0.999);
1400 (*pbbox)->ury = (int)(fury+0.999);
1402 return CDSC_OK;
1403 case CDSC_RESPONSE_CANCEL:
1404 return CDSC_OK;
1405 case CDSC_RESPONSE_IGNORE_ALL:
1406 return CDSC_NOTDSC;
1410 return CDSC_OK;
1413 dsc_private int
1414 dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
1416 unsigned int i, n;
1417 float fllx, flly, furx, fury;
1418 char *p;
1419 /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1420 * and last in trailer.
1422 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1423 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1424 dsc->line_length);
1425 switch (rc) {
1426 case CDSC_RESPONSE_OK:
1427 case CDSC_RESPONSE_CANCEL:
1428 return CDSC_OK; /* ignore duplicate comments in header */
1429 case CDSC_RESPONSE_IGNORE_ALL:
1430 return CDSC_NOTDSC;
1433 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1434 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1435 dsc->line_length);
1436 switch (rc) {
1437 case CDSC_RESPONSE_OK:
1438 case CDSC_RESPONSE_CANCEL:
1439 return CDSC_OK; /* ignore duplicate comments in header */
1440 case CDSC_RESPONSE_IGNORE_ALL:
1441 return CDSC_NOTDSC;
1444 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1445 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1446 dsc->line_length);
1447 switch (rc) {
1448 case CDSC_RESPONSE_OK:
1449 case CDSC_RESPONSE_CANCEL:
1450 break; /* use duplicate comments in trailer */
1451 case CDSC_RESPONSE_IGNORE_ALL:
1452 return CDSC_NOTDSC;
1455 if (*pbbox != NULL) {
1456 dsc_memfree(dsc, *pbbox);
1457 *pbbox = NULL;
1460 /* should only process first %%BoundingBox: */
1462 while (IS_WHITE(dsc->line[offset]))
1463 offset++;
1464 p = dsc->line + offset;
1466 if (COMPARE(p, "atend")) {
1467 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1468 dsc->line_length);
1469 switch (rc) {
1470 case CDSC_RESPONSE_OK:
1471 /* assume (atend) */
1472 /* we should mark it as deferred */
1473 break;
1474 case CDSC_RESPONSE_CANCEL:
1475 /* ignore it */
1476 break;
1477 case CDSC_RESPONSE_IGNORE_ALL:
1478 return CDSC_NOTDSC;
1481 else if (COMPARE(p, "(atend)")) {
1482 /* do nothing */
1483 /* we should mark it as deferred */
1485 else {
1486 /* fllx = */ flly = furx = fury = 0.0;
1487 n = offset;
1488 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1489 n += i;
1490 if (i)
1491 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1492 n += i;
1493 if (i)
1494 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1495 n += i;
1496 if (i)
1497 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1498 if (i) {
1499 *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
1500 if (*pbbox == NULL)
1501 return CDSC_ERROR; /* no memory */
1502 (*pbbox)->fllx = fllx;
1503 (*pbbox)->flly = flly;
1504 (*pbbox)->furx = furx;
1505 (*pbbox)->fury = fury;
1508 return CDSC_OK;
1511 dsc_private int
1512 dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
1514 char *p;
1515 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1516 (dsc->scan_section == scan_comments)) {
1517 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1518 dsc->line_length);
1519 switch (rc) {
1520 case CDSC_RESPONSE_OK:
1521 case CDSC_RESPONSE_CANCEL:
1522 return CDSC_OK; /* ignore duplicate comments in header */
1523 case CDSC_RESPONSE_IGNORE_ALL:
1524 return CDSC_NOTDSC;
1527 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1528 (dsc->scan_section == scan_trailer)) {
1529 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1530 dsc->line_length);
1531 switch (rc) {
1532 case CDSC_RESPONSE_OK:
1533 case CDSC_RESPONSE_CANCEL:
1534 break; /* use duplicate comments in header; */
1535 case CDSC_RESPONSE_IGNORE_ALL:
1536 return CDSC_NOTDSC;
1539 p = dsc->line + offset;
1540 while (IS_WHITE(*p))
1541 p++;
1542 if (COMPARE(p, "atend")) {
1543 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
1544 switch (rc) {
1545 case CDSC_RESPONSE_OK:
1546 /* assume (atend) */
1547 /* we should mark it as deferred */
1548 break;
1549 case CDSC_RESPONSE_CANCEL:
1550 /* ignore it */
1551 break;
1552 case CDSC_RESPONSE_IGNORE_ALL:
1553 return CDSC_NOTDSC;
1556 else if (COMPARE(p, "(atend)")) {
1557 /* do nothing */
1558 /* we should mark it as deferred */
1560 else if (COMPARE(p, "Portrait")) {
1561 *porientation = CDSC_PORTRAIT;
1563 else if (COMPARE(p, "Landscape")) {
1564 *porientation = CDSC_LANDSCAPE;
1566 else {
1567 dsc_unknown(dsc);
1569 return CDSC_OK;
1572 dsc_private int
1573 dsc_parse_order(CDSC *dsc)
1575 char *p;
1576 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1577 (dsc->scan_section == scan_comments)) {
1578 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1579 dsc->line_length);
1580 switch (rc) {
1581 case CDSC_RESPONSE_OK:
1582 case CDSC_RESPONSE_CANCEL:
1583 return CDSC_OK; /* ignore duplicate comments in header */
1584 case CDSC_RESPONSE_IGNORE_ALL:
1585 return CDSC_NOTDSC;
1588 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1589 (dsc->scan_section == scan_trailer)) {
1590 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1591 dsc->line_length);
1592 switch (rc) {
1593 case CDSC_RESPONSE_OK:
1594 case CDSC_RESPONSE_CANCEL:
1595 break; /* use duplicate comments in trailer */
1596 case CDSC_RESPONSE_IGNORE_ALL:
1597 return CDSC_NOTDSC;
1601 p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13);
1602 while (IS_WHITE(*p))
1603 p++;
1604 if (COMPARE(p, "atend")) {
1605 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1606 dsc->line_length);
1607 switch (rc) {
1608 case CDSC_RESPONSE_OK:
1609 /* assume (atend) */
1610 /* we should mark it as deferred */
1611 break;
1612 case CDSC_RESPONSE_CANCEL:
1613 /* ignore it */
1614 break;
1615 case CDSC_RESPONSE_IGNORE_ALL:
1616 return CDSC_NOTDSC;
1619 else if (COMPARE(p, "(atend)")) {
1620 /* do nothing */
1621 /* we should mark it as deferred */
1623 else if (COMPARE(p, "Ascend")) {
1624 dsc->page_order = CDSC_ASCEND;
1626 else if (COMPARE(p, "Descend")) {
1627 dsc->page_order = CDSC_DESCEND;
1629 else if (COMPARE(p, "Special")) {
1630 dsc->page_order = CDSC_SPECIAL;
1632 else {
1633 dsc_unknown(dsc);
1635 return CDSC_OK;
1639 dsc_private int
1640 dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media)
1642 char media_name[MAXSTR];
1643 int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */
1644 unsigned int i;
1646 if (dsc_copy_string(media_name, sizeof(media_name)-1,
1647 dsc->line+n, dsc->line_length-n, NULL)) {
1648 for (i=0; i<dsc->media_count; i++) {
1649 if (dsc->media[i]->name &&
1650 (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) {
1651 *page_media = dsc->media[i];
1652 return CDSC_OK;
1656 dsc_unknown(dsc);
1658 return CDSC_OK;
1662 dsc_private int
1663 dsc_parse_document_media(CDSC *dsc)
1665 unsigned int i, n;
1666 CDSCMEDIA lmedia;
1667 GSBOOL blank_line;
1669 if (IS_DSC(dsc->line, "%%DocumentMedia:"))
1670 n = 16;
1671 else if (IS_DSC(dsc->line, "%%+"))
1672 n = 3;
1673 else
1674 return CDSC_ERROR; /* error */
1676 /* check for blank remainder of line */
1677 blank_line = TRUE;
1678 for (i=n; i<dsc->line_length; i++) {
1679 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
1680 blank_line = FALSE;
1681 break;
1685 if (!blank_line) {
1686 char name[MAXSTR];
1687 char colour[MAXSTR];
1688 char type[MAXSTR];
1689 lmedia.name = lmedia.colour = lmedia.type = (char *)NULL;
1690 lmedia.width = lmedia.height = lmedia.weight = 0;
1691 lmedia.mediabox = (CDSCBBOX *)NULL;
1692 lmedia.name = dsc_copy_string(name, sizeof(name)-1,
1693 dsc->line+n, dsc->line_length-n, &i);
1694 n+=i;
1695 if (i)
1696 lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1697 n+=i;
1698 if (i)
1699 lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1700 n+=i;
1701 if (i)
1702 lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1703 n+=i;
1704 if (i)
1705 lmedia.colour = dsc_copy_string(colour, sizeof(colour)-1,
1706 dsc->line+n, dsc->line_length-n, &i);
1707 n+=i;
1708 if (i)
1709 lmedia.type = dsc_copy_string(type, sizeof(type)-1,
1710 dsc->line+n, dsc->line_length-n, &i);
1712 if (i==0)
1713 dsc_unknown(dsc); /* we didn't get all fields */
1714 else {
1715 if (dsc_add_media(dsc, &lmedia))
1716 return CDSC_ERROR; /* out of memory */
1719 return CDSC_OK;
1722 /* viewing orientation is believed to be the first four elements of
1723 * a CTM matrix
1725 dsc_private int
1726 dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm)
1728 CDSCCTM ctm;
1729 unsigned int i, n;
1731 if (*pctm != NULL) {
1732 dsc_memfree(dsc, *pctm);
1733 *pctm = NULL;
1736 n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
1737 while (IS_WHITE(dsc->line[n]))
1738 n++;
1740 /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0;
1741 ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1742 n += i;
1743 if (i)
1744 ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1745 n += i;
1746 if (i)
1747 ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1748 n += i;
1749 if (i)
1750 ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1751 if (i==0) {
1752 dsc_unknown(dsc); /* we didn't get all fields */
1754 else {
1755 *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM));
1756 if (*pctm == NULL)
1757 return CDSC_ERROR; /* no memory */
1758 **pctm = ctm;
1760 return CDSC_OK;
1764 /* This is called before dsc_read_line(), since we may
1765 * need to skip a binary header which contains a new line
1766 * character
1768 dsc_private int
1769 dsc_scan_type(CDSC *dsc)
1771 unsigned char *p;
1772 unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
1773 int length = dsc->data_length - dsc->data_index;
1775 /* Types that should be known:
1776 * DSC
1777 * EPSF
1778 * PJL + any of above
1779 * ^D + any of above
1780 * DOS EPS
1781 * PDF
1782 * non-DSC
1785 /* First process any non PostScript headers */
1786 /* At this stage we do not have a complete line */
1788 if (length == 0)
1789 return CDSC_NEEDMORE;
1791 if (dsc->skip_pjl) {
1792 /* skip until first PostScript comment */
1793 while (length >= 2) {
1794 while (length && !IS_EOL(line[0])) {
1795 /* skip until EOL character */
1796 line++;
1797 dsc->data_index++;
1798 length--;
1800 while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) {
1801 /* skip until EOL followed by non-EOL */
1802 line++;
1803 dsc->data_index++;
1804 length--;
1806 if (length < 2)
1807 return CDSC_NEEDMORE;
1809 if (IS_EOL(line[0]) && line[1]=='%') {
1810 line++;
1811 dsc->data_index++;
1812 length--;
1813 dsc->skip_pjl = FALSE;
1814 break;
1816 else {
1817 /* line++; */
1818 dsc->data_index++;
1819 /* length--; */
1820 return CDSC_NEEDMORE;
1823 if (dsc->skip_pjl)
1824 return CDSC_NEEDMORE;
1827 if (length == 0)
1828 return CDSC_NEEDMORE;
1830 if (line[0] == '\004') {
1831 line++;
1832 dsc->data_index++;
1833 length--;
1834 dsc->ctrld = TRUE;
1837 if (line[0] == '\033') {
1838 /* possibly PJL */
1839 if (length < 9)
1840 return CDSC_NEEDMORE;
1841 if (COMPARE(line, "\033%-12345X")) {
1842 dsc->skip_pjl = TRUE; /* skip until first PostScript comment */
1843 dsc->pjl = TRUE;
1844 dsc->data_index += 9;
1845 return dsc_scan_type(dsc);
1849 if ((line[0]==0xc5) && (length < 4))
1850 return CDSC_NEEDMORE;
1851 if ((line[0]==0xc5) && (line[1]==0xd0) &&
1852 (line[2]==0xd3) && (line[3]==0xc6) ) {
1853 /* id is "EPSF" with bit 7 set */
1854 /* read DOS EPS header, then ignore all bytes until the PS section */
1855 if (length < 30)
1856 return CDSC_NEEDMORE;
1857 dsc->line = (char *)line;
1858 if (dsc_read_doseps(dsc))
1859 return CDSC_ERROR;
1861 else {
1862 if (length < 2)
1863 return CDSC_NEEDMORE;
1864 if ((line[0] == '%') && (line[1] == 'P')) {
1865 if (length < 5)
1866 return CDSC_NEEDMORE;
1867 if (COMPARE(line, "%PDF-")) {
1868 dsc->pdf = TRUE;
1869 dsc->scan_section = scan_comments;
1870 return CDSC_OK;
1875 /* Finally process PostScript headers */
1877 if (dsc_read_line(dsc) <= 0)
1878 return CDSC_NEEDMORE;
1880 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
1881 if (COMPARE(dsc->line, "%!PS-Adobe")) {
1882 dsc->dsc = TRUE;
1883 dsc->begincomments = DSC_START(dsc);
1884 if (dsc->dsc_version == NULL)
1885 return CDSC_ERROR; /* no memory */
1886 p = (unsigned char *)dsc->line + 14;
1887 while (IS_WHITE(*p))
1888 p++;
1889 if (COMPARE(p, "EPSF-"))
1890 dsc->epsf = TRUE;
1891 dsc->scan_section = scan_comments;
1892 return CDSC_PSADOBE;
1894 if (COMPARE(dsc->line, "%!")) {
1895 dsc->scan_section = scan_comments;
1896 return CDSC_NOTDSC;
1899 dsc->scan_section = scan_comments;
1900 return CDSC_NOTDSC; /* unrecognised */
1905 dsc_private int
1906 dsc_scan_comments(CDSC *dsc)
1908 /* Comments section ends at */
1909 /* %%EndComments */
1910 /* another section */
1911 /* line that does not start with %% */
1912 /* Save a few important lines */
1914 char *line = dsc->line;
1915 GSBOOL continued = FALSE;
1916 dsc->id = CDSC_OK;
1917 if (IS_DSC(line, "%%EndComments")) {
1918 dsc->id = CDSC_ENDCOMMENTS;
1919 dsc->endcomments = DSC_END(dsc);
1920 dsc->scan_section = scan_pre_preview;
1921 return CDSC_OK;
1923 else if (IS_DSC(line, "%%BeginComments")) {
1924 /* ignore because we are in this section */
1925 dsc->id = CDSC_BEGINCOMMENTS;
1927 else if (dsc_is_section(line)) {
1928 dsc->endcomments = DSC_START(dsc);
1929 dsc->scan_section = scan_pre_preview;
1930 return CDSC_PROPAGATE;
1932 else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) {
1933 dsc->endcomments = DSC_START(dsc);
1934 dsc->scan_section = scan_pre_preview;
1935 return CDSC_PROPAGATE;
1937 else if (line[0] != '%') {
1938 dsc->id = CDSC_OK;
1939 dsc->endcomments = DSC_START(dsc);
1940 dsc->scan_section = scan_pre_preview;
1941 return CDSC_PROPAGATE;
1943 else if (IS_DSC(line, "%%Begin")) {
1944 dsc->endcomments = DSC_START(dsc);
1945 dsc->scan_section = scan_pre_preview;
1946 return CDSC_PROPAGATE;
1949 /* Handle continuation lines.
1950 * To simply processing, we assume that contination lines
1951 * will only occur if repeat parameters are allowed and that
1952 * a complete set of these parameters appears on each line.
1953 * This is more restrictive than the DSC specification, but
1954 * is valid for the DSC comments understood by this parser
1955 * for all documents that we have seen.
1957 if (IS_DSC(line, "%%+")) {
1958 line = dsc->last_line;
1959 continued = TRUE;
1961 else
1962 dsc_save_line(dsc);
1964 if (IS_DSC(line, "%%Pages:")) {
1965 dsc->id = CDSC_PAGES;
1966 if (dsc_parse_pages(dsc) != 0)
1967 return CDSC_ERROR;
1969 else if (IS_DSC(line, "%%Creator:")) {
1970 dsc->id = CDSC_CREATOR;
1971 dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10);
1972 if (dsc->dsc_creator==NULL)
1973 return CDSC_ERROR;
1975 else if (IS_DSC(line, "%%CreationDate:")) {
1976 dsc->id = CDSC_CREATIONDATE;
1977 dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15);
1978 if (dsc->dsc_date==NULL)
1979 return CDSC_ERROR;
1981 else if (IS_DSC(line, "%%Title:")) {
1982 dsc->id = CDSC_TITLE;
1983 dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8);
1984 if (dsc->dsc_title==NULL)
1985 return CDSC_ERROR;
1987 else if (IS_DSC(line, "%%For:")) {
1988 dsc->id = CDSC_FOR;
1989 dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6);
1990 if (dsc->dsc_for==NULL)
1991 return CDSC_ERROR;
1993 else if (IS_DSC(line, "%%LanguageLevel:")) {
1994 unsigned int n = continued ? 3 : 16;
1995 unsigned int i;
1996 int ll;
1997 dsc->id = CDSC_LANGUAGELEVEL;
1998 ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1999 if (i) {
2000 if ( (ll==1) || (ll==2) || (ll==3) )
2001 dsc->language_level = ll;
2002 else {
2003 dsc_unknown(dsc);
2006 else
2007 dsc_unknown(dsc);
2009 else if (IS_DSC(line, "%%BoundingBox:")) {
2010 dsc->id = CDSC_BOUNDINGBOX;
2011 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
2012 return CDSC_ERROR;
2014 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
2015 dsc->id = CDSC_HIRESBOUNDINGBOX;
2016 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
2017 continued ? 3 : 19))
2018 return CDSC_ERROR;
2020 else if (IS_DSC(line, "%%CropBox:")) {
2021 dsc->id = CDSC_CROPBOX;
2022 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
2023 continued ? 3 : 10))
2024 return CDSC_ERROR;
2026 else if (IS_DSC(line, "%%Orientation:")) {
2027 dsc->id = CDSC_ORIENTATION;
2028 if (dsc_parse_orientation(dsc, &(dsc->page_orientation),
2029 continued ? 3 : 14))
2030 return CDSC_ERROR;
2032 else if (IS_DSC(line, "%%PageOrder:")) {
2033 dsc->id = CDSC_PAGEORDER;
2034 if (dsc_parse_order(dsc))
2035 return CDSC_ERROR;
2037 else if (IS_DSC(line, "%%DocumentMedia:")) {
2038 dsc->id = CDSC_DOCUMENTMEDIA;
2039 if (dsc_parse_document_media(dsc))
2040 return CDSC_ERROR;
2042 else if (IS_DSC(line, "%%DocumentPaperSizes:")) {
2043 /* DSC 2.1 */
2044 unsigned int n = continued ? 3 : 21;
2045 unsigned int count = 0;
2046 unsigned int i = 1;
2047 char name[MAXSTR];
2048 char *p;
2049 dsc->id = CDSC_DOCUMENTPAPERSIZES;
2050 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2051 p = dsc_copy_string(name, sizeof(name)-1,
2052 dsc->line+n, dsc->line_length-n, &i);
2053 if (i && p) {
2054 const CDSCMEDIA *m = dsc_known_media;
2055 if (count >= dsc->media_count) {
2056 /* set some default values */
2057 CDSCMEDIA lmedia;
2058 lmedia.name = p;
2059 lmedia.width = 595.0;
2060 lmedia.height = 842.0;
2061 lmedia.weight = 80.0;
2062 lmedia.colour = NULL;
2063 lmedia.type = NULL;
2064 lmedia.mediabox = NULL;
2065 if (dsc_add_media(dsc, &lmedia))
2066 return CDSC_ERROR;
2068 else
2069 dsc->media[count]->name =
2070 dsc_alloc_string(dsc, p, strlen(p));
2071 /* find in list of known media */
2072 while (m && m->name) {
2073 if (dsc_stricmp(p, m->name)==0) {
2074 dsc->media[count]->width = m->width;
2075 dsc->media[count]->height = m->height;
2076 break;
2078 m++;
2081 n+=i;
2082 count++;
2085 else if (IS_DSC(line, "%%DocumentPaperForms:")) {
2086 /* DSC 2.1 */
2087 unsigned int n = continued ? 3 : 21;
2088 unsigned int count = 0;
2089 unsigned int i = 1;
2090 char type[MAXSTR];
2091 char *p;
2092 dsc->id = CDSC_DOCUMENTPAPERFORMS;
2093 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2094 p = dsc_copy_string(type, sizeof(type)-1,
2095 dsc->line+n, dsc->line_length-n, &i);
2096 if (i && p) {
2097 if (count >= dsc->media_count) {
2098 /* set some default values */
2099 CDSCMEDIA lmedia;
2100 lmedia.name = NULL;
2101 lmedia.width = 595.0;
2102 lmedia.height = 842.0;
2103 lmedia.weight = 80.0;
2104 lmedia.colour = NULL;
2105 lmedia.type = p;
2106 lmedia.mediabox = NULL;
2107 if (dsc_add_media(dsc, &lmedia))
2108 return CDSC_ERROR;
2110 else
2111 dsc->media[count]->type =
2112 dsc_alloc_string(dsc, p, strlen(p));
2114 n+=i;
2115 count++;
2118 else if (IS_DSC(line, "%%DocumentPaperColors:")) {
2119 /* DSC 2.1 */
2120 unsigned int n = continued ? 3 : 22;
2121 unsigned int count = 0;
2122 unsigned int i = 1;
2123 char colour[MAXSTR];
2124 char *p;
2125 dsc->id = CDSC_DOCUMENTPAPERCOLORS;
2126 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2127 p = dsc_copy_string(colour, sizeof(colour)-1,
2128 dsc->line+n, dsc->line_length-n, &i);
2129 if (i && p) {
2130 if (count >= dsc->media_count) {
2131 /* set some default values */
2132 CDSCMEDIA lmedia;
2133 lmedia.name = NULL;
2134 lmedia.width = 595.0;
2135 lmedia.height = 842.0;
2136 lmedia.weight = 80.0;
2137 lmedia.colour = p;
2138 lmedia.type = NULL;
2139 lmedia.mediabox = NULL;
2140 if (dsc_add_media(dsc, &lmedia))
2141 return CDSC_ERROR;
2143 else
2144 dsc->media[count]->colour =
2145 dsc_alloc_string(dsc, p, strlen(p));
2147 n+=i;
2148 count++;
2151 else if (IS_DSC(line, "%%DocumentPaperWeights:")) {
2152 /* DSC 2.1 */
2153 unsigned int n = continued ? 3 : 23;
2154 unsigned int count = 0;
2155 unsigned int i = 1;
2156 float w;
2157 dsc->id = CDSC_DOCUMENTPAPERWEIGHTS;
2158 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2159 w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2160 if (i) {
2161 if (count >= dsc->media_count) {
2162 /* set some default values */
2163 CDSCMEDIA lmedia;
2164 lmedia.name = NULL;
2165 lmedia.width = 595.0;
2166 lmedia.height = 842.0;
2167 lmedia.weight = w;
2168 lmedia.colour = NULL;
2169 lmedia.type = NULL;
2170 lmedia.mediabox = NULL;
2171 if (dsc_add_media(dsc, &lmedia))
2172 return CDSC_ERROR;
2174 else
2175 dsc->media[count]->weight = w;
2177 n+=i;
2178 count++;
2181 else if (IS_DSC(line, "%%DocumentData:")) {
2182 unsigned int n = continued ? 3 : 15;
2183 char *p = dsc->line + n;
2184 while (IS_WHITE(*p))
2185 p++;
2186 dsc->id = CDSC_DOCUMENTDATA;
2187 if (COMPARE(p, "Clean7Bit"))
2188 dsc->document_data = CDSC_CLEAN7BIT;
2189 else if (COMPARE(p, "Clean8Bit"))
2190 dsc->document_data = CDSC_CLEAN8BIT;
2191 else if (COMPARE(p, "Binary"))
2192 dsc->document_data = CDSC_BINARY;
2193 else
2194 dsc_unknown(dsc);
2196 else if (IS_DSC(line, "%%Requirements:")) {
2197 dsc->id = CDSC_REQUIREMENTS;
2198 /* ignore */
2200 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
2201 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
2202 /* ignore */
2204 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
2205 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
2206 /* ignore */
2208 else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
2209 dsc->id = CDSC_OK;
2210 /* ignore */
2212 else {
2213 dsc->id = CDSC_UNKNOWNDSC;
2214 dsc_unknown(dsc);
2217 dsc->endcomments = DSC_END(dsc);
2218 return CDSC_OK;
2222 dsc_private int
2223 dsc_scan_preview(CDSC *dsc)
2225 /* Preview section ends at */
2226 /* %%EndPreview */
2227 /* another section */
2228 /* Preview section must start with %%BeginPreview */
2229 char *line = dsc->line;
2230 dsc->id = CDSC_OK;
2232 if (dsc->scan_section == scan_pre_preview) {
2233 if (IS_BLANK(line))
2234 return CDSC_OK; /* ignore blank lines before preview */
2235 else if (IS_DSC(line, "%%BeginPreview")) {
2236 dsc->id = CDSC_BEGINPREVIEW;
2237 dsc->beginpreview = DSC_START(dsc);
2238 dsc->endpreview = DSC_END(dsc);
2239 dsc->scan_section = scan_preview;
2240 /* Don't mark the preview as EPSI if a DOS EPS header is present */
2241 if (dsc->preview == CDSC_NOPREVIEW)
2242 dsc->preview = CDSC_EPSI;
2243 return CDSC_OK;
2245 else {
2246 dsc->scan_section = scan_pre_defaults;
2247 return CDSC_PROPAGATE;
2251 if (IS_DSC(line, "%%BeginPreview")) {
2252 /* ignore because we are in this section */
2254 else if (dsc_is_section(line)) {
2255 dsc->endpreview = DSC_START(dsc);
2256 dsc->scan_section = scan_pre_defaults;
2257 return CDSC_PROPAGATE;
2259 else if (IS_DSC(line, "%%EndPreview")) {
2260 dsc->id = CDSC_ENDPREVIEW;
2261 dsc->endpreview = DSC_END(dsc);
2262 dsc->scan_section = scan_pre_defaults;
2263 return CDSC_OK;
2265 else if (line[0] == '%' && line[1] != '%') {
2266 /* Ordinary comments are OK */
2268 else {
2269 dsc->id = CDSC_UNKNOWNDSC;
2270 /* DSC comments should not occur in preview */
2271 dsc_unknown(dsc);
2274 dsc->endpreview = DSC_END(dsc);
2275 return CDSC_OK;
2278 dsc_private int
2279 dsc_scan_defaults(CDSC *dsc)
2281 /* Defaults section ends at */
2282 /* %%EndDefaults */
2283 /* another section */
2284 /* Defaults section must start with %%BeginDefaults */
2285 char *line = dsc->line;
2286 dsc->id = CDSC_OK;
2288 if (dsc->scan_section == scan_pre_defaults) {
2289 if (IS_BLANK(line))
2290 return CDSC_OK; /* ignore blank lines before defaults */
2291 else if (IS_DSC(line, "%%BeginDefaults")) {
2292 dsc->id = CDSC_BEGINDEFAULTS;
2293 dsc->begindefaults = DSC_START(dsc);
2294 dsc->enddefaults = DSC_END(dsc);
2295 dsc->scan_section = scan_defaults;
2296 return CDSC_OK;
2298 else {
2299 dsc->scan_section = scan_pre_prolog;
2300 return CDSC_PROPAGATE;
2304 if (NOT_DSC_LINE(line)) {
2305 /* ignore */
2307 else if (IS_DSC(line, "%%BeginPreview")) {
2308 /* ignore because we have already processed this section */
2310 else if (IS_DSC(line, "%%BeginDefaults")) {
2311 /* ignore because we are in this section */
2313 else if (dsc_is_section(line)) {
2314 dsc->enddefaults = DSC_START(dsc);
2315 dsc->scan_section = scan_pre_prolog;
2316 return CDSC_PROPAGATE;
2318 else if (IS_DSC(line, "%%EndDefaults")) {
2319 dsc->id = CDSC_ENDDEFAULTS;
2320 dsc->enddefaults = DSC_END(dsc);
2321 dsc->scan_section = scan_pre_prolog;
2322 return CDSC_OK;
2324 else if (IS_DSC(line, "%%PageMedia:")) {
2325 dsc->id = CDSC_PAGEMEDIA;
2326 dsc_parse_media(dsc, &dsc->page_media);
2328 else if (IS_DSC(line, "%%PageOrientation:")) {
2329 dsc->id = CDSC_PAGEORIENTATION;
2330 /* This can override %%Orientation: */
2331 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18))
2332 return CDSC_ERROR;
2334 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2335 dsc->id = CDSC_PAGEBOUNDINGBOX;
2336 if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18))
2337 return CDSC_ERROR;
2339 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2340 dsc->id = CDSC_VIEWINGORIENTATION;
2341 if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation))
2342 return CDSC_ERROR;
2344 else {
2345 dsc->id = CDSC_UNKNOWNDSC;
2346 /* All other DSC comments are unknown, but not an error */
2347 dsc_unknown(dsc);
2349 dsc->enddefaults = DSC_END(dsc);
2350 return CDSC_OK;
2353 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
2354 * mismatch (default) */
2355 dsc_private int
2356 dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
2358 if (count != 0) {
2359 char buf[MAXSTR+MAXSTR] = "";
2360 if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) {
2361 strncpy(buf, dsc->line, dsc->line_length);
2362 buf[dsc->line_length] = '\0';
2364 sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
2365 return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, strlen(buf));
2367 return CDSC_RESPONSE_CANCEL;
2370 dsc_private int
2371 dsc_check_match_type(CDSC *dsc, const char *str, int count)
2373 if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
2374 return CDSC_NOTDSC;
2375 return CDSC_OK;
2378 /* complain if Begin/End blocks didn't match */
2379 /* return non-zero if we should ignore all DSC */
2380 dsc_private int
2381 dsc_check_match(CDSC *dsc)
2383 int rc = 0;
2384 const char *font = "Font";
2385 const char *feature = "Feature";
2386 const char *resource = "Resource";
2387 const char *procset = "ProcSet";
2389 if (!rc)
2390 rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
2391 if (!rc)
2392 rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
2393 if (!rc)
2394 rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
2395 if (!rc)
2396 rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
2398 dsc->begin_font_count = 0;
2399 dsc->begin_feature_count = 0;
2400 dsc->begin_resource_count = 0;
2401 dsc->begin_procset_count = 0;
2402 return rc;
2406 dsc_private int
2407 dsc_scan_prolog(CDSC *dsc)
2409 /* Prolog section ends at */
2410 /* %%EndProlog */
2411 /* another section */
2412 /* Prolog section may start with %%BeginProlog or non-dsc line */
2413 char *line = dsc->line;
2414 dsc->id = CDSC_OK;
2416 if (dsc->scan_section == scan_pre_prolog) {
2417 if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
2418 dsc->scan_section = scan_pre_setup;
2419 return CDSC_PROPAGATE;
2421 dsc->id = CDSC_BEGINPROLOG;
2422 dsc->beginprolog = DSC_START(dsc);
2423 dsc->endprolog = DSC_END(dsc);
2424 dsc->scan_section = scan_prolog;
2425 if (IS_DSC(line, "%%BeginProlog"))
2426 return CDSC_OK;
2429 if (NOT_DSC_LINE(line)) {
2430 /* ignore */
2432 else if (IS_DSC(line, "%%BeginPreview")) {
2433 /* ignore because we have already processed this section */
2435 else if (IS_DSC(line, "%%BeginDefaults")) {
2436 /* ignore because we have already processed this section */
2438 else if (IS_DSC(line, "%%BeginProlog")) {
2439 /* ignore because we are in this section */
2441 else if (dsc_is_section(line)) {
2442 dsc->endprolog = DSC_START(dsc);
2443 dsc->scan_section = scan_pre_setup;
2444 if (dsc_check_match(dsc))
2445 return CDSC_NOTDSC;
2446 return CDSC_PROPAGATE;
2448 else if (IS_DSC(line, "%%EndProlog")) {
2449 dsc->id = CDSC_ENDPROLOG;
2450 dsc->endprolog = DSC_END(dsc);
2451 dsc->scan_section = scan_pre_setup;
2452 if (dsc_check_match(dsc))
2453 return CDSC_NOTDSC;
2454 return CDSC_OK;
2456 else if (IS_DSC(line, "%%BeginFont:")) {
2457 dsc->id = CDSC_BEGINFONT;
2458 /* ignore Begin/EndFont, apart form making sure */
2459 /* that they are matched. */
2460 dsc->begin_font_count++;
2462 else if (IS_DSC(line, "%%EndFont")) {
2463 dsc->id = CDSC_ENDFONT;
2464 dsc->begin_font_count--;
2466 else if (IS_DSC(line, "%%BeginFeature:")) {
2467 dsc->id = CDSC_BEGINFEATURE;
2468 /* ignore Begin/EndFeature, apart form making sure */
2469 /* that they are matched. */
2470 dsc->begin_feature_count++;
2472 else if (IS_DSC(line, "%%EndFeature")) {
2473 dsc->id = CDSC_ENDFEATURE;
2474 dsc->begin_feature_count--;
2476 else if (IS_DSC(line, "%%BeginResource:")) {
2477 dsc->id = CDSC_BEGINRESOURCE;
2478 /* ignore Begin/EndResource, apart form making sure */
2479 /* that they are matched. */
2480 dsc->begin_resource_count++;
2482 else if (IS_DSC(line, "%%EndResource")) {
2483 dsc->id = CDSC_ENDRESOURCE;
2484 dsc->begin_resource_count--;
2486 else if (IS_DSC(line, "%%BeginProcSet:")) {
2487 dsc->id = CDSC_BEGINPROCSET;
2488 /* ignore Begin/EndProcSet, apart form making sure */
2489 /* that they are matched. */
2490 dsc->begin_procset_count++;
2492 else if (IS_DSC(line, "%%EndProcSet")) {
2493 dsc->id = CDSC_ENDPROCSET;
2494 dsc->begin_procset_count--;
2496 else {
2497 /* All other DSC comments are unknown, but not an error */
2498 dsc->id = CDSC_UNKNOWNDSC;
2499 dsc_unknown(dsc);
2502 dsc->endprolog = DSC_END(dsc);
2503 return CDSC_OK;
2506 dsc_private int
2507 dsc_scan_setup(CDSC *dsc)
2509 /* Setup section ends at */
2510 /* %%EndSetup */
2511 /* another section */
2512 /* Setup section must start with %%BeginSetup */
2514 char *line = dsc->line;
2515 dsc->id = CDSC_OK;
2517 if (dsc->scan_section == scan_pre_setup) {
2518 if (IS_BLANK(line))
2519 return CDSC_OK; /* ignore blank lines before setup */
2520 else if (IS_DSC(line, "%%BeginSetup")) {
2521 dsc->id = CDSC_BEGINSETUP;
2522 dsc->beginsetup = DSC_START(dsc);
2523 dsc->endsetup = DSC_END(dsc);
2524 dsc->scan_section = scan_setup;
2525 return CDSC_OK;
2527 else {
2528 dsc->scan_section = scan_pre_pages;
2529 return CDSC_PROPAGATE;
2533 if (NOT_DSC_LINE(line)) {
2534 /* ignore */
2536 else if (IS_DSC(line, "%%BeginPreview")) {
2537 /* ignore because we have already processed this section */
2539 else if (IS_DSC(line, "%%BeginDefaults")) {
2540 /* ignore because we have already processed this section */
2542 else if (IS_DSC(line, "%%BeginProlog")) {
2543 /* ignore because we have already processed this section */
2545 else if (IS_DSC(line, "%%BeginSetup")) {
2546 /* ignore because we are in this section */
2548 else if (dsc_is_section(line)) {
2549 dsc->endsetup = DSC_START(dsc);
2550 dsc->scan_section = scan_pre_pages;
2551 if (dsc_check_match(dsc))
2552 return CDSC_NOTDSC;
2553 return CDSC_PROPAGATE;
2555 else if (IS_DSC(line, "%%EndSetup")) {
2556 dsc->id = CDSC_ENDSETUP;
2557 dsc->endsetup = DSC_END(dsc);
2558 dsc->scan_section = scan_pre_pages;
2559 if (dsc_check_match(dsc))
2560 return CDSC_NOTDSC;
2561 return CDSC_OK;
2563 else if (IS_DSC(line, "%%BeginFeature:")) {
2564 dsc->id = CDSC_BEGINFEATURE;
2565 /* ignore Begin/EndFeature, apart form making sure */
2566 /* that they are matched. */
2567 dsc->begin_feature_count++;
2569 else if (IS_DSC(line, "%%EndFeature")) {
2570 dsc->id = CDSC_ENDFEATURE;
2571 dsc->begin_feature_count--;
2573 else if (IS_DSC(line, "%%Feature:")) {
2574 dsc->id = CDSC_FEATURE;
2575 /* ignore */
2577 else if (IS_DSC(line, "%%BeginResource:")) {
2578 dsc->id = CDSC_BEGINRESOURCE;
2579 /* ignore Begin/EndResource, apart form making sure */
2580 /* that they are matched. */
2581 dsc->begin_resource_count++;
2583 else if (IS_DSC(line, "%%EndResource")) {
2584 dsc->id = CDSC_ENDRESOURCE;
2585 dsc->begin_resource_count--;
2587 else if (IS_DSC(line, "%%PaperColor:")) {
2588 dsc->id = CDSC_PAPERCOLOR;
2589 /* ignore */
2591 else if (IS_DSC(line, "%%PaperForm:")) {
2592 dsc->id = CDSC_PAPERFORM;
2593 /* ignore */
2595 else if (IS_DSC(line, "%%PaperWeight:")) {
2596 dsc->id = CDSC_PAPERWEIGHT;
2597 /* ignore */
2599 else if (IS_DSC(line, "%%PaperSize:")) {
2600 /* DSC 2.1 */
2601 GSBOOL found_media = FALSE;
2602 int i;
2603 int n = 12;
2604 char buf[MAXSTR];
2605 buf[0] = '\0';
2606 dsc->id = CDSC_PAPERSIZE;
2607 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n,
2608 NULL);
2609 for (i=0; i<(int)dsc->media_count; i++) {
2610 if (dsc->media[i] && dsc->media[i]->name &&
2611 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2612 dsc->page_media = dsc->media[i];
2613 found_media = TRUE;
2614 break;
2617 if (!found_media) {
2618 /* It didn't match %%DocumentPaperSizes: */
2619 /* Try our known media */
2620 const CDSCMEDIA *m = dsc_known_media;
2621 while (m->name) {
2622 if (dsc_stricmp(buf, m->name)==0) {
2623 dsc->page_media = m;
2624 break;
2626 m++;
2628 if (m->name == NULL)
2629 dsc_unknown(dsc);
2632 else {
2633 /* All other DSC comments are unknown, but not an error */
2634 dsc->id = CDSC_UNKNOWNDSC;
2635 dsc_unknown(dsc);
2638 dsc->endsetup = DSC_END(dsc);
2639 return CDSC_OK;
2642 dsc_private int
2643 dsc_scan_page(CDSC *dsc)
2645 /* Page section ends at */
2646 /* %%Page */
2647 /* %%Trailer */
2648 /* %%EOF */
2649 char *line = dsc->line;
2650 dsc->id = CDSC_OK;
2652 if (dsc->scan_section == scan_pre_pages) {
2653 if (IS_DSC(line, "%%Page:")) {
2654 dsc->scan_section = scan_pages;
2655 /* fall through */
2657 else {
2658 /* %%Page: didn't follow %%EndSetup
2659 * Keep reading until reach %%Page or %%Trailer
2660 * and add it to previous section.
2662 unsigned long *last;
2663 if (dsc->endsetup != 0)
2664 last = &dsc->endsetup;
2665 else if (dsc->endprolog != 0)
2666 last = &dsc->endprolog;
2667 else if (dsc->enddefaults != 0)
2668 last = &dsc->enddefaults;
2669 else if (dsc->endpreview != 0)
2670 last = &dsc->endpreview;
2671 else if (dsc->endcomments != 0)
2672 last = &dsc->endcomments;
2673 else
2674 last = &dsc->begincomments;
2675 *last = DSC_START(dsc);
2676 if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
2677 dsc->scan_section = scan_pre_trailer;
2678 return CDSC_PROPAGATE;
2680 return CDSC_OK;
2684 if (NOT_DSC_LINE(line)) {
2685 /* ignore */
2687 else if (IS_DSC(line, "%%Page:")) {
2688 dsc->id = CDSC_PAGE;
2689 if (dsc->page_count) {
2690 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
2691 if (dsc_check_match(dsc))
2692 return CDSC_NOTDSC;
2695 if (dsc_parse_page(dsc) != 0)
2696 return CDSC_ERROR;
2698 return CDSC_OK;
2700 else if (IS_DSC(line, "%%BeginPreview")) {
2701 /* ignore because we have already processed this section */
2703 else if (IS_DSC(line, "%%BeginDefaults")) {
2704 /* ignore because we have already processed this section */
2706 else if (IS_DSC(line, "%%BeginProlog")) {
2707 /* ignore because we have already processed this section */
2709 else if (IS_DSC(line, "%%BeginSetup")) {
2710 /* ignore because we have already processed this section */
2712 else if (dsc_is_section(line)) {
2713 if (IS_DSC(line, "%%Trailer")) {
2714 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
2715 if (dsc->file_length) {
2716 if ((!dsc->doseps &&
2717 ((DSC_END(dsc) + 32768) < dsc->file_length)) ||
2718 ((dsc->doseps) &&
2719 ((DSC_END(dsc) + 32768) < dsc->doseps_end))) {
2720 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER,
2721 dsc->line, dsc->line_length);
2722 switch (rc) {
2723 case CDSC_RESPONSE_OK:
2724 /* ignore early trailer */
2725 break;
2726 case CDSC_RESPONSE_CANCEL:
2727 /* this is the trailer */
2728 dsc->scan_section = scan_pre_trailer;
2729 if (dsc_check_match(dsc))
2730 return CDSC_NOTDSC;
2731 return CDSC_PROPAGATE;
2732 case CDSC_RESPONSE_IGNORE_ALL:
2733 return CDSC_NOTDSC;
2736 else {
2737 dsc->scan_section = scan_pre_trailer;
2738 if (dsc_check_match(dsc))
2739 return CDSC_NOTDSC;
2740 return CDSC_PROPAGATE;
2743 else {
2744 dsc->scan_section = scan_pre_trailer;
2745 if (dsc_check_match(dsc))
2746 return CDSC_NOTDSC;
2747 return CDSC_PROPAGATE;
2750 else if (IS_DSC(line, "%%EOF")) {
2751 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
2752 if (dsc->file_length) {
2753 if ((DSC_END(dsc)+100 < dsc->file_length) ||
2754 (dsc->doseps && (DSC_END(dsc) + 100 < dsc->doseps_end))) {
2755 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF,
2756 dsc->line, dsc->line_length);
2757 switch (rc) {
2758 case CDSC_RESPONSE_OK:
2759 /* %%EOF is wrong, ignore it */
2760 break;
2761 case CDSC_RESPONSE_CANCEL:
2762 /* %%EOF is correct */
2763 dsc->scan_section = scan_eof;
2764 dsc->eof = TRUE;
2765 if (dsc_check_match(dsc))
2766 return CDSC_NOTDSC;
2767 return CDSC_PROPAGATE;
2768 case CDSC_RESPONSE_IGNORE_ALL:
2769 return CDSC_NOTDSC;
2773 else {
2774 /* ignore it */
2775 if (dsc_check_match(dsc))
2776 return CDSC_NOTDSC;
2777 return CDSC_OK;
2780 else {
2781 /* Section comment, probably from a badly */
2782 /* encapsulated EPS file. */
2783 int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION,
2784 dsc->line, dsc->line_length);
2785 if (rc == CDSC_RESPONSE_IGNORE_ALL)
2786 return CDSC_NOTDSC;
2789 else if (IS_DSC(line, "%%PageTrailer")) {
2790 dsc->id = CDSC_PAGETRAILER;
2791 /* ignore */
2793 else if (IS_DSC(line, "%%BeginPageSetup")) {
2794 dsc->id = CDSC_BEGINPAGESETUP;
2795 /* ignore */
2797 else if (IS_DSC(line, "%%EndPageSetup")) {
2798 dsc->id = CDSC_ENDPAGESETUP;
2799 /* ignore */
2801 else if (IS_DSC(line, "%%PageMedia:")) {
2802 dsc->id = CDSC_PAGEMEDIA;
2803 dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media));
2805 else if (IS_DSC(line, "%%PaperColor:")) {
2806 dsc->id = CDSC_PAPERCOLOR;
2807 /* ignore */
2809 else if (IS_DSC(line, "%%PaperForm:")) {
2810 dsc->id = CDSC_PAPERFORM;
2811 /* ignore */
2813 else if (IS_DSC(line, "%%PaperWeight:")) {
2814 dsc->id = CDSC_PAPERWEIGHT;
2815 /* ignore */
2817 else if (IS_DSC(line, "%%PaperSize:")) {
2818 /* DSC 2.1 */
2819 GSBOOL found_media = FALSE;
2820 int i;
2821 int n = 12;
2822 char buf[MAXSTR];
2823 buf[0] = '\0';
2824 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n,
2825 dsc->line_length-n, NULL);
2826 for (i=0; i<(int)dsc->media_count; i++) {
2827 if (dsc->media[i] && dsc->media[i]->name &&
2828 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2829 dsc->page_media = dsc->media[i];
2830 found_media = TRUE;
2831 break;
2834 if (!found_media) {
2835 /* It didn't match %%DocumentPaperSizes: */
2836 /* Try our known media */
2837 const CDSCMEDIA *m = dsc_known_media;
2838 while (m->name) {
2839 if (dsc_stricmp(buf, m->name)==0) {
2840 dsc->page[dsc->page_count-1].media = m;
2841 break;
2843 m++;
2845 if (m->name == NULL)
2846 dsc_unknown(dsc);
2849 else if (IS_DSC(line, "%%PageOrientation:")) {
2850 dsc->id = CDSC_PAGEORIENTATION;
2851 if (dsc_parse_orientation(dsc,
2852 &(dsc->page[dsc->page_count-1].orientation) ,18))
2853 return CDSC_NOTDSC;
2855 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2856 dsc->id = CDSC_PAGEBOUNDINGBOX;
2857 if (dsc_parse_bounding_box(dsc, &dsc->page[dsc->page_count-1].bbox, 18))
2858 return CDSC_NOTDSC;
2860 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2861 dsc->id = CDSC_VIEWINGORIENTATION;
2862 if (dsc_parse_viewing_orientation(dsc,
2863 &dsc->page[dsc->page_count-1].viewing_orientation))
2864 return CDSC_ERROR;
2866 else if (IS_DSC(line, "%%BeginFont:")) {
2867 dsc->id = CDSC_BEGINFONT;
2868 /* ignore Begin/EndFont, apart form making sure */
2869 /* that they are matched. */
2870 dsc->begin_font_count++;
2872 else if (IS_DSC(line, "%%EndFont")) {
2873 dsc->id = CDSC_BEGINFONT;
2874 dsc->begin_font_count--;
2876 else if (IS_DSC(line, "%%BeginFeature:")) {
2877 dsc->id = CDSC_BEGINFEATURE;
2878 /* ignore Begin/EndFeature, apart form making sure */
2879 /* that they are matched. */
2880 dsc->begin_feature_count++;
2882 else if (IS_DSC(line, "%%EndFeature")) {
2883 dsc->id = CDSC_ENDFEATURE;
2884 dsc->begin_feature_count--;
2886 else if (IS_DSC(line, "%%BeginResource:")) {
2887 dsc->id = CDSC_BEGINRESOURCE;
2888 /* ignore Begin/EndResource, apart form making sure */
2889 /* that they are matched. */
2890 dsc->begin_resource_count++;
2892 else if (IS_DSC(line, "%%EndResource")) {
2893 dsc->id = CDSC_ENDRESOURCE;
2894 dsc->begin_resource_count--;
2896 else if (IS_DSC(line, "%%BeginProcSet:")) {
2897 dsc->id = CDSC_BEGINPROCSET;
2898 /* ignore Begin/EndProcSet, apart form making sure */
2899 /* that they are matched. */
2900 dsc->begin_procset_count++;
2902 else if (IS_DSC(line, "%%EndProcSet")) {
2903 dsc->id = CDSC_ENDPROCSET;
2904 dsc->begin_procset_count--;
2906 else if (IS_DSC(line, "%%IncludeFont:")) {
2907 dsc->id = CDSC_INCLUDEFONT;
2908 /* ignore */
2910 else {
2911 /* All other DSC comments are unknown, but not an error */
2912 dsc->id = CDSC_UNKNOWNDSC;
2913 dsc_unknown(dsc);
2916 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
2917 return CDSC_OK;
2920 /* Valid Trailer comments are
2921 * %%Trailer
2922 * %%EOF
2923 * or the following deferred with (atend)
2924 * %%BoundingBox:
2925 * %%DocumentCustomColors:
2926 * %%DocumentFiles:
2927 * %%DocumentFonts:
2928 * %%DocumentNeededFiles:
2929 * %%DocumentNeededFonts:
2930 * %%DocumentNeededProcSets:
2931 * %%DocumentNeededResources:
2932 * %%DocumentProcSets:
2933 * %%DocumentProcessColors:
2934 * %%DocumentSuppliedFiles:
2935 * %%DocumentSuppliedFonts:
2936 * %%DocumentSuppliedProcSets:
2937 * %%DocumentSuppliedResources:
2938 * %%Orientation:
2939 * %%Pages:
2940 * %%PageOrder:
2942 * Our supported subset is
2943 * %%Trailer
2944 * %%EOF
2945 * %%BoundingBox:
2946 * %%Orientation:
2947 * %%Pages:
2948 * %%PageOrder:
2949 * In addition to these, we support
2950 * %%DocumentMedia:
2952 * A %%PageTrailer can have the following:
2953 * %%PageBoundingBox:
2954 * %%PageCustomColors:
2955 * %%PageFiles:
2956 * %%PageFonts:
2957 * %%PageOrientation:
2958 * %%PageProcessColors:
2959 * %%PageResources:
2962 dsc_private int
2963 dsc_scan_trailer(CDSC *dsc)
2965 /* Trailer section start at */
2966 /* %%Trailer */
2967 /* and ends at */
2968 /* %%EOF */
2969 char *line = dsc->line;
2970 GSBOOL continued = FALSE;
2971 dsc->id = CDSC_OK;
2973 if (dsc->scan_section == scan_pre_trailer) {
2974 if (IS_DSC(line, "%%Trailer")) {
2975 dsc->id = CDSC_TRAILER;
2976 dsc->begintrailer = DSC_START(dsc);
2977 dsc->endtrailer = DSC_END(dsc);
2978 dsc->scan_section = scan_trailer;
2979 return CDSC_OK;
2981 else if (IS_DSC(line, "%%EOF")) {
2982 dsc->id = CDSC_EOF;
2983 dsc->begintrailer = DSC_START(dsc);
2984 dsc->endtrailer = DSC_END(dsc);
2985 dsc->scan_section = scan_trailer;
2986 /* Continue, in case we found %%EOF in an embedded document */
2987 return CDSC_OK;
2989 else {
2990 /* %%Page: didn't follow %%EndSetup
2991 * Keep reading until reach %%Page or %%Trailer
2992 * and add it to setup section
2994 /* append to previous section */
2995 if (dsc->beginsetup)
2996 dsc->endsetup = DSC_END(dsc);
2997 else if (dsc->beginprolog)
2998 dsc->endprolog = DSC_END(dsc);
2999 else {
3000 /* horribly confused */
3002 return CDSC_OK;
3006 /* Handle continuation lines.
3007 * See comment above about our restrictive processing of
3008 * continuation lines
3010 if (IS_DSC(line, "%%+")) {
3011 line = dsc->last_line;
3012 continued = TRUE;
3014 else
3015 dsc_save_line(dsc);
3017 if (NOT_DSC_LINE(line)) {
3018 /* ignore */
3020 else if (IS_DSC(dsc->line, "%%EOF")) {
3021 /* Keep scanning, in case we have a false trailer */
3022 dsc->id = CDSC_EOF;
3024 else if (IS_DSC(dsc->line, "%%Trailer")) {
3025 /* Cope with no pages with code after setup and before trailer. */
3026 /* Last trailer is the correct one. */
3027 dsc->id = CDSC_TRAILER;
3028 dsc->begintrailer = DSC_START(dsc);
3030 else if (IS_DSC(line, "%%Pages:")) {
3031 dsc->id = CDSC_PAGES;
3032 if (dsc_parse_pages(dsc) != 0)
3033 return CDSC_ERROR;
3035 else if (IS_DSC(line, "%%BoundingBox:")) {
3036 dsc->id = CDSC_BOUNDINGBOX;
3037 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
3038 return CDSC_ERROR;
3040 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
3041 dsc->id = CDSC_HIRESBOUNDINGBOX;
3042 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
3043 continued ? 3 : 19))
3044 return CDSC_ERROR;
3046 else if (IS_DSC(line, "%%CropBox:")) {
3047 dsc->id = CDSC_CROPBOX;
3048 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
3049 continued ? 3 : 10))
3050 return CDSC_ERROR;
3052 else if (IS_DSC(line, "%%Orientation:")) {
3053 dsc->id = CDSC_ORIENTATION;
3054 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14))
3055 return CDSC_ERROR;
3057 else if (IS_DSC(line, "%%PageOrder:")) {
3058 dsc->id = CDSC_PAGEORDER;
3059 if (dsc_parse_order(dsc))
3060 return CDSC_ERROR;
3062 else if (IS_DSC(line, "%%DocumentMedia:")) {
3063 dsc->id = CDSC_DOCUMENTMEDIA;
3064 if (dsc_parse_document_media(dsc))
3065 return CDSC_ERROR;
3067 else if (IS_DSC(dsc->line, "%%Page:")) {
3068 /* This should not occur in the trailer, but we might see
3069 * this if a document has been incorrectly embedded.
3071 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER,
3072 dsc->line, dsc->line_length);
3073 switch (rc) {
3074 case CDSC_RESPONSE_OK:
3075 /* Assume that we are really in the previous */
3076 /* page, not the trailer */
3077 dsc->scan_section = scan_pre_pages;
3078 if (dsc->page_count)
3079 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3080 return CDSC_PROPAGATE; /* try again */
3081 case CDSC_RESPONSE_CANCEL:
3082 /* ignore pages in trailer */
3083 break;
3084 case CDSC_RESPONSE_IGNORE_ALL:
3085 return CDSC_NOTDSC;
3088 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
3089 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
3090 /* ignore */
3092 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
3093 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
3094 /* ignore */
3096 else {
3097 /* All other DSC comments are unknown, but not an error */
3098 dsc->id = CDSC_UNKNOWNDSC;
3099 dsc_unknown(dsc);
3102 dsc->endtrailer = DSC_END(dsc);
3103 return CDSC_OK;
3107 dsc_private char *
3108 dsc_alloc_string(CDSC *dsc, const char *str, int len)
3110 char *p;
3111 if (dsc->string_head == NULL) {
3112 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3113 if (dsc->string_head == NULL)
3114 return NULL; /* no memory */
3115 dsc->string = dsc->string_head;
3116 dsc->string->next = NULL;
3117 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3118 if (dsc->string->data == NULL) {
3119 dsc_reset(dsc);
3120 return NULL; /* no memory */
3122 dsc->string->index = 0;
3123 dsc->string->length = CDSC_STRING_CHUNK;
3125 if ( dsc->string->index + len + 1 > dsc->string->length) {
3126 /* allocate another string block */
3127 CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3128 if (newstring == NULL) {
3129 dsc_debug_print(dsc, "Out of memory\n");
3130 return NULL;
3132 newstring->next = NULL;
3133 newstring->length = 0;
3134 newstring->index = 0;
3135 newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3136 if (newstring->data == NULL) {
3137 dsc_memfree(dsc, newstring);
3138 dsc_debug_print(dsc, "Out of memory\n");
3139 return NULL; /* no memory */
3141 newstring->length = CDSC_STRING_CHUNK;
3142 dsc->string->next = newstring;
3143 dsc->string = newstring;
3145 if ( dsc->string->index + len + 1 > dsc->string->length)
3146 return NULL; /* failed */
3147 p = dsc->string->data + dsc->string->index;
3148 memcpy(p, str, len);
3149 *(p+len) = '\0';
3150 dsc->string->index += len + 1;
3151 return p;
3154 /* store line, ignoring leading spaces */
3155 dsc_private char *
3156 dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
3158 char *newline;
3159 unsigned int i;
3160 while (len && (IS_WHITE(*line))) {
3161 len--;
3162 line++;
3164 newline = dsc_alloc_string(dsc, line, len);
3165 if (newline == NULL)
3166 return NULL;
3168 for (i=0; i<len; i++) {
3169 if (newline[i] == '\r') {
3170 newline[i]='\0';
3171 break;
3173 if (newline[i] == '\n') {
3174 newline[i]='\0';
3175 break;
3178 return newline;
3182 /* Copy string on line to new allocated string str */
3183 /* String is always null terminated */
3184 /* String is no longer than len */
3185 /* Return pointer to string */
3186 /* Store number of used characters from line */
3187 /* Don't copy enclosing () */
3188 dsc_private char *
3189 dsc_copy_string(char *str, unsigned int slen, char *line,
3190 unsigned int len, unsigned int *offset)
3192 int quoted = FALSE;
3193 int instring=0;
3194 unsigned int newlength = 0;
3195 unsigned int i = 0;
3196 unsigned char ch;
3197 if (len > slen)
3198 len = slen-1;
3199 while ( (i<len) && IS_WHITE(line[i]))
3200 i++; /* skip leading spaces */
3201 if (line[i]=='(') {
3202 quoted = TRUE;
3203 instring++;
3204 i++; /* don't copy outside () */
3206 while (i < len) {
3207 str[newlength] = ch = line[i];
3208 i++;
3209 if (quoted) {
3210 if (ch == '(')
3211 instring++;
3212 if (ch == ')')
3213 instring--;
3214 if (instring==0)
3215 break;
3217 else if (ch == ' ')
3218 break;
3220 if (ch == '\r')
3221 break;
3222 if (ch == '\n')
3223 break;
3224 else if ( (ch == '\\') && (i+1 < len) ) {
3225 ch = line[i];
3226 if ((ch >= '0') && (ch <= '9')) {
3227 /* octal coded character */
3228 int j = 3;
3229 ch = 0;
3230 while (j && (i < len) && line[i]>='0' && line[i]<='7') {
3231 ch = (unsigned char)((ch<<3) + (line[i]-'0'));
3232 i++;
3233 j--;
3235 str[newlength] = ch;
3237 else if (ch == '(') {
3238 str[newlength] = ch;
3239 i++;
3241 else if (ch == ')') {
3242 str[newlength] = ch;
3243 i++;
3245 else if (ch == 'b') {
3246 str[newlength] = '\b';
3247 i++;
3249 else if (ch == 'f') {
3250 str[newlength] = '\b';
3251 i++;
3253 else if (ch == 'n') {
3254 str[newlength] = '\n';
3255 i++;
3257 else if (ch == 'r') {
3258 str[newlength] = '\r';
3259 i++;
3261 else if (ch == 't') {
3262 str[newlength] = '\t';
3263 i++;
3265 else if (ch == '\\') {
3266 str[newlength] = '\\';
3267 i++;
3270 newlength++;
3272 str[newlength] = '\0';
3273 if (offset != (unsigned int *)NULL)
3274 *offset = i;
3275 return str;
3278 dsc_private int
3279 dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
3281 char newline[MAXSTR];
3282 int newlength = 0;
3283 unsigned int i = 0;
3284 unsigned char ch;
3286 len = min(len, sizeof(newline)-1);
3287 while ((i<len) && IS_WHITE(line[i]))
3288 i++; /* skip leading spaces */
3289 while (i < len) {
3290 newline[newlength] = ch = line[i];
3291 if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
3292 break; /* not part of an integer number */
3293 i++;
3294 newlength++;
3296 while ((i<len) && IS_WHITE(line[i]))
3297 i++; /* skip trailing spaces */
3298 newline[newlength] = '\0';
3299 if (offset != (unsigned int *)NULL)
3300 *offset = i;
3301 return atoi(newline);
3304 dsc_private float
3305 dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
3307 char newline[MAXSTR];
3308 int newlength = 0;
3309 unsigned int i = 0;
3310 unsigned char ch;
3312 len = min(len, sizeof(newline)-1);
3313 while ((i<len) && IS_WHITE(line[i]))
3314 i++; /* skip leading spaces */
3315 while (i < len) {
3316 newline[newlength] = ch = line[i];
3317 if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
3318 || (ch=='e') || (ch=='E')))
3319 break; /* not part of a real number */
3320 i++;
3321 newlength++;
3323 while ((i<len) && IS_WHITE(line[i]))
3324 i++; /* skip trailing spaces */
3326 newline[newlength] = '\0';
3328 if (offset != (unsigned int *)NULL)
3329 *offset = i;
3330 return (float)atof(newline);
3333 dsc_private int
3334 dsc_stricmp(const char *s, const char *t)
3336 while (toupper(*s) == toupper(*t)) {
3337 if (*s == '\0')
3338 return 0;
3339 s++;
3340 t++;
3342 return (toupper(*s) - toupper(*t));
3346 dsc_private int
3347 dsc_parse_page(CDSC *dsc)
3349 char *p;
3350 unsigned int i;
3351 char page_label[MAXSTR];
3352 char *pl;
3353 int page_ordinal;
3354 int page_number;
3356 p = dsc->line + 7;
3357 pl = dsc_copy_string(page_label, sizeof(page_label)-1, p, dsc->line_length-7, &i);
3358 if (pl == NULL)
3359 return CDSC_ERROR;
3360 p += i;
3361 page_ordinal = atoi(p);
3363 if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
3364 (dsc->page_count &&
3365 (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
3366 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
3367 dsc->line_length);
3368 switch (rc) {
3369 case CDSC_RESPONSE_OK:
3370 /* ignore this page */
3371 return CDSC_OK;
3372 case CDSC_RESPONSE_CANCEL:
3373 /* accept the page */
3374 break;
3375 case CDSC_RESPONSE_IGNORE_ALL:
3376 return CDSC_NOTDSC;
3380 page_number = dsc->page_count;
3381 dsc_add_page(dsc, page_ordinal, page_label);
3382 dsc->page[page_number].begin = DSC_START(dsc);
3383 dsc->page[page_number].end = DSC_START(dsc);
3385 if (dsc->page[page_number].label == NULL)
3386 return CDSC_ERROR; /* no memory */
3388 return CDSC_OK;
3393 /* DSC error reporting */
3395 void
3396 dsc_debug_print(CDSC *dsc, const char *str)
3398 if (dsc->debug_print_fn)
3399 dsc->debug_print_fn(dsc->caller_data, str);
3403 /* Display a message about a problem with the DSC comments.
3405 * explanation = an index to to a multiline explanation in dsc_message[]
3406 * line = pointer to the offending DSC line (if any)
3407 * return code =
3408 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
3409 * was really meant.
3410 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
3411 * is misplaced.
3412 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
3414 /* Silent operation. Don't display errors. */
3415 dsc_private int
3416 dsc_error(CDSC *dsc, unsigned int explanation,
3417 char *line, unsigned int line_len)
3419 /* if error function provided, use it */
3420 if (dsc->dsc_error_fn)
3421 return dsc->dsc_error_fn(dsc->caller_data, dsc,
3422 explanation, line, line_len);
3424 /* treat DSC as being correct */
3425 return CDSC_RESPONSE_CANCEL;
3429 // vim:sw=4:sts=4:ts=8:noet