Coverage Report

Created: 2025-06-10 07:17

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