Coverage Report

Created: 2025-06-24 07:01

/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
4.70M
#define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
56
4.40M
#define IS_DSC(line, str) (COMPARE((line), (str)))
57
58
/* Macros for comparing the first one or two characters */
59
514k
#define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
60
169k
#define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
61
166k
#define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
62
3.09k
#define IS_BLANK(str) (IS_EOL(str[0]))
63
30.9k
#define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
64
65
/* Macros for document offset to start and end of line */
66
12.1k
#define DSC_START(dsc)  ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
67
150k
#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
157k
#define CDSC_PROPAGATE  10
75
76
/* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
77
167k
#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
324k
#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
162k
{
227
162k
    CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
228
162k
    if (dsc == NULL)
229
0
        return NULL;
230
162k
    memset(dsc, 0, sizeof(CDSC));
231
162k
    dsc->caller_data = caller_data;
232
233
162k
    dsc->memalloc = memalloc;
234
162k
    dsc->memfree = memfree;
235
162k
    dsc->mem_closure_data = closure_data;
236
162k
    dsc->ref_count = 0;
237
162k
    dsc_ref(dsc);
238
239
162k
    return dsc_init2(dsc);
240
162k
}
241
242
/* destructor */
243
void
244
dsc_free(CDSC *dsc)
245
162k
{
246
162k
    if (dsc == NULL)
247
0
        return;
248
162k
    dsc_reset(dsc);
249
162k
    dsc_memfree(dsc, dsc);
250
162k
}
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
162k
{
261
162k
    return ++(dsc->ref_count);
262
162k
}
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
1.49M
{
296
1.49M
    int bytes_read;
297
1.49M
    int code = 0;
298
299
1.49M
    if (dsc == NULL)
300
0
        return CDSC_ERROR;
301
302
1.49M
    if (dsc->id == CDSC_NOTDSC)
303
1.32M
        return CDSC_NOTDSC;
304
167k
    dsc->id = CDSC_OK;
305
167k
    if (dsc->eof)
306
0
        return CDSC_OK; /* ignore */
307
308
167k
    if (length == 0) {
309
        /* EOF, so process what remains */
310
0
        dsc->eof = TRUE;
311
0
    }
312
313
167k
    do {
314
167k
        if (dsc->id == CDSC_NOTDSC)
315
0
            break;
316
317
167k
        if (length != 0) {
318
            /* move existing data if needed */
319
167k
            if (dsc->data_length > CDSC_DATA_LENGTH/2) {
320
447
                memmove(dsc->data, dsc->data + dsc->data_index,
321
447
                    dsc->data_length - dsc->data_index);
322
447
                dsc->data_offset += dsc->data_index;
323
447
                dsc->data_length -= dsc->data_index;
324
447
                dsc->data_index = 0;
325
447
            }
326
            /* append to buffer */
327
167k
            bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
328
167k
            memcpy(dsc->data + dsc->data_length, data, bytes_read);
329
167k
            dsc->data_length += bytes_read;
330
167k
            data += bytes_read;
331
167k
            length -= bytes_read;
332
167k
        }
333
167k
        if (dsc->scan_section == scan_none) {
334
17.1k
            code = dsc_scan_type(dsc);
335
17.1k
            if (code == CDSC_NEEDMORE) {
336
                /* need more characters before we can identify type */
337
0
                code = CDSC_OK;
338
0
                break;
339
0
            }
340
17.1k
            dsc->id = code;
341
17.1k
        }
342
343
167k
        if (code == CDSC_NOTDSC) {
344
11.8k
            dsc->id = CDSC_NOTDSC;
345
11.8k
            break;
346
11.8k
        }
347
348
305k
        while ((code = dsc_read_line(dsc)) > 0) {
349
150k
            if (dsc->id == CDSC_NOTDSC)
350
0
                break;
351
150k
            if (dsc->file_length &&
352
150k
                (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
150k
            if (dsc->doseps_end &&
357
150k
                (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
150k
            if (dsc->eof)
364
0
                return CDSC_OK;
365
150k
            if (dsc->skip_document)
366
16
                continue;  /* embedded document */
367
150k
            if (dsc->skip_lines)
368
0
                continue; /* embedded lines */
369
150k
            if (IS_DSC(dsc->line, "%%BeginData:"))
370
0
                continue;
371
150k
            if (IS_DSC(dsc->line, "%%BeginBinary:"))
372
0
                continue;
373
150k
            if (IS_DSC(dsc->line, "%%EndDocument"))
374
1
                continue;
375
150k
            if (IS_DSC(dsc->line, "%%EndData"))
376
0
                continue;
377
150k
            if (IS_DSC(dsc->line, "%%EndBinary"))
378
0
                continue;
379
380
153k
            do {
381
153k
                switch (dsc->scan_section) {
382
114k
                    case scan_comments:
383
114k
                        code = dsc_scan_comments(dsc);
384
114k
                        break;
385
1.19k
                    case scan_pre_preview:
386
1.99k
                    case scan_preview:
387
1.99k
                        code = dsc_scan_preview(dsc);
388
1.99k
                        break;
389
1.16k
                    case scan_pre_defaults:
390
1.62k
                    case scan_defaults:
391
1.62k
                        code = dsc_scan_defaults(dsc);
392
1.62k
                        break;
393
1.14k
                    case scan_pre_prolog:
394
18.8k
                    case scan_prolog:
395
18.8k
                        code = dsc_scan_prolog(dsc);
396
18.8k
                        break;
397
735
                    case scan_pre_setup:
398
5.78k
                    case scan_setup:
399
5.78k
                        code = dsc_scan_setup(dsc);
400
5.78k
                        break;
401
4.93k
                    case scan_pre_pages:
402
10.1k
                    case scan_pages:
403
10.1k
                        code = dsc_scan_page(dsc);
404
10.1k
                        break;
405
51
                    case scan_pre_trailer:
406
603
                    case scan_trailer:
407
603
                        code = dsc_scan_trailer(dsc);
408
603
                        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
153k
                }
416
                /* repeat if line is start of next section */
417
153k
            } while (code == CDSC_PROPAGATE);
418
419
            /* if DOS EPS header not complete, ask for more */
420
150k
            if (code == CDSC_NEEDMORE) {
421
0
                code = CDSC_OK;
422
0
                break;
423
0
            }
424
150k
            if (code == CDSC_NOTDSC) {
425
0
                dsc->id = CDSC_NOTDSC;
426
0
                break;
427
0
            }
428
150k
        }
429
155k
    } while (length != 0);
430
431
167k
    return (code < 0) ? code : dsc->id;
432
167k
}
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
162k
{
605
162k
    dsc->dsc_error_fn = fn;
606
162k
}
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
490
{
622
490
    dsc->page[dsc->page_count].ordinal = ordinal;
623
490
    dsc->page[dsc->page_count].label =
624
490
        dsc_alloc_string(dsc, label, (int)strlen(label)+1);
625
490
    if (dsc->page[dsc->page_count].label == NULL)
626
0
        return CDSC_ERROR; /* out of memory */
627
628
490
    dsc->page[dsc->page_count].begin = 0;
629
490
    dsc->page[dsc->page_count].end = 0;
630
490
    dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
631
490
    dsc->page[dsc->page_count].media = NULL;
632
490
    dsc->page[dsc->page_count].bbox = NULL;
633
490
    dsc->page[dsc->page_count].viewing_orientation = NULL;
634
490
    dsc->page[dsc->page_count].crop_box = NULL;
635
636
490
    dsc->page_count++;
637
490
    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
490
    return CDSC_OK;
649
490
}
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
490k
{
747
490k
    if (dsc->memalloc)
748
490k
        return dsc->memalloc(size, dsc->mem_closure_data);
749
0
    return malloc(size);
750
490k
}
751
752
static void
753
dsc_memfree(CDSC*dsc, void *ptr)
754
652k
{
755
652k
    if (dsc->memfree)
756
652k
        dsc->memfree(ptr, dsc->mem_closure_data);
757
0
    else
758
0
        free(ptr);
759
652k
}
760
761
/* private constructor */
762
static CDSC *
763
dsc_init2(CDSC *dsc)
764
162k
{
765
162k
    dsc_reset(dsc);
766
767
162k
    dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
768
162k
    if (dsc->string_head == NULL) {
769
0
        dsc_free(dsc);
770
0
        return NULL;  /* no memory */
771
0
    }
772
162k
    dsc->string = dsc->string_head;
773
162k
    dsc->string->next = NULL;
774
162k
    dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
775
162k
    if (dsc->string->data == NULL) {
776
0
        dsc_free(dsc);
777
0
        return NULL;  /* no memory */
778
0
    }
779
162k
    dsc->string->index = 0;
780
162k
    dsc->string->length = CDSC_STRING_CHUNK;
781
782
162k
    dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
783
162k
    if (dsc->page == NULL) {
784
0
        dsc_free(dsc);
785
0
        return NULL;  /* no memory */
786
0
    }
787
162k
    dsc->page_chunk_length = CDSC_PAGE_CHUNK;
788
162k
    dsc->page_count = 0;
789
790
162k
    dsc->line = NULL;
791
162k
    dsc->data_length = 0;
792
162k
    dsc->data_index = dsc->data_length;
793
794
162k
    return dsc;
795
162k
}
796
797
static void
798
dsc_reset(CDSC *dsc)
799
324k
{
800
324k
    unsigned int i;
801
    /* Clear public members */
802
324k
    dsc->dsc = FALSE;
803
324k
    dsc->ctrld = FALSE;
804
324k
    dsc->pjl = FALSE;
805
324k
    dsc->epsf = FALSE;
806
324k
    dsc->pdf = FALSE;
807
324k
    dsc->epsf = FALSE;
808
324k
    dsc->preview = CDSC_NOPREVIEW;
809
324k
    dsc->dsc_version = NULL;  /* stored in dsc->string */
810
324k
    dsc->language_level = 0;
811
324k
    dsc->document_data = CDSC_DATA_UNKNOWN;
812
324k
    dsc->begincomments = 0;
813
324k
    dsc->endcomments = 0;
814
324k
    dsc->beginpreview = 0;
815
324k
    dsc->endpreview = 0;
816
324k
    dsc->begindefaults = 0;
817
324k
    dsc->enddefaults = 0;
818
324k
    dsc->beginprolog = 0;
819
324k
    dsc->endprolog = 0;
820
324k
    dsc->beginsetup = 0;
821
324k
    dsc->endsetup = 0;
822
324k
    dsc->begintrailer = 0;
823
324k
    dsc->endtrailer = 0;
824
825
325k
    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
490
        if (dsc->page[i].bbox)
830
3
            dsc_memfree(dsc, dsc->page[i].bbox);
831
490
        if (dsc->page[i].viewing_orientation)
832
0
            dsc_memfree(dsc, dsc->page[i].viewing_orientation);
833
490
        if (dsc->page[i].crop_box)
834
0
            dsc_memfree(dsc, dsc->page[i].crop_box);
835
490
    }
836
324k
    if (dsc->page)
837
162k
        dsc_memfree(dsc, dsc->page);
838
324k
    dsc->page = NULL;
839
840
324k
    dsc->page_count = 0;
841
324k
    dsc->page_pages = 0;
842
324k
    dsc->page_order = CDSC_ORDER_UNKNOWN;
843
324k
    dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
844
324k
    if (dsc->viewing_orientation)
845
0
        dsc_memfree(dsc, dsc->viewing_orientation);
846
324k
    dsc->viewing_orientation = NULL;
847
848
324k
    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
324k
    dsc->media_count = 0;
859
324k
    dsc->media = NULL;
860
861
    /* page_media is pointer to an element of media or dsc_known_media */
862
    /* do not free it. */
863
324k
    dsc->page_media = NULL;
864
865
324k
    if (dsc->bbox)
866
2.31k
        dsc_memfree(dsc, dsc->bbox);
867
324k
    dsc->bbox = NULL;
868
324k
    if (dsc->page_bbox)
869
0
        dsc_memfree(dsc, dsc->page_bbox);
870
324k
    dsc->page_bbox = NULL;
871
324k
    if (dsc->doseps)
872
0
        dsc_memfree(dsc, dsc->doseps);
873
324k
    dsc->doseps = NULL;
874
875
324k
    dsc->dsc_title = NULL;
876
324k
    dsc->dsc_creator = NULL;
877
324k
    dsc->dsc_date = NULL;
878
324k
    dsc->dsc_for = NULL;
879
880
324k
    dsc->max_error = DSC_MAX_ERROR;
881
324k
    dsc->severity = dsc_severity;
882
883
    /* Clear private members */
884
    /* Don't touch dsc->caller_data */
885
324k
    dsc->id = CDSC_OK;
886
324k
    dsc->scan_section = scan_none;
887
324k
    dsc->doseps_end = 0;
888
324k
    dsc->page_chunk_length = 0;
889
324k
    dsc->file_length = 0;
890
324k
    dsc->skip_document = 0;
891
324k
    dsc->skip_bytes = 0;
892
324k
    dsc->skip_lines = 0;
893
324k
    dsc->skip_pjl = 0;
894
324k
    dsc->begin_font_count = 0;
895
324k
    dsc->begin_feature_count = 0;
896
324k
    dsc->begin_resource_count = 0;
897
324k
    dsc->begin_procset_count = 0;
898
899
324k
    dsc->data_length = 0;
900
324k
    dsc->data_index = 0;
901
324k
    dsc->data_offset = 0;
902
903
324k
    dsc->eof = 0;
904
905
324k
    dsc->line = 0;
906
324k
    dsc->line_length = 0;
907
324k
    dsc->eol = 0;
908
324k
    dsc->last_cr = FALSE;
909
324k
    dsc->line_count = 1;
910
324k
    dsc->long_line = FALSE;
911
324k
    memset(dsc->last_line, 0, sizeof(dsc->last_line));
912
913
324k
    dsc->string = dsc->string_head;
914
487k
    while (dsc->string != (CDSCSTRING *)NULL) {
915
162k
        if (dsc->string->data)
916
162k
            dsc_memfree(dsc, dsc->string->data);
917
162k
        dsc->string_head = dsc->string;
918
162k
        dsc->string = dsc->string->next;
919
162k
        dsc_memfree(dsc, dsc->string_head);
920
162k
    }
921
324k
    dsc->string_head = NULL;
922
324k
    dsc->string = NULL;
923
924
    /* don't touch caller functions */
925
926
    /* public data */
927
324k
    if (dsc->hires_bbox)
928
60
        dsc_memfree(dsc, dsc->hires_bbox);
929
324k
    dsc->hires_bbox = NULL;
930
324k
    if (dsc->crop_box)
931
2
        dsc_memfree(dsc, dsc->crop_box);
932
324k
    dsc->crop_box = NULL;
933
934
324k
    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
324k
    if (dsc->colours) {
946
61
        CDSCCOLOUR *this_colour, *next_colour;
947
61
        this_colour = dsc->colours;
948
340
        while (this_colour) {
949
279
            next_colour = this_colour->next;
950
            /* strings have already been freed */
951
279
            dsc_memfree(dsc, this_colour);
952
279
            this_colour = next_colour;
953
279
        }
954
61
        dsc->colours = NULL;
955
61
    }
956
957
324k
    if (dsc->macbin)
958
0
        dsc_memfree(dsc, dsc->macbin);
959
324k
    dsc->macbin = NULL;
960
324k
}
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
322k
{
983
322k
    char *p, *last;
984
322k
    dsc->line = NULL;
985
986
322k
    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
322k
    if (dsc->file_length &&
995
322k
        (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
322k
    if (dsc->doseps_end &&
1005
322k
        (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
322k
    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
322k
    do {
1025
322k
        dsc->line = dsc->data + dsc->data_index;
1026
322k
        last = dsc->data + dsc->data_length;
1027
322k
        if (dsc->data_index == dsc->data_length) {
1028
155k
            dsc->line_length = 0;
1029
155k
            return 0;
1030
155k
        }
1031
167k
        if (dsc->eol) {
1032
            /* if previous line was complete, increment line count */
1033
150k
            dsc->line_count++;
1034
150k
            if (dsc->skip_lines)
1035
0
                dsc->skip_lines--;
1036
150k
        }
1037
1038
        /* skip over \n which followed \r */
1039
167k
        if (dsc->last_cr && dsc->line[0] == '\n') {
1040
0
            dsc->data_index++;
1041
0
            dsc->line++;
1042
0
        }
1043
167k
        dsc->last_cr = FALSE;
1044
1045
        /* look for EOL */
1046
167k
        dsc->eol = FALSE;
1047
4.71M
        for (p = dsc->line; p < last; p++) {
1048
4.71M
            if (*p == '\r') {
1049
167k
                p++;
1050
167k
                if ((p<last) && (*p == '\n'))
1051
0
                    p++; /* include line feed also */
1052
167k
                else
1053
167k
                    dsc->last_cr = TRUE; /* we might need to skip \n */
1054
167k
                dsc->eol = TRUE; /* dsc->line is a complete line */
1055
167k
                break;
1056
167k
            }
1057
4.55M
            if (*p == '\n') {
1058
0
                p++;
1059
0
                dsc->eol = TRUE; /* dsc->line is a complete line */
1060
0
                break;
1061
0
            }
1062
4.55M
            if (*p == '\032') {   /* MS-DOS Ctrl+Z */
1063
2.08k
                dsc->eol = TRUE;
1064
2.08k
            }
1065
4.55M
        }
1066
167k
        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
167k
        dsc->data_index += dsc->line_length = (int)(p - dsc->line);
1075
167k
    } while (dsc->skip_lines && dsc->line_length);
1076
1077
167k
    if (dsc->line_length == 0)
1078
0
        return 0;
1079
1080
167k
    if ((dsc->line[0]=='%') && (dsc->line[1]=='%'))  {
1081
        /* handle recursive %%BeginDocument */
1082
139k
        if ((dsc->skip_document) && dsc->line_length &&
1083
139k
                COMPARE(dsc->line, "%%EndDocument")) {
1084
0
            dsc->skip_document--;
1085
0
        }
1086
1087
        /* handle embedded lines or binary data */
1088
139k
        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
139k
        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
139k
    }
1154
1155
167k
    if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
1156
167k
        COMPARE(dsc->line, "%%BeginDocument:") ) {
1157
        /* Skip over embedded document, recursively */
1158
19
        dsc->skip_document++;
1159
19
    }
1160
1161
167k
    if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
1162
421
        dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
1163
421
        dsc->long_line = TRUE;
1164
421
    }
1165
1166
167k
    return dsc->line_length;
1167
167k
}
1168
1169
/* Save last DSC line, for use with %%+ */
1170
static void
1171
dsc_save_line(CDSC *dsc)
1172
113k
{
1173
113k
    int len = min(sizeof(dsc->last_line), dsc->line_length);
1174
113k
    memcpy(dsc->last_line, dsc->line, len);
1175
113k
}
1176
1177
/* display unknown DSC line */
1178
static void
1179
dsc_unknown(CDSC *dsc)
1180
77.5k
{
1181
77.5k
    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
77.5k
}
1193
1194
static GSBOOL
1195
dsc_is_section(char *line)
1196
140k
{
1197
140k
    if ( !((line[0]=='%') && (line[1]=='%')) )
1198
10.0k
        return FALSE;
1199
130k
    if (IS_DSC(line, "%%BeginPreview"))
1200
33
        return TRUE;
1201
130k
    if (IS_DSC(line, "%%BeginDefaults"))
1202
18
        return TRUE;
1203
130k
    if (IS_DSC(line, "%%BeginProlog"))
1204
121
        return TRUE;
1205
130k
    if (IS_DSC(line, "%%BeginSetup"))
1206
110
        return TRUE;
1207
130k
    if (IS_DSC(line, "%%Page:"))
1208
464
        return TRUE;
1209
129k
    if (IS_DSC(line, "%%Trailer"))
1210
62
        return TRUE;
1211
129k
    if (IS_DSC(line, "%%EOF"))
1212
13
        return TRUE;
1213
129k
    return FALSE;
1214
129k
}
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
1.49k
{
1395
1.49k
    int ip, io;
1396
1.49k
    unsigned int i;
1397
1.49k
    char *p;
1398
1.49k
    int n;
1399
1.49k
    if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
1400
21
        int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1401
21
                dsc->line_length);
1402
21
        switch (rc) {
1403
21
            case CDSC_RESPONSE_OK:
1404
21
            case CDSC_RESPONSE_CANCEL:
1405
21
                return CDSC_OK;  /* ignore duplicate comments in header */
1406
0
            case CDSC_RESPONSE_IGNORE_ALL:
1407
0
                return CDSC_NOTDSC;
1408
21
        }
1409
21
    }
1410
1.47k
    if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
1411
11
        int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1412
11
                dsc->line_length);
1413
11
        switch (rc) {
1414
11
            case CDSC_RESPONSE_OK:
1415
11
            case CDSC_RESPONSE_CANCEL:
1416
11
                break;    /* use duplicate comments in header */
1417
0
            case CDSC_RESPONSE_IGNORE_ALL:
1418
0
                return CDSC_NOTDSC;
1419
11
        }
1420
11
    }
1421
1422
1.47k
    n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
1423
2.87k
    while (IS_WHITE(dsc->line[n]))
1424
1.39k
        n++;
1425
1.47k
    p = dsc->line + n;
1426
1.47k
    if (COMPARE(p, "atend")) {
1427
1
        if (dsc->scan_section != scan_comments)
1428
0
            dsc_unknown(dsc);
1429
1
        else {
1430
1
            int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1431
1
                dsc->line, dsc->line_length);
1432
1
            switch (rc) {
1433
1
                case CDSC_RESPONSE_OK:
1434
                    /* assume (atend) */
1435
                    /* we should mark it as deferred */
1436
1
                    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
1
            }
1443
1
        }
1444
1
    }
1445
1.47k
    else if (COMPARE(p, "(atend)")) {
1446
988
        if (dsc->scan_section != scan_comments)
1447
2
            dsc_unknown(dsc);
1448
        /* do nothing */
1449
        /* we should mark it as deferred */
1450
988
    }
1451
489
    else {
1452
489
        ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1453
489
        if (i) {
1454
243
            n+=i;
1455
243
            dsc->page_pages = ip;
1456
243
            io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1457
243
            if (i) {
1458
                /* DSC 2 uses extra integer to indicate page order */
1459
                /* DSC 3 uses %%PageOrder: */
1460
5
                if (dsc->page_order == CDSC_ORDER_UNKNOWN)
1461
5
                    switch (io) {
1462
0
                        case -1:
1463
0
                            dsc->page_order = CDSC_DESCEND;
1464
0
                            break;
1465
3
                        case 0:
1466
3
                            dsc->page_order = CDSC_SPECIAL;
1467
3
                            break;
1468
0
                        case 1:
1469
0
                            dsc->page_order = CDSC_ASCEND;
1470
0
                            break;
1471
5
                    }
1472
5
            }
1473
243
        }
1474
246
        else {
1475
246
            int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
1476
246
                dsc->line_length);
1477
246
            switch (rc) {
1478
246
                case CDSC_RESPONSE_OK:
1479
246
                case CDSC_RESPONSE_CANCEL:
1480
                    /* ignore it */
1481
246
                    break;
1482
0
                case CDSC_RESPONSE_IGNORE_ALL:
1483
0
                    return CDSC_NOTDSC;
1484
246
            }
1485
246
        }
1486
489
    }
1487
1.47k
    return CDSC_OK;
1488
1.47k
}
1489
1490
static int
1491
dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
1492
9.37k
{
1493
9.37k
    unsigned int i, n;
1494
9.37k
    int llx, lly, urx, ury;
1495
9.37k
    float fllx, flly, furx, fury;
1496
9.37k
    char *p;
1497
    /* Process first %%BoundingBox: in comments, and last in trailer */
1498
9.37k
    if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1499
6.29k
        int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1500
6.29k
                dsc->line_length);
1501
6.29k
        switch (rc) {
1502
6.29k
            case CDSC_RESPONSE_OK:
1503
6.29k
            case CDSC_RESPONSE_CANCEL:
1504
6.29k
                return CDSC_OK;  /* ignore duplicate comments in header */
1505
0
            case CDSC_RESPONSE_IGNORE_ALL:
1506
0
                return CDSC_NOTDSC;
1507
6.29k
        }
1508
6.29k
    }
1509
3.08k
    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
3.08k
    if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1521
2
        int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1522
2
                dsc->line_length);
1523
2
        switch (rc) {
1524
2
            case CDSC_RESPONSE_OK:
1525
2
            case CDSC_RESPONSE_CANCEL:
1526
2
                break;    /* use duplicate comments in trailer */
1527
0
            case CDSC_RESPONSE_IGNORE_ALL:
1528
0
                return CDSC_NOTDSC;
1529
2
        }
1530
2
    }
1531
3.08k
    if (*pbbox != NULL) {
1532
2
        dsc_memfree(dsc, *pbbox);
1533
2
        *pbbox = NULL;
1534
2
    }
1535
1536
    /* should only process first %%BoundingBox: */
1537
1538
6.29k
    while (IS_WHITE(dsc->line[offset]))
1539
3.21k
        offset++;
1540
3.08k
    p = dsc->line + offset;
1541
1542
3.08k
    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
3.08k
    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
3.08k
    else {
1568
3.08k
        /* llx = */ lly = urx = ury = 0;
1569
3.08k
        n = offset;
1570
3.08k
        llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1571
3.08k
        n += i;
1572
3.08k
        if (i)
1573
2.90k
            lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1574
3.08k
        n += i;
1575
3.08k
        if (i)
1576
2.79k
            urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1577
3.08k
        n += i;
1578
3.08k
        if (i)
1579
2.60k
            ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1580
3.08k
        if (i) {
1581
2.30k
            *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1582
2.30k
            if (*pbbox == NULL)
1583
0
                return CDSC_ERROR; /* no memory */
1584
2.30k
            (*pbbox)->llx = llx;
1585
2.30k
            (*pbbox)->lly = lly;
1586
2.30k
            (*pbbox)->urx = urx;
1587
2.30k
            (*pbbox)->ury = ury;
1588
2.30k
        }
1589
773
        else {
1590
773
            int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
1591
773
                dsc->line_length);
1592
773
            switch (rc) {
1593
773
              case CDSC_RESPONSE_OK:
1594
773
                /* fllx = */ flly = furx = fury = 0.0;
1595
773
                n = offset;
1596
773
                n += i;
1597
773
                fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1598
773
                n += i;
1599
773
                if (i)
1600
601
                    flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1601
773
                n += i;
1602
773
                if (i)
1603
492
                    furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1604
773
                n += i;
1605
773
                if (i)
1606
311
                    fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1607
773
                if (i) {
1608
8
                    *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1609
8
                    if (*pbbox == NULL)
1610
0
                        return CDSC_ERROR; /* no memory */
1611
8
                    (*pbbox)->llx = (int)fllx;
1612
8
                    (*pbbox)->lly = (int)flly;
1613
8
                    (*pbbox)->urx = (int)(furx+0.999);
1614
8
                    (*pbbox)->ury = (int)(fury+0.999);
1615
8
                }
1616
773
                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
773
          }
1622
773
        }
1623
3.08k
    }
1624
2.30k
    return CDSC_OK;
1625
3.08k
}
1626
1627
static int
1628
dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
1629
62
{
1630
62
    unsigned int i, n;
1631
62
    float fllx, flly, furx, fury;
1632
62
    char *p;
1633
    /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1634
     * and last in trailer.
1635
     */
1636
62
    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
62
    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
62
    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
62
    if (*pbbox != NULL) {
1670
0
        dsc_memfree(dsc, *pbbox);
1671
0
        *pbbox = NULL;
1672
0
    }
1673
1674
    /* should only process first %%BoundingBox: */
1675
1676
124
    while (IS_WHITE(dsc->line[offset]))
1677
62
        offset++;
1678
62
    p = dsc->line + offset;
1679
1680
62
    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
62
    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
62
    else {
1706
62
        /* fllx = */ flly = furx = fury = 0.0;
1707
62
        n = offset;
1708
62
        fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1709
62
        n += i;
1710
62
        if (i)
1711
62
            flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1712
62
        n += i;
1713
62
        if (i)
1714
62
            furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1715
62
        n += i;
1716
62
        if (i)
1717
62
            fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1718
62
        if (i) {
1719
62
            *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
1720
62
            if (*pbbox == NULL)
1721
0
                return CDSC_ERROR; /* no memory */
1722
62
            (*pbbox)->fllx = fllx;
1723
62
            (*pbbox)->flly = flly;
1724
62
            (*pbbox)->furx = furx;
1725
62
            (*pbbox)->fury = fury;
1726
62
        }
1727
62
    }
1728
62
    return CDSC_OK;
1729
62
}
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
17.1k
{
2001
17.1k
    unsigned char *p;
2002
17.1k
    unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
2003
17.1k
    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
17.1k
    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
17.1k
    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
17.1k
    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
17.1k
    if (length == 0)
2070
0
        return CDSC_NEEDMORE;
2071
2072
17.1k
    if (line[0] == '\004') {
2073
0
        line++;
2074
0
        dsc->data_index++;
2075
0
        length--;
2076
0
        dsc->ctrld = TRUE;
2077
0
    }
2078
2079
17.1k
    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
17.1k
    if ((line[0]==0x0) && (length < 2))
2092
0
        return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2093
17.1k
    if ((line[0]==0x0) && (line[1] >= 1) && (line[1] <= 63) && (length < 128))
2094
0
        return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2095
17.1k
    if ((line[0]==0x0) && (line[1] == 0x5) && (length < 4))
2096
0
        return CDSC_NEEDMORE; /* Could be Mac AppleSingle/AppleDouble */
2097
17.1k
    if ((line[0]==0xc5) && (length < 4))
2098
0
        return CDSC_NEEDMORE; /* Could be DOS EPS */
2099
2100
17.1k
    if ((line[0]==0xc5) && (line[1]==0xd0) &&
2101
17.1k
         (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
17.1k
    else if ((line[0]==0x0) && (line[1]==0x05) &&
2111
17.1k
         (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
17.1k
    else if ((line[0]==0x0) &&
2128
17.1k
        (line[1] >= 1) && (line[1] <= 63) &&
2129
17.1k
        (line[74]==0x0) &&
2130
17.1k
        (line[65]=='E') && (line[66]=='P') &&
2131
17.1k
        (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
17.1k
    else {
2138
17.1k
        if (length < 2)
2139
0
            return CDSC_NEEDMORE;
2140
17.1k
        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
17.1k
    }
2150
2151
    /* Finally process PostScript headers */
2152
2153
17.1k
    if (dsc_read_line(dsc) <= 0)
2154
0
        return CDSC_NEEDMORE;
2155
2156
17.1k
    dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
2157
17.1k
    if (COMPARE(dsc->line, "%!PS-Adobe")) {
2158
5.34k
        dsc->dsc = TRUE;
2159
5.34k
        dsc->begincomments = DSC_START(dsc);
2160
5.34k
        if (dsc->dsc_version == NULL)
2161
0
            return CDSC_ERROR; /* no memory */
2162
5.34k
        p = (unsigned char *)dsc->line + 14;
2163
8.75k
        while (IS_WHITE(*p))
2164
3.40k
            p++;
2165
5.34k
        if (COMPARE(p, "EPSF-"))
2166
2.31k
            dsc->epsf = TRUE;
2167
5.34k
        dsc->scan_section = scan_comments;
2168
5.34k
        return CDSC_PSADOBE;
2169
5.34k
    }
2170
11.8k
    if (COMPARE(dsc->line, "%!")) {
2171
9.05k
        dsc->scan_section = scan_comments;
2172
9.05k
        return CDSC_NOTDSC;
2173
9.05k
    }
2174
2175
2.77k
    dsc->scan_section = scan_comments;
2176
2.77k
    return CDSC_NOTDSC; /* unrecognised */
2177
11.8k
}
2178
2179
static int
2180
dsc_scan_comments(CDSC *dsc)
2181
114k
{
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
114k
    char *line = dsc->line;
2189
114k
    GSBOOL continued = FALSE;
2190
114k
    dsc->id = CDSC_OK;
2191
114k
    if (IS_DSC(line, "%%EndComments")) {
2192
946
        dsc->id = CDSC_ENDCOMMENTS;
2193
946
        dsc->endcomments = DSC_END(dsc);
2194
946
        dsc->scan_section = scan_pre_preview;
2195
946
        return CDSC_OK;
2196
946
    }
2197
113k
    else if (IS_DSC(line, "%%BeginComments")) {
2198
        /* ignore because we are in this section */
2199
0
        dsc->id = CDSC_BEGINCOMMENTS;
2200
0
    }
2201
113k
    else if (dsc_is_section(line)) {
2202
270
        dsc->endcomments = DSC_START(dsc);
2203
270
        dsc->scan_section = scan_pre_preview;
2204
270
        return CDSC_PROPAGATE;
2205
270
    }
2206
113k
    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
113k
    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
113k
    else if (IS_DSC(line, "%%Begin")) {
2218
141
        dsc->endcomments = DSC_START(dsc);
2219
141
        dsc->scan_section = scan_pre_preview;
2220
141
        return CDSC_PROPAGATE;
2221
141
    }
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
113k
    if (IS_DSC(line, "%%+")) {
2232
25
        line = dsc->last_line;
2233
25
        continued = TRUE;
2234
25
    }
2235
113k
    else
2236
113k
        dsc_save_line(dsc);
2237
2238
113k
    if (IS_DSC(line, "%%Pages:")) {
2239
1.46k
        dsc->id = CDSC_PAGES;
2240
1.46k
        if (dsc_parse_pages(dsc) != 0)
2241
0
            return CDSC_ERROR;
2242
1.46k
    }
2243
111k
    else if (IS_DSC(line, "%%Creator:")) {
2244
21.9k
        unsigned int n = continued ? 3 : 10;
2245
21.9k
        dsc->id = CDSC_CREATOR;
2246
21.9k
        dsc->dsc_creator = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2247
21.9k
        if (dsc->dsc_creator==NULL)
2248
0
            return CDSC_ERROR;
2249
21.9k
    }
2250
89.9k
    else if (IS_DSC(line, "%%CreationDate:")) {
2251
7.47k
        unsigned int n = continued ? 3 : 15;
2252
7.47k
        dsc->id = CDSC_CREATIONDATE;
2253
7.47k
        dsc->dsc_date = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2254
7.47k
        if (dsc->dsc_date==NULL)
2255
0
            return CDSC_ERROR;
2256
7.47k
    }
2257
82.4k
    else if (IS_DSC(line, "%%Title:")) {
2258
18.3k
        unsigned int n = continued ? 3 : 8;
2259
18.3k
        dsc->id = CDSC_TITLE;
2260
18.3k
        dsc->dsc_title = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2261
18.3k
        if (dsc->dsc_title==NULL)
2262
0
            return CDSC_ERROR;
2263
18.3k
    }
2264
64.1k
    else if (IS_DSC(line, "%%For:")) {
2265
2.17k
        unsigned int n = continued ? 3 : 6;
2266
2.17k
        dsc->id = CDSC_FOR;
2267
2.17k
        dsc->dsc_for = dsc_add_line(dsc, dsc->line + n, dsc->line_length - n);
2268
2.17k
        if (dsc->dsc_for==NULL)
2269
0
            return CDSC_ERROR;
2270
2.17k
    }
2271
61.9k
    else if (IS_DSC(line, "%%LanguageLevel:")) {
2272
162
        unsigned int n = continued ? 3 : 16;
2273
162
        unsigned int i;
2274
162
        int ll;
2275
162
        dsc->id = CDSC_LANGUAGELEVEL;
2276
162
        ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
2277
162
        if (i) {
2278
158
            if ( (ll==1) || (ll==2) || (ll==3) )
2279
90
                dsc->language_level = ll;
2280
68
            else {
2281
68
                dsc_unknown(dsc);
2282
68
            }
2283
158
        }
2284
4
        else
2285
4
            dsc_unknown(dsc);
2286
162
    }
2287
61.7k
    else if (IS_DSC(line, "%%BoundingBox:")) {
2288
9.36k
        dsc->id = CDSC_BOUNDINGBOX;
2289
9.36k
        if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
2290
0
            return CDSC_ERROR;
2291
9.36k
    }
2292
52.4k
    else if (IS_DSC(line, "%%HiResBoundingBox:")) {
2293
60
        dsc->id = CDSC_HIRESBOUNDINGBOX;
2294
60
        if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
2295
60
            continued ? 3 : 19))
2296
0
            return CDSC_ERROR;
2297
60
    }
2298
52.3k
    else if (IS_DSC(line, "%%CropBox:")) {
2299
2
        dsc->id = CDSC_CROPBOX;
2300
2
        if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
2301
2
            continued ? 3 : 10))
2302
0
            return CDSC_ERROR;
2303
2
    }
2304
52.3k
    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
52.3k
    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
52.3k
    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
52.3k
    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
52.3k
    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
52.3k
    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
52.3k
    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
52.3k
    else if (IS_DSC(line, "%%DocumentData:")) {
2469
15
        unsigned int n = continued ? 3 : 15;
2470
15
        char *p = dsc->line + n;
2471
30
        while (IS_WHITE(*p))
2472
15
            p++;
2473
15
        dsc->id = CDSC_DOCUMENTDATA;
2474
15
        if (COMPARE(p, "Clean7Bit"))
2475
15
            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
15
    }
2483
52.3k
    else if (IS_DSC(line, "%%Requirements:")) {
2484
0
        dsc->id = CDSC_REQUIREMENTS;
2485
        /* ignore */
2486
0
    }
2487
52.3k
    else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
2488
44
        dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
2489
        /* ignore */
2490
44
    }
2491
52.2k
    else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
2492
0
        dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
2493
        /* ignore */
2494
0
    }
2495
52.2k
    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
52.2k
    else if (IS_DSC(line, "%%CyanPlate:") ||
2501
52.2k
        IS_DSC(line, "%%MagentaPlate:") ||
2502
52.2k
        IS_DSC(line, "%%YellowPlate:") ||
2503
52.2k
        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
52.2k
    else if (IS_DSC(line, "%%DocumentProcessColors:")) {
2509
114
        dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
2510
114
        if (dsc_parse_process_colours(dsc) != CDSC_OK)
2511
0
            dsc->id = CDSC_UNKNOWNDSC;
2512
114
    }
2513
52.1k
    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
52.1k
    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
52.1k
    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
52.1k
    else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
2529
0
        dsc->id = CDSC_OK;
2530
        /* ignore */
2531
0
    }
2532
52.1k
    else {
2533
52.1k
        dsc->id = CDSC_UNKNOWNDSC;
2534
52.1k
        dsc_unknown(dsc);
2535
52.1k
    }
2536
2537
113k
    dsc->endcomments = DSC_END(dsc);
2538
113k
    return CDSC_OK;
2539
113k
}
2540
2541
static int
2542
dsc_scan_preview(CDSC *dsc)
2543
1.99k
{
2544
    /* Preview section ends at */
2545
    /*  %%EndPreview */
2546
    /*  another section */
2547
    /* Preview section must start with %%BeginPreview */
2548
1.99k
    char *line = dsc->line;
2549
1.99k
    dsc->id = CDSC_OK;
2550
2551
1.99k
    if (dsc->scan_section == scan_pre_preview) {
2552
1.19k
        if (IS_BLANK(line))
2553
0
            return CDSC_OK; /* ignore blank lines before preview */
2554
1.19k
        else if (IS_DSC(line, "%%BeginPreview")) {
2555
33
            dsc->id = CDSC_BEGINPREVIEW;
2556
33
            dsc->beginpreview = DSC_START(dsc);
2557
33
            dsc->endpreview = DSC_END(dsc);
2558
33
            dsc->scan_section = scan_preview;
2559
            /* Don't mark the preview as EPSI if a DOS EPS header is present */
2560
33
            if (dsc->preview == CDSC_NOPREVIEW)
2561
33
                dsc->preview = CDSC_EPSI;
2562
33
            return CDSC_OK;
2563
33
        }
2564
1.16k
        else {
2565
1.16k
            dsc->scan_section = scan_pre_defaults;
2566
1.16k
            return CDSC_PROPAGATE;
2567
1.16k
        }
2568
1.19k
    }
2569
2570
794
    if (IS_DSC(line, "%%BeginPreview")) {
2571
        /* ignore because we are in this section */
2572
63
    }
2573
731
    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
731
    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
731
    else if (line[0] == '%' && line[1] != '%') {
2585
        /* Ordinary comments are OK */
2586
73
    }
2587
658
    else {
2588
658
        dsc->id = CDSC_UNKNOWNDSC;
2589
        /* DSC comments should not occur in preview */
2590
658
        dsc_unknown(dsc);
2591
658
    }
2592
2593
794
    dsc->endpreview = DSC_END(dsc);
2594
794
    return CDSC_OK;
2595
794
}
2596
2597
static int
2598
dsc_scan_defaults(CDSC *dsc)
2599
1.62k
{
2600
    /* Defaults section ends at */
2601
    /*  %%EndDefaults */
2602
    /*  another section */
2603
    /* Defaults section must start with %%BeginDefaults */
2604
1.62k
    char *line = dsc->line;
2605
1.62k
    dsc->id = CDSC_OK;
2606
2607
1.62k
    if (dsc->scan_section == scan_pre_defaults) {
2608
1.16k
        if (IS_BLANK(line))
2609
0
            return CDSC_OK; /* ignore blank lines before defaults */
2610
1.16k
        else if (IS_DSC(line, "%%BeginDefaults")) {
2611
26
            dsc->id = CDSC_BEGINDEFAULTS;
2612
26
            dsc->begindefaults = DSC_START(dsc);
2613
26
            dsc->enddefaults = DSC_END(dsc);
2614
26
            dsc->scan_section = scan_defaults;
2615
26
            return CDSC_OK;
2616
26
        }
2617
1.13k
        else {
2618
1.13k
            dsc->scan_section = scan_pre_prolog;
2619
1.13k
            return CDSC_PROPAGATE;
2620
1.13k
        }
2621
1.16k
    }
2622
2623
458
    if (NOT_DSC_LINE(line)) {
2624
        /* ignore */
2625
15
    }
2626
443
    else if (IS_DSC(line, "%%BeginPreview")) {
2627
        /* ignore because we have already processed this section */
2628
0
    }
2629
443
    else if (IS_DSC(line, "%%BeginDefaults")) {
2630
        /* ignore because we are in this section */
2631
10
    }
2632
433
    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
433
    else if (IS_DSC(line, "%%EndDefaults")) {
2638
8
        dsc->id = CDSC_ENDDEFAULTS;
2639
8
        dsc->enddefaults = DSC_END(dsc);
2640
8
        dsc->scan_section = scan_pre_prolog;
2641
8
        return CDSC_OK;
2642
8
    }
2643
425
    else if (IS_DSC(line, "%%PageMedia:")) {
2644
0
        dsc->id = CDSC_PAGEMEDIA;
2645
0
        dsc_parse_media(dsc, &dsc->page_media);
2646
0
    }
2647
425
    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
425
    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
425
    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
425
    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
425
    else {
2669
425
        dsc->id = CDSC_UNKNOWNDSC;
2670
        /* All other DSC comments are unknown, but not an error */
2671
425
        dsc_unknown(dsc);
2672
425
    }
2673
450
    dsc->enddefaults = DSC_END(dsc);
2674
450
    return CDSC_OK;
2675
458
}
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
4.03k
{
2682
4.03k
    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
4.03k
    return CDSC_RESPONSE_CANCEL;
2693
4.03k
}
2694
2695
static int
2696
dsc_check_match_type(CDSC *dsc, const char *str, int count)
2697
4.03k
{
2698
4.03k
    if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
2699
0
        return CDSC_NOTDSC;
2700
4.03k
    return CDSC_OK;
2701
4.03k
}
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
1.00k
{
2708
1.00k
    int rc = 0;
2709
1.00k
    const char *font = "Font";
2710
1.00k
    const char *feature = "Feature";
2711
1.00k
    const char *resource = "Resource";
2712
1.00k
    const char *procset = "ProcSet";
2713
2714
1.00k
    if (!rc)
2715
1.00k
        rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
2716
1.00k
    if (!rc)
2717
1.00k
        rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
2718
1.00k
    if (!rc)
2719
1.00k
        rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
2720
1.00k
    if (!rc)
2721
1.00k
        rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
2722
2723
1.00k
    dsc->begin_font_count = 0;
2724
1.00k
    dsc->begin_feature_count = 0;
2725
1.00k
    dsc->begin_resource_count = 0;
2726
1.00k
    dsc->begin_procset_count = 0;
2727
1.00k
    return rc;
2728
1.00k
}
2729
2730
static int
2731
dsc_scan_prolog(CDSC *dsc)
2732
18.8k
{
2733
    /* Prolog section ends at */
2734
    /*  %%EndProlog */
2735
    /*  another section */
2736
    /* Prolog section may start with %%BeginProlog or non-dsc line */
2737
18.8k
    char *line = dsc->line;
2738
18.8k
    dsc->id = CDSC_OK;
2739
2740
18.8k
    if (dsc->scan_section == scan_pre_prolog) {
2741
1.14k
        if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
2742
335
            dsc->scan_section = scan_pre_setup;
2743
335
            return CDSC_PROPAGATE;
2744
335
        }
2745
811
        dsc->id = CDSC_BEGINPROLOG;
2746
811
        dsc->beginprolog = DSC_START(dsc);
2747
811
        dsc->endprolog = DSC_END(dsc);
2748
811
        dsc->scan_section = scan_prolog;
2749
811
        if (IS_DSC(line, "%%BeginProlog"))
2750
114
            return CDSC_OK;
2751
811
    }
2752
2753
18.4k
    if (NOT_DSC_LINE(line)) {
2754
        /* ignore */
2755
286
    }
2756
18.1k
    else if (IS_DSC(line, "%%BeginPreview")) {
2757
        /* ignore because we have already processed this section */
2758
20
    }
2759
18.1k
    else if (IS_DSC(line, "%%BeginDefaults")) {
2760
        /* ignore because we have already processed this section */
2761
25
    }
2762
18.1k
    else if (IS_DSC(line, "%%BeginProlog")) {
2763
        /* ignore because we are in this section */
2764
26
    }
2765
18.0k
    else if (dsc_is_section(line)) {
2766
86
        dsc->endprolog = DSC_START(dsc);
2767
86
        dsc->scan_section = scan_pre_setup;
2768
86
        if (dsc_check_match(dsc))
2769
0
            return CDSC_NOTDSC;
2770
86
        return CDSC_PROPAGATE;
2771
86
    }
2772
18.0k
    else if (IS_DSC(line, "%%EndProlog")) {
2773
314
        dsc->id = CDSC_ENDPROLOG;
2774
314
        dsc->endprolog = DSC_END(dsc);
2775
314
        dsc->scan_section = scan_pre_setup;
2776
314
        if (dsc_check_match(dsc))
2777
0
            return CDSC_NOTDSC;
2778
314
        return CDSC_OK;
2779
314
    }
2780
17.6k
    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
17.6k
    else if (IS_DSC(line, "%%EndFont")) {
2787
0
        dsc->id = CDSC_ENDFONT;
2788
0
        dsc->begin_font_count--;
2789
0
    }
2790
17.6k
    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
17.6k
    else if (IS_DSC(line, "%%EndFeature")) {
2797
0
        dsc->id = CDSC_ENDFEATURE;
2798
0
        dsc->begin_feature_count--;
2799
0
    }
2800
17.6k
    else if (IS_DSC(line, "%%BeginResource:")) {
2801
60
        dsc->id = CDSC_BEGINRESOURCE;
2802
        /* ignore Begin/EndResource, apart form making sure */
2803
        /* that they are matched. */
2804
60
        dsc->begin_resource_count++;
2805
60
    }
2806
17.6k
    else if (IS_DSC(line, "%%EndResource")) {
2807
11
        dsc->id = CDSC_ENDRESOURCE;
2808
11
        dsc->begin_resource_count--;
2809
11
    }
2810
17.6k
    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
17.6k
    else if (IS_DSC(line, "%%EndProcSet")) {
2817
0
        dsc->id = CDSC_ENDPROCSET;
2818
0
        dsc->begin_procset_count--;
2819
0
    }
2820
17.6k
    else {
2821
        /* All other DSC comments are unknown, but not an error */
2822
17.6k
        dsc->id = CDSC_UNKNOWNDSC;
2823
17.6k
        dsc_unknown(dsc);
2824
17.6k
    }
2825
2826
18.0k
    dsc->endprolog = DSC_END(dsc);
2827
18.0k
    return CDSC_OK;
2828
18.4k
}
2829
2830
static int
2831
dsc_scan_setup(CDSC *dsc)
2832
5.78k
{
2833
    /* Setup section ends at */
2834
    /*  %%EndSetup */
2835
    /*  another section */
2836
    /* Setup section must start with %%BeginSetup */
2837
2838
5.78k
    char *line = dsc->line;
2839
5.78k
    dsc->id = CDSC_OK;
2840
2841
5.78k
    if (dsc->scan_section == scan_pre_setup) {
2842
735
        if (IS_BLANK(line))
2843
0
            return CDSC_OK; /* ignore blank lines before setup */
2844
735
        else if (IS_DSC(line, "%%BeginSetup")) {
2845
116
            dsc->id = CDSC_BEGINSETUP;
2846
116
            dsc->beginsetup = DSC_START(dsc);
2847
116
            dsc->endsetup = DSC_END(dsc);
2848
116
            dsc->scan_section = scan_setup;
2849
116
            return CDSC_OK;
2850
116
        }
2851
619
        else {
2852
619
            dsc->scan_section = scan_pre_pages;
2853
619
            return CDSC_PROPAGATE;
2854
619
        }
2855
735
    }
2856
2857
5.04k
    if (NOT_DSC_LINE(line)) {
2858
        /* ignore */
2859
2.08k
    }
2860
2.96k
    else if (IS_DSC(line, "%%BeginPreview")) {
2861
        /* ignore because we have already processed this section */
2862
0
    }
2863
2.96k
    else if (IS_DSC(line, "%%BeginDefaults")) {
2864
        /* ignore because we have already processed this section */
2865
0
    }
2866
2.96k
    else if (IS_DSC(line, "%%BeginProlog")) {
2867
        /* ignore because we have already processed this section */
2868
0
    }
2869
2.96k
    else if (IS_DSC(line, "%%BeginSetup")) {
2870
        /* ignore because we are in this section */
2871
1.06k
    }
2872
1.90k
    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
1.90k
    else if (IS_DSC(line, "%%EndSetup")) {
2880
56
        dsc->id = CDSC_ENDSETUP;
2881
56
        dsc->endsetup = DSC_END(dsc);
2882
56
        dsc->scan_section = scan_pre_pages;
2883
56
        if (dsc_check_match(dsc))
2884
0
            return CDSC_NOTDSC;
2885
56
        return CDSC_OK;
2886
56
    }
2887
1.85k
    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
1.85k
    else if (IS_DSC(line, "%%EndFeature")) {
2894
0
        dsc->id = CDSC_ENDFEATURE;
2895
0
        dsc->begin_feature_count--;
2896
0
    }
2897
1.85k
    else if (IS_DSC(line, "%%Feature:")) {
2898
0
        dsc->id = CDSC_FEATURE;
2899
        /* ignore */
2900
0
    }
2901
1.85k
    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
1.85k
    else if (IS_DSC(line, "%%EndResource")) {
2908
0
        dsc->id = CDSC_ENDRESOURCE;
2909
0
        dsc->begin_resource_count--;
2910
0
    }
2911
1.85k
    else if (IS_DSC(line, "%%PaperColor:")) {
2912
0
        dsc->id = CDSC_PAPERCOLOR;
2913
        /* ignore */
2914
0
    }
2915
1.85k
    else if (IS_DSC(line, "%%PaperForm:")) {
2916
0
        dsc->id = CDSC_PAPERFORM;
2917
        /* ignore */
2918
0
    }
2919
1.85k
    else if (IS_DSC(line, "%%PaperWeight:")) {
2920
0
        dsc->id = CDSC_PAPERWEIGHT;
2921
        /* ignore */
2922
0
    }
2923
1.85k
    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
1.85k
    else {
2957
        /* All other DSC comments are unknown, but not an error */
2958
1.85k
        dsc->id = CDSC_UNKNOWNDSC;
2959
1.85k
        dsc_unknown(dsc);
2960
1.85k
    }
2961
2962
4.99k
    dsc->endsetup = DSC_END(dsc);
2963
4.99k
    return CDSC_OK;
2964
5.04k
}
2965
2966
static int
2967
dsc_scan_page(CDSC *dsc)
2968
10.1k
{
2969
    /* Page section ends at */
2970
    /*  %%Page */
2971
    /*  %%Trailer */
2972
    /*  %%EOF */
2973
10.1k
    char *line = dsc->line;
2974
10.1k
    dsc->id = CDSC_OK;
2975
2976
10.1k
    if (dsc->scan_section == scan_pre_pages) {
2977
4.93k
        if (IS_DSC(line, "%%Page:")) {
2978
1.18k
            dsc->scan_section = scan_pages;
2979
            /* fall through */
2980
1.18k
        }
2981
3.74k
        else  {
2982
            /* %%Page: didn't follow %%EndSetup
2983
             * Keep reading until reach %%Page or %%Trailer
2984
             * and add it to previous section.
2985
             */
2986
3.74k
            DSC_OFFSET *last;
2987
3.74k
            if (dsc->endsetup != 0)
2988
2.77k
                last = &dsc->endsetup;
2989
967
            else if (dsc->endprolog != 0)
2990
144
                last = &dsc->endprolog;
2991
823
            else if (dsc->enddefaults != 0)
2992
0
                last = &dsc->enddefaults;
2993
823
            else if (dsc->endpreview != 0)
2994
0
                last = &dsc->endpreview;
2995
823
            else if (dsc->endcomments != 0)
2996
823
                last = &dsc->endcomments;
2997
0
            else
2998
0
                last = &dsc->begincomments;
2999
3.74k
            *last = DSC_START(dsc);
3000
3.74k
            if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
3001
35
                dsc->scan_section = scan_pre_trailer;
3002
35
                return CDSC_PROPAGATE;
3003
35
            }
3004
3.71k
            *last = DSC_END(dsc);
3005
3.71k
            return CDSC_OK;
3006
3.74k
        }
3007
4.93k
    }
3008
3009
6.44k
    if (NOT_DSC_LINE(line)) {
3010
        /* ignore */
3011
402
    }
3012
6.04k
    else if (IS_DSC(line, "%%Page:")) {
3013
1.72k
        int code;
3014
1.72k
        dsc->id = CDSC_PAGE;
3015
1.72k
        if (dsc->page_count) {
3016
536
            dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3017
536
            if (dsc_check_match(dsc))
3018
0
                return CDSC_NOTDSC;
3019
536
        }
3020
3021
1.72k
        if ( (code = dsc_parse_page(dsc)) != CDSC_OK)
3022
0
            return code;
3023
1.72k
        if (dsc->page_count == 0)
3024
699
            dsc->scan_section = scan_pre_pages;
3025
1.72k
    }
3026
4.31k
    else if (IS_DSC(line, "%%BeginPreview")) {
3027
        /* ignore because we have already processed this section */
3028
0
    }
3029
4.31k
    else if (IS_DSC(line, "%%BeginDefaults")) {
3030
        /* ignore because we have already processed this section */
3031
3
    }
3032
4.31k
    else if (IS_DSC(line, "%%BeginProlog")) {
3033
        /* ignore because we have already processed this section */
3034
0
    }
3035
4.31k
    else if (IS_DSC(line, "%%BeginSetup")) {
3036
        /* ignore because we have already processed this section */
3037
0
    }
3038
4.31k
    else if (dsc_is_section(line)) {
3039
16
        if (IS_DSC(line, "%%Trailer")) {
3040
16
            if (dsc->page_count)
3041
16
                dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3042
16
            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
16
            else {
3071
16
                dsc->scan_section = scan_pre_trailer;
3072
16
                if (dsc_check_match(dsc))
3073
0
                    return CDSC_NOTDSC;
3074
16
                return CDSC_PROPAGATE;
3075
16
            }
3076
16
        }
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
16
    }
3119
4.29k
    else if (IS_DSC(line, "%%PageTrailer")) {
3120
1
        dsc->id = CDSC_PAGETRAILER;
3121
        /* ignore */
3122
1
    }
3123
4.29k
    else if (IS_DSC(line, "%%BeginPageSetup")) {
3124
13
        dsc->id = CDSC_BEGINPAGESETUP;
3125
        /* ignore */
3126
13
    }
3127
4.28k
    else if (IS_DSC(line, "%%EndPageSetup")) {
3128
13
        dsc->id = CDSC_ENDPAGESETUP;
3129
        /* ignore */
3130
13
    }
3131
4.26k
    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
4.26k
    else if (IS_DSC(line, "%%PaperColor:")) {
3137
0
        dsc->id = CDSC_PAPERCOLOR;
3138
        /* ignore */
3139
0
    }
3140
4.26k
    else if (IS_DSC(line, "%%PaperForm:")) {
3141
0
        dsc->id = CDSC_PAPERFORM;
3142
        /* ignore */
3143
0
    }
3144
4.26k
    else if (IS_DSC(line, "%%PaperWeight:")) {
3145
0
        dsc->id = CDSC_PAPERWEIGHT;
3146
        /* ignore */
3147
0
    }
3148
4.26k
    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
4.26k
    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
4.26k
    else if (IS_DSC(line, "%%PageBoundingBox:")) {
3191
3
        if (dsc->page_count) {
3192
3
            dsc->id = CDSC_PAGEBOUNDINGBOX;
3193
3
            if (dsc_parse_bounding_box(dsc,
3194
3
                &dsc->page[dsc->page_count-1].bbox, 18))
3195
0
                return CDSC_NOTDSC;
3196
3
        }
3197
3
    }
3198
4.26k
    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
4.26k
    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
4.26k
    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
4.26k
    else if (IS_DSC(line, "%%EndFont")) {
3221
0
        dsc->id = CDSC_BEGINFONT;
3222
0
        dsc->begin_font_count--;
3223
0
    }
3224
4.26k
    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
4.26k
    else if (IS_DSC(line, "%%EndFeature")) {
3231
0
        dsc->id = CDSC_ENDFEATURE;
3232
0
        dsc->begin_feature_count--;
3233
0
    }
3234
4.26k
    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
4.26k
    else if (IS_DSC(line, "%%EndResource")) {
3241
0
        dsc->id = CDSC_ENDRESOURCE;
3242
0
        dsc->begin_resource_count--;
3243
0
    }
3244
4.26k
    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
4.26k
    else if (IS_DSC(line, "%%EndProcSet")) {
3251
0
        dsc->id = CDSC_ENDPROCSET;
3252
0
        dsc->begin_procset_count--;
3253
0
    }
3254
4.26k
    else if (IS_DSC(line, "%%IncludeFont:")) {
3255
0
        dsc->id = CDSC_INCLUDEFONT;
3256
        /* ignore */
3257
0
    }
3258
4.26k
    else {
3259
        /* All other DSC comments are unknown, but not an error */
3260
4.26k
        dsc->id = CDSC_UNKNOWNDSC;
3261
4.26k
        dsc_unknown(dsc);
3262
4.26k
    }
3263
3264
6.42k
    if (dsc->page_count)
3265
5.72k
        dsc->page[dsc->page_count-1].end = DSC_END(dsc);
3266
6.42k
    return CDSC_OK;
3267
6.44k
}
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
603
{
3318
    /* Trailer section start at */
3319
    /*  %%Trailer */
3320
    /* and ends at */
3321
    /*  %%EOF */
3322
603
    char *line = dsc->line;
3323
603
    GSBOOL continued = FALSE;
3324
3325
603
    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
603
    dsc->id = CDSC_OK;
3346
3347
603
    if (dsc->scan_section == scan_pre_trailer) {
3348
51
        if (IS_DSC(line, "%%Trailer")) {
3349
42
            dsc->id = CDSC_TRAILER;
3350
42
            dsc->begintrailer = DSC_START(dsc);
3351
42
            dsc->endtrailer = DSC_END(dsc);
3352
42
            dsc->scan_section = scan_trailer;
3353
42
            return CDSC_OK;
3354
42
        }
3355
9
        else if (IS_DSC(line, "%%EOF")) {
3356
9
            dsc->id = CDSC_EOF;
3357
9
            dsc->begintrailer = DSC_START(dsc);
3358
9
            dsc->endtrailer = DSC_END(dsc);
3359
9
            dsc->scan_section = scan_trailer;
3360
            /* Continue, in case we found %%EOF in an embedded document */
3361
9
            return CDSC_OK;
3362
9
        }
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
51
    }
3379
3380
    /* Handle continuation lines.
3381
     * See comment above about our restrictive processing of
3382
     * continuation lines
3383
     */
3384
552
    if (IS_DSC(line, "%%+")) {
3385
0
        line = dsc->last_line;
3386
0
        continued = TRUE;
3387
0
    }
3388
552
    else
3389
552
        dsc_save_line(dsc);
3390
3391
552
    if (NOT_DSC_LINE(line)) {
3392
        /* ignore */
3393
1
    }
3394
551
    else if (IS_DSC(dsc->line, "%%EOF")) {
3395
        /* Keep scanning, in case we have a false trailer */
3396
18
        dsc->id = CDSC_EOF;
3397
18
    }
3398
533
    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
26
        dsc->id = CDSC_TRAILER;
3402
26
        dsc->begintrailer = DSC_START(dsc);
3403
26
    }
3404
507
    else if (IS_DSC(line, "%%Pages:")) {
3405
31
        dsc->id = CDSC_PAGES;
3406
31
        if (dsc_parse_pages(dsc) != 0)
3407
0
               return CDSC_ERROR;
3408
31
    }
3409
476
    else if (IS_DSC(line, "%%BoundingBox:")) {
3410
2
        dsc->id = CDSC_BOUNDINGBOX;
3411
2
        if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
3412
0
            return CDSC_ERROR;
3413
2
    }
3414
474
    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
474
    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
474
    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
474
    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
474
    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
474
    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
474
    else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
3463
0
        dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
3464
        /* ignore */
3465
0
    }
3466
474
    else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
3467
0
        dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
3468
        /* ignore */
3469
0
    }
3470
474
    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
474
    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
474
    else {
3481
        /* All other DSC comments are unknown, but not an error */
3482
474
        dsc->id = CDSC_UNKNOWNDSC;
3483
474
        dsc_unknown(dsc);
3484
474
    }
3485
3486
552
    dsc->endtrailer = DSC_END(dsc);
3487
552
    return CDSC_OK;
3488
552
}
3489
3490
static char *
3491
dsc_alloc_string(CDSC *dsc, const char *str, int len)
3492
67.9k
{
3493
67.9k
    char *p;
3494
67.9k
    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
67.9k
    if ( dsc->string->index + len + 1 > dsc->string->length) {
3509
        /* allocate another string block */
3510
126
        CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3511
126
        if (newstring == NULL) {
3512
0
            dsc_debug_print(dsc, "Out of memory\n");
3513
0
            return NULL;
3514
0
        }
3515
126
        newstring->next = NULL;
3516
126
        newstring->length = 0;
3517
126
        newstring->index = 0;
3518
126
        newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3519
126
        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
126
        newstring->length = CDSC_STRING_CHUNK;
3525
126
        dsc->string->next = newstring;
3526
126
        dsc->string = newstring;
3527
126
    }
3528
67.9k
    if ( dsc->string->index + len + 1 > dsc->string->length)
3529
0
        return NULL; /* failed */
3530
67.9k
    p = dsc->string->data + dsc->string->index;
3531
67.9k
    memcpy(p, str, len);
3532
67.9k
    *(p+len) = '\0';
3533
67.9k
    dsc->string->index += len + 1;
3534
67.9k
    return p;
3535
67.9k
}
3536
3537
/* store line, ignoring leading spaces */
3538
static char *
3539
dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
3540
67.1k
{
3541
67.1k
    char *newline;
3542
67.1k
    unsigned int i;
3543
116k
    while (len && (IS_WHITE(*line))) {
3544
49.7k
        len--;
3545
49.7k
        line++;
3546
49.7k
    }
3547
67.1k
    newline = dsc_alloc_string(dsc, line, len);
3548
67.1k
    if (newline == NULL)
3549
0
        return NULL;
3550
3551
1.94M
    for (i=0; i<len; i++) {
3552
1.94M
        if (newline[i] == '\r') {
3553
67.1k
            newline[i]='\0';
3554
67.1k
            break;
3555
67.1k
        }
3556
1.87M
        if (newline[i] == '\n') {
3557
0
            newline[i]='\0';
3558
0
            break;
3559
0
        }
3560
1.87M
    }
3561
67.1k
    return newline;
3562
67.1k
}
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
2.30k
{
3574
2.30k
    int quoted = FALSE;
3575
2.30k
    int instring=0;
3576
2.30k
    unsigned int newlength = 0;
3577
2.30k
    unsigned int i = 0;
3578
2.30k
    unsigned char ch;
3579
2.30k
    if (len > slen)
3580
0
        len = slen-1;
3581
3.25k
    while ( (i<len) && IS_WHITE(line[i]))
3582
949
        i++; /* skip leading spaces */
3583
2.30k
    if ((i < len) && (line[i]=='(')) {
3584
1
        quoted = TRUE;
3585
1
        instring++;
3586
1
        i++; /* don't copy outside () */
3587
1
    }
3588
14.5k
    while (i < len) {
3589
14.4k
        str[newlength] = ch = line[i];
3590
14.4k
        i++;
3591
14.4k
        if (quoted) {
3592
7
            if (ch == '(')
3593
0
                    instring++;
3594
7
            if (ch == ')')
3595
1
                    instring--;
3596
7
            if (instring==0)
3597
1
                    break;
3598
7
        }
3599
14.4k
        else if (ch == ' ')
3600
1.35k
            break;
3601
3602
13.1k
        if (ch == '\r')
3603
836
            break;
3604
12.2k
        if (ch == '\n')
3605
0
            break;
3606
12.2k
        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
12.2k
        newlength++;
3653
12.2k
    }
3654
2.30k
    str[newlength] = '\0';
3655
2.30k
    if (offset != (unsigned int *)NULL)
3656
2.30k
        *offset = i;
3657
2.30k
    return str;
3658
2.30k
}
3659
3660
static int
3661
dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
3662
14.0k
{
3663
14.0k
    char newline[MAXSTR];
3664
14.0k
    int newlength = 0;
3665
14.0k
    unsigned int i = 0;
3666
14.0k
    unsigned char ch;
3667
3668
14.0k
    len = min(len, sizeof(newline)-1);
3669
14.1k
    while ((i<len) && IS_WHITE(line[i]))
3670
102
        i++; /* skip leading spaces */
3671
37.5k
    while (i < len) {
3672
37.5k
        newline[newlength] = ch = line[i];
3673
37.5k
        if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
3674
14.0k
            break;  /* not part of an integer number */
3675
23.5k
        i++;
3676
23.5k
        newlength++;
3677
23.5k
    }
3678
22.2k
    while ((i<len) && IS_WHITE(line[i]))
3679
8.28k
        i++; /* skip trailing spaces */
3680
14.0k
    newline[newlength] = '\0';
3681
14.0k
    if (offset != (unsigned int *)NULL)
3682
12.2k
        *offset = i;
3683
14.0k
    return atoi(newline);
3684
14.0k
}
3685
3686
static float
3687
dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
3688
2.42k
{
3689
2.42k
    char newline[MAXSTR];
3690
2.42k
    int newlength = 0;
3691
2.42k
    unsigned int i = 0;
3692
2.42k
    unsigned char ch;
3693
3694
2.42k
    len = min(len, sizeof(newline)-1);
3695
2.42k
    while ((i<len) && IS_WHITE(line[i]))
3696
0
        i++; /* skip leading spaces */
3697
6.30k
    while (i < len) {
3698
6.30k
        newline[newlength] = ch = line[i];
3699
6.30k
        if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
3700
6.30k
            || (ch=='e') || (ch=='E')))
3701
2.42k
            break;  /* not part of a real number */
3702
3.87k
        i++;
3703
3.87k
        newlength++;
3704
3.87k
    }
3705
3.71k
    while ((i<len) && IS_WHITE(line[i]))
3706
1.28k
        i++; /* skip trailing spaces */
3707
3708
2.42k
    newline[newlength] = '\0';
3709
3710
2.42k
    if (offset != (unsigned int *)NULL)
3711
2.42k
        *offset = i;
3712
2.42k
    return (float)atof(newline);
3713
2.42k
}
3714
3715
int
3716
dsc_stricmp(const char *s, const char *t)
3717
3.18k
{
3718
8.59k
    while (toupper((unsigned char)*s) == toupper((unsigned char)*t)) {
3719
5.74k
        if (*s == '\0')
3720
341
            return 0;
3721
5.40k
        s++;
3722
5.40k
        t++;
3723
5.40k
    }
3724
2.84k
    return (toupper((unsigned char)*s) - toupper((unsigned char)*t));
3725
3.18k
}
3726
3727
static int
3728
dsc_parse_page(CDSC *dsc)
3729
1.72k
{
3730
1.72k
    char *p;
3731
1.72k
    unsigned int i;
3732
1.72k
    char page_label[MAXSTR];
3733
1.72k
    char *pl;
3734
1.72k
    int page_ordinal;
3735
1.72k
    int page_number;
3736
3737
1.72k
    p = dsc->line + 7;
3738
1.72k
    pl = dsc_copy_string(page_label, sizeof(page_label), p, dsc->line_length-7, &i);
3739
1.72k
    if (pl == NULL)
3740
0
        return CDSC_ERROR;
3741
1.72k
    p += i;
3742
1.72k
    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
1.44k
        while (i > 0) {
3746
786
            if (!IS_WHITE_OR_EOL(p[-1]))
3747
62
                break;
3748
724
            p--;
3749
724
            i--;
3750
724
        }
3751
763
        while (i > 0) {
3752
94
            if (!isdigit((int)p[-1]))
3753
53
                break;
3754
41
            p--;
3755
41
            i--;
3756
41
        }
3757
722
    }
3758
1.72k
    page_ordinal = dsc_get_int(p, dsc->line_length - 7 - i, NULL);
3759
3760
1.72k
    if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
3761
1.72k
       (dsc->page_count &&
3762
1.23k
            (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
3763
1.23k
        int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
3764
1.23k
                dsc->line_length);
3765
1.23k
        switch (rc) {
3766
1.23k
            case CDSC_RESPONSE_OK:
3767
                /* ignore this page */
3768
1.23k
                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
1.23k
        }
3775
1.23k
    }
3776
3777
490
    page_number = dsc->page_count;
3778
490
    dsc_add_page(dsc, page_ordinal, page_label);
3779
490
    dsc->page[page_number].begin = DSC_START(dsc);
3780
490
    dsc->page[page_number].end = DSC_START(dsc);
3781
3782
490
    if (dsc->page[page_number].label == NULL)
3783
0
        return CDSC_ERROR; /* no memory */
3784
3785
490
    return CDSC_OK;
3786
490
}
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
9.00k
{
3813
    /* if error function provided, use it */
3814
9.00k
    if (dsc->dsc_error_fn)
3815
9.00k
        return dsc->dsc_error_fn(dsc->caller_data, dsc,
3816
9.00k
            explanation, line, line_len);
3817
3818
    /* treat DSC as being correct */
3819
0
    return CDSC_RESPONSE_CANCEL;
3820
9.00k
}
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
        unsigned 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
        page_number = dsc->page_count - 1;
3852
0
        pbegin = &dsc->page[page_number].begin;
3853
0
        pend = &dsc->page[page_number].end;
3854
0
        if (*pbegin == *pend) {
3855
            /* no page, so force it to conform to the following sections */
3856
0
            *pbegin = 999999999;
3857
0
            *pend = 0;
3858
0
        }
3859
3860
0
        if (dsc->begincomments != dsc->endcomments) {
3861
0
            *pbegin = min(dsc->begincomments, *pbegin);
3862
0
            dsc->begincomments = 0;
3863
0
            *pend = max(dsc->endcomments, *pend);
3864
0
            dsc->endcomments = 0;
3865
0
        }
3866
3867
0
        if (dsc->beginpreview != dsc->endpreview) {
3868
0
            *pbegin = min(dsc->beginpreview, *pbegin);
3869
0
            dsc->beginpreview = 0;
3870
0
            *pend = max(dsc->endpreview, *pend);
3871
0
            dsc->endpreview = 0;
3872
0
        }
3873
3874
0
        if (dsc->begindefaults != dsc->enddefaults) {
3875
0
            *pbegin = min(dsc->begindefaults, *pbegin);
3876
0
            dsc->begindefaults = 0;
3877
0
            *pend = max(dsc->enddefaults, *pend);
3878
0
            dsc->enddefaults = 0;
3879
0
        }
3880
3881
0
        if (dsc->beginprolog != dsc->endprolog) {
3882
0
            *pbegin = min(dsc->beginprolog, *pbegin);
3883
0
            dsc->beginprolog = 0;
3884
0
            *pend = max(dsc->endprolog, *pend);
3885
0
            dsc->endprolog = 0;
3886
0
        }
3887
3888
0
        if (dsc->beginsetup != dsc->endsetup) {
3889
0
            *pbegin = min(dsc->beginsetup, *pbegin);
3890
0
            dsc->beginsetup = 0;
3891
0
            *pend = max(dsc->endsetup, *pend);
3892
0
            dsc->endsetup = 0;
3893
0
        }
3894
3895
0
        if (dsc->begintrailer != dsc->endtrailer) {
3896
0
            *pbegin = min(dsc->begintrailer, *pbegin);
3897
0
            dsc->begintrailer = 0;
3898
0
            *pend = max(dsc->endtrailer, *pend);
3899
0
            dsc->endtrailer = 0;
3900
0
        }
3901
3902
0
        if (*pbegin == 999999999)
3903
0
            *pbegin = *pend;
3904
0
        end = 0;  /* end of composite is start of first separation */
3905
3906
        /* we used to do this where the pointer is declared, but Coverity points out
3907
         * that dsc_alloc_string can call dsc_reset which can free dsc and dsc->dcs2.
3908
         * By deferring the initialisation to here we can ensure we don't have a
3909
         * dangling pointer. This makes me suspiciouos that DCS (not DSC!) comments
3910
         * have never worked properly.
3911
         */
3912
0
        pdcs = dsc->dcs2;
3913
3914
0
        while (pdcs) {
3915
0
            page_number = dsc->page_count;
3916
0
            if ((pdcs->begin) && (pdcs->colourname != NULL)) {
3917
                /* Single file DCS 2.0 */
3918
0
                code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3919
0
                if (code)
3920
0
                    return code;
3921
0
                dsc->page[page_number].begin = pdcs->begin;
3922
0
                dsc->page[page_number].end = pdcs->end;
3923
0
                if (end != 0)
3924
0
                    end = min(end, pdcs->begin);
3925
0
                else
3926
0
                    end = pdcs->begin;   /* first separation  */
3927
0
                pend = &dsc->page[page_number+1].end;
3928
0
            }
3929
0
            else {
3930
                /* Multiple file DCS 2.0 */
3931
0
                if ((pdcs->location != NULL) &&
3932
0
                    (pdcs->filetype != NULL) &&
3933
0
                    (pdcs->colourname != NULL) &&
3934
0
                    (dsc_stricmp(pdcs->location, "Local") == 0) &&
3935
0
                    ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
3936
0
                     (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
3937
0
                    code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3938
0
                    if (code)
3939
0
                        return code;
3940
0
                    dsc->page[page_number].begin = 0;
3941
0
                    dsc->page[page_number].end = 0;
3942
0
                }
3943
0
            }
3944
0
            pdcs = pdcs->next;
3945
0
        }
3946
        /* end of composite is start of first separation */
3947
0
        if (end != 0)
3948
0
            *pend = end;
3949
        /* According to the DCS2 specification, the size of the composite
3950
         * section can be determined by the smallest #offset.
3951
         * Some incorrect DCS2 files don't put the separations inside
3952
         * the DOS EPS PostScript section, and have a TIFF separation
3953
         * between the composite and the first separation.  This
3954
         * contravenes the DCS2 specification.  If we see one of these
3955
         * files, bring the end of the composite back to the end of
3956
         * the DOS EPS PostScript section.
3957
         */
3958
0
        if (dsc->doseps_end && (*pend > dsc->doseps_end))
3959
0
            *pend = dsc->doseps_end;
3960
0
    }
3961
0
    return 0;
3962
0
}
3963
3964
static int
3965
dsc_parse_platefile(CDSC *dsc)
3966
0
{
3967
0
    unsigned int i, n;
3968
0
    CDCS2 dcs2;
3969
0
    CDCS2 *pdcs2;
3970
0
    char colourname[MAXSTR];
3971
0
    char filetype[MAXSTR];
3972
0
    char location[MAXSTR];
3973
0
    char *filename = NULL;
3974
0
    int filename_length = 0;
3975
0
    GSBOOL blank_line;
3976
0
    GSBOOL single = FALSE;
3977
0
    if (IS_DSC(dsc->line, "%%PlateFile:"))
3978
0
        n = 12;
3979
0
    else if (IS_DSC(dsc->line, "%%+"))
3980
0
        n = 3;
3981
0
    else
3982
0
        return CDSC_ERROR; /* error */
3983
3984
0
    memset(&dcs2, 0, sizeof(dcs2));
3985
0
    memset(&colourname, 0, sizeof(colourname));
3986
0
    memset(&filetype, 0, sizeof(filetype));
3987
0
    memset(&location, 0, sizeof(location));
3988
0
    memset(&filename, 0, sizeof(filename));
3989
3990
    /* check for blank remainder of line */
3991
0
    blank_line = TRUE;
3992
0
    for (i=n; i<dsc->line_length; i++) {
3993
0
        if (!IS_WHITE_OR_EOL(dsc->line[i])) {
3994
0
            blank_line = FALSE;
3995
0
            break;
3996
0
        }
3997
0
    }
3998
3999
0
    if (!blank_line) {
4000
0
        dsc_copy_string(colourname, sizeof(colourname),
4001
0
                dsc->line+n, dsc->line_length-n, &i);
4002
0
        n+=i;
4003
0
        if (i)
4004
0
            dsc_copy_string(filetype, sizeof(filetype),
4005
0
                dsc->line+n, dsc->line_length-n, &i);
4006
0
        n+=i;
4007
0
        while (IS_WHITE_OR_EOL(dsc->line[n]))
4008
0
            n++;
4009
0
        if (dsc->line[n] == '#') {
4010
            /* single file DCS 2.0 */
4011
0
            single = TRUE;
4012
0
            n++;
4013
0
            if ( n + 4 > dsc->line_length) {
4014
0
                i = 0;
4015
0
            }
4016
0
            if (i) {
4017
0
                dcs2.begin= dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
4018
0
                n+=i;
4019
0
                if ( n + 4 > dsc->line_length) {
4020
0
                    i = 0;
4021
0
                }
4022
0
                if (i)
4023
0
                    dcs2.end= dcs2.begin +
4024
0
                        dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
4025
0
            }
4026
0
        }
4027
0
        else {
4028
            /* multiple file DCS 2.0 */
4029
0
            if ( n + sizeof(location) > dsc->line_length) {
4030
0
                i = 0;
4031
0
            }
4032
0
            if (i) {
4033
0
                dsc_copy_string(location, sizeof(location),
4034
0
                    dsc->line+n, dsc->line_length-n, &i);
4035
0
                n+=i;
4036
0
                if ( n > dsc->line_length) {
4037
0
                    i = 0;
4038
0
                }
4039
0
                if (i) {
4040
0
                    filename = dsc->line+n;
4041
0
                    filename_length = dsc->line_length-n;
4042
0
                }
4043
0
            }
4044
0
        }
4045
0
        if (i==0)
4046
0
            dsc_unknown(dsc); /* we didn't get all fields */
4047
0
        else {
4048
            /* Allocate strings */
4049
0
            if (strlen(colourname)) {
4050
0
                dcs2.colourname = dsc_alloc_string(dsc,
4051
0
                    colourname, (int)strlen(colourname));
4052
0
                if (dcs2.colourname == NULL)
4053
0
                    return CDSC_ERROR;
4054
0
            }
4055
0
            if (strlen(filetype)) {
4056
0
                dcs2.filetype = dsc_alloc_string(dsc,
4057
0
                    filetype, (int)strlen(filetype));
4058
0
                if (dcs2.filetype == NULL)
4059
0
                    return CDSC_ERROR;
4060
0
            }
4061
0
            if (strlen(location)) {
4062
0
                dcs2.location = dsc_alloc_string(dsc,
4063
0
                    location, (int)strlen(location));
4064
0
                if (dcs2.location == NULL)
4065
0
                    return CDSC_ERROR;
4066
0
            }
4067
0
            if (filename)
4068
0
                dcs2.filename = dsc_add_line(dsc, filename, filename_length);
4069
4070
            /* Prevent parser from reading separations */
4071
0
            if (single)
4072
0
                dsc->file_length = min(dsc->file_length, dcs2.begin);
4073
            /* Allocate it */
4074
0
            pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4075
0
            if (pdcs2 == NULL)
4076
0
                return CDSC_ERROR; /* out of memory */
4077
0
            memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4078
            /* Then add to list of separations */
4079
0
            if (dsc->dcs2 == NULL)
4080
0
                dsc->dcs2 = pdcs2;
4081
0
            else {
4082
0
                CDCS2 *this_dcs2 = dsc->dcs2;
4083
0
                while (this_dcs2->next)
4084
0
                    this_dcs2 = this_dcs2->next;
4085
0
                this_dcs2->next = pdcs2;
4086
0
            }
4087
0
        }
4088
0
    }
4089
0
    return CDSC_OK;
4090
0
}
4091
4092
/* Parse a DCS 1.0 plate comment, storing like a multi file DSC 2.0 */
4093
static int
4094
dsc_parse_dcs1plate(CDSC *dsc)
4095
0
{
4096
0
    unsigned int i, n = 0;
4097
0
    CDCS2 dcs2;
4098
0
    CDCS2 *pdcs2;
4099
0
    const char *colourname;
4100
0
    char filename[MAXSTR];
4101
0
    GSBOOL blank_line;
4102
0
    GSBOOL continued = FALSE;
4103
0
    char *line = dsc->line;
4104
4105
0
    memset(&dcs2, 0, sizeof(dcs2));
4106
0
    memset(&filename, 0, sizeof(filename));
4107
4108
0
    if (IS_DSC(line, "%%+")) {
4109
0
        n = 3;
4110
0
        line = dsc->last_line;
4111
0
        continued = TRUE;
4112
0
    }
4113
4114
0
    if (IS_DSC(line, "%%CyanPlate:")) {
4115
0
        colourname = "Cyan";
4116
0
        if (!continued)
4117
0
            n = 12;
4118
0
    }
4119
0
    else if (IS_DSC(line, "%%MagentaPlate:")) {
4120
0
        colourname = "Magenta";
4121
0
        if (!continued)
4122
0
            n = 15;
4123
0
    }
4124
0
    else if (IS_DSC(line, "%%YellowPlate:")) {
4125
0
        colourname = "Yellow";
4126
0
        if (!continued)
4127
0
            n = 14;
4128
0
    }
4129
0
    else if (IS_DSC(line, "%%BlackPlate:")) {
4130
0
        colourname = "Black";
4131
0
        if (!continued)
4132
0
            n = 13;
4133
0
    }
4134
0
    else
4135
0
        return CDSC_ERROR; /* error */
4136
4137
    /* check for blank remainder of line */
4138
0
    blank_line = TRUE;
4139
0
    for (i=n; i<dsc->line_length; i++) {
4140
0
        if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4141
0
            blank_line = FALSE;
4142
0
            break;
4143
0
        }
4144
0
    }
4145
4146
0
    if (!blank_line) {
4147
0
        dsc_copy_string(filename, sizeof(filename),
4148
0
                    dsc->line+n, dsc->line_length-n, &i);
4149
0
        if (i==0)
4150
0
            dsc_unknown(dsc); /* we didn't get all fields */
4151
0
        else {
4152
            /* Allocate strings */
4153
0
            dcs2.colourname = dsc_alloc_string(dsc,
4154
0
                    colourname, (int)strlen(colourname));
4155
0
            dcs2.filetype = dsc_alloc_string(dsc, "EPS", 3);
4156
0
            dcs2.location = dsc_alloc_string(dsc, "Local", 5);
4157
0
            if (dcs2.colourname == NULL || dcs2.filetype == NULL || dcs2.location == NULL) {
4158
0
                return CDSC_ERROR;
4159
0
            }
4160
0
            if (strlen(filename)) {
4161
0
                dcs2.filename = dsc_alloc_string(dsc,
4162
0
                    filename, (int)strlen(filename));
4163
0
                if (dcs2.filename == NULL)
4164
0
                    return CDSC_ERROR;
4165
0
            }
4166
            /* Allocate it */
4167
0
            pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4168
0
            if (pdcs2 == NULL)
4169
0
                return CDSC_ERROR; /* out of memory */
4170
0
            memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4171
            /* Then add to list of separations */
4172
0
            if (dsc->dcs2 == NULL)
4173
0
                dsc->dcs2 = pdcs2;
4174
0
            else {
4175
0
                CDCS2 *this_dcs2 = dsc->dcs2;
4176
0
                while (this_dcs2->next)
4177
0
                    this_dcs2 = this_dcs2->next;
4178
0
                this_dcs2->next = pdcs2;
4179
0
            }
4180
0
        }
4181
0
    }
4182
0
    return CDSC_OK;
4183
0
}
4184
4185
/* Find the filename which corresponds to this separation.
4186
 * Used with multiple file DCS 2.0.
4187
 * Returns NULL if there is no filename, or not DCS 2.0,
4188
 * or single file DCS 2.0.
4189
 * Caller will need to obtain the filesize from the file.
4190
 */
4191
const char *
4192
dsc_find_platefile(CDSC *dsc, int page)
4193
0
{
4194
0
    CDCS2 *pdcs = dsc->dcs2;
4195
0
    int i = 1;
4196
0
    while (pdcs) {
4197
0
        if (pdcs->begin != pdcs->end)
4198
0
            return NULL; /* Single file DCS 2.0 */
4199
0
        if (pdcs->location && pdcs->filetype && pdcs->colourname
4200
0
            && (dsc_stricmp(pdcs->location, "Local") == 0)
4201
0
            && ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
4202
0
                (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
4203
0
            if (i == page)
4204
0
                return pdcs->filename;
4205
0
            i++;
4206
0
        }
4207
0
        pdcs = pdcs->next;
4208
0
    }
4209
0
    return NULL;
4210
0
}
4211
4212
static CDSCCOLOUR *
4213
dsc_find_colour(CDSC *dsc, const char *colourname)
4214
413
{
4215
413
    CDSCCOLOUR *colour = dsc->colours;
4216
1.51k
    while (colour) {
4217
1.23k
        if (colour->name && (dsc_stricmp(colour->name, colourname)==0))
4218
134
            return colour;
4219
1.10k
        colour = colour->next;
4220
1.10k
    }
4221
279
    return 0;
4222
413
}
4223
4224
static int
4225
dsc_parse_process_colours(CDSC *dsc)
4226
114
{
4227
114
    unsigned int i, n;
4228
114
    CDSCCOLOUR *pcolour;
4229
114
    char colourname[MAXSTR];
4230
114
    GSBOOL blank_line;
4231
114
    if (IS_DSC(dsc->line, "%%DocumentProcessColors:"))
4232
114
        n = 24;
4233
0
    else if (IS_DSC(dsc->line, "%%+"))
4234
0
        n = 3;
4235
0
    else
4236
0
        return CDSC_ERROR; /* error */
4237
4238
114
    memset(&colourname, 0, sizeof(colourname));
4239
4240
    /* check for blank remainder of line */
4241
114
    blank_line = TRUE;
4242
226
    for (i=n; i<dsc->line_length; i++) {
4243
226
        if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4244
114
            blank_line = FALSE;
4245
114
            break;
4246
114
        }
4247
226
    }
4248
226
    while (IS_WHITE(dsc->line[n]))
4249
112
        n++;
4250
114
    if (COMPARE(dsc->line+n, "(atend)")) {
4251
0
        if (dsc->scan_section == scan_comments)
4252
0
            blank_line = TRUE;
4253
0
        else {
4254
0
            dsc_unknown(dsc);
4255
0
            return CDSC_NOTDSC;
4256
0
        }
4257
0
    }
4258
4259
114
    if (!blank_line) {
4260
576
        do {
4261
576
            dsc_copy_string(colourname, sizeof(colourname),
4262
576
                dsc->line+n, dsc->line_length-n, &i);
4263
576
            n+=i;
4264
576
            if (i && strlen(colourname)) {
4265
413
                if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4266
279
                    pcolour = (CDSCCOLOUR *)
4267
279
                        dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4268
279
                    if (pcolour == NULL)
4269
0
                        return CDSC_ERROR; /* out of memory */
4270
279
                    memset(pcolour, 0, sizeof(CDSCCOLOUR));
4271
279
                    pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4272
279
                    pcolour->name = dsc_alloc_string(dsc,
4273
279
                        colourname, (int)strlen(colourname));
4274
279
                    if (pcolour->name == NULL) {
4275
0
                        dsc_memfree(dsc, pcolour);
4276
0
                        return CDSC_ERROR;
4277
0
                    }
4278
279
                    if (dsc->colours == NULL)
4279
61
                        dsc->colours = pcolour;
4280
218
                    else {
4281
218
                        CDSCCOLOUR *this_colour = dsc->colours;
4282
693
                        while (this_colour->next)
4283
475
                            this_colour = this_colour->next;
4284
218
                        this_colour->next = pcolour;
4285
218
                    }
4286
279
                }
4287
413
                pcolour->type = CDSC_COLOUR_PROCESS;
4288
413
                if (dsc_stricmp(colourname, "Cyan")==0) {
4289
54
                    pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4290
54
                    pcolour->cyan = 1.0;
4291
54
                    pcolour->magenta = pcolour->yellow = pcolour->black = 0.0;
4292
54
                }
4293
359
                else if (dsc_stricmp(colourname, "Magenta")==0) {
4294
52
                    pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4295
52
                    pcolour->magenta = 1.0;
4296
52
                    pcolour->cyan = pcolour->yellow = pcolour->black = 0.0;
4297
52
                }
4298
307
                else if (dsc_stricmp(colourname, "Yellow")==0) {
4299
51
                    pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4300
51
                    pcolour->yellow = 1.0;
4301
51
                    pcolour->cyan = pcolour->magenta = pcolour->black = 0.0;
4302
51
                }
4303
256
                else if (dsc_stricmp(colourname, "Black")==0) {
4304
50
                    pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4305
50
                    pcolour->black = 1.0;
4306
50
                    pcolour->cyan = pcolour->magenta = pcolour->yellow = 0.0;
4307
50
                }
4308
206
                else if (dsc_stricmp(colourname, "Red")==0) {
4309
0
                    pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4310
0
                    pcolour->red = 1.0;
4311
0
                    pcolour->green = pcolour->blue = 0.0;
4312
0
                }
4313
206
                else if (dsc_stricmp(colourname, "Green")==0) {
4314
0
                    pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4315
0
                    pcolour->green = 1.0;
4316
0
                    pcolour->red = pcolour->blue = 0.0;
4317
0
                }
4318
206
                else if (dsc_stricmp(colourname, "Blue")==0) {
4319
0
                    pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4320
0
                    pcolour->blue = 1.0;
4321
0
                    pcolour->red = pcolour->green = 0.0;
4322
0
                }
4323
413
            }
4324
576
        } while (i != 0);
4325
114
    }
4326
114
    return CDSC_OK;
4327
114
}
4328
4329
static int
4330
dsc_parse_custom_colours(CDSC *dsc)
4331
0
{
4332
0
    unsigned int i, n;
4333
0
    CDSCCOLOUR *pcolour;
4334
0
    char colourname[MAXSTR];
4335
0
    GSBOOL blank_line;
4336
0
    if (IS_DSC(dsc->line, "%%DocumentCustomColors:"))
4337
0
        n = 23;
4338
0
    else if (IS_DSC(dsc->line, "%%+"))
4339
0
        n = 3;
4340
0
    else
4341
0
        return CDSC_ERROR; /* error */
4342
4343
0
    memset(&colourname, 0, sizeof(colourname));
4344
4345
    /* check for blank remainder of line */
4346
0
    blank_line = TRUE;
4347
0
    for (i=n; i<dsc->line_length; i++) {
4348
0
        if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4349
0
            blank_line = FALSE;
4350
0
            break;
4351
0
        }
4352
0
    }
4353
0
    while (IS_WHITE(dsc->line[n]))
4354
0
        n++;
4355
0
    if (COMPARE(dsc->line+n, "(atend)")) {
4356
0
        if (dsc->scan_section == scan_comments)
4357
0
            blank_line = TRUE;
4358
0
        else {
4359
0
            dsc_unknown(dsc);
4360
0
            return CDSC_NOTDSC;
4361
0
        }
4362
0
    }
4363
4364
0
    if (!blank_line) {
4365
0
        do {
4366
0
            dsc_copy_string(colourname, sizeof(colourname),
4367
0
                dsc->line+n, dsc->line_length-n, &i);
4368
0
            n+=i;
4369
0
            if (i && strlen(colourname)) {
4370
0
                if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4371
0
                    pcolour = (CDSCCOLOUR *)
4372
0
                        dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4373
0
                    if (pcolour == NULL)
4374
0
                        return CDSC_ERROR; /* out of memory */
4375
0
                    memset(pcolour, 0, sizeof(CDSCCOLOUR));
4376
0
                    pcolour->name = dsc_alloc_string(dsc,
4377
0
                        colourname, (int)strlen(colourname));
4378
0
                    if (pcolour->name == NULL) {
4379
0
                        dsc_memfree(dsc, pcolour);
4380
0
                        return CDSC_ERROR;
4381
0
                    }
4382
0
                    pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4383
0
                    if (dsc->colours == NULL)
4384
0
                        dsc->colours = pcolour;
4385
0
                    else {
4386
0
                        CDSCCOLOUR *this_colour = dsc->colours;
4387
0
                        while (this_colour->next)
4388
0
                            this_colour = this_colour->next;
4389
0
                        this_colour->next = pcolour;
4390
0
                    }
4391
0
                }
4392
0
                pcolour->type = CDSC_COLOUR_CUSTOM;
4393
0
            }
4394
0
        } while (i != 0);
4395
0
    }
4396
0
    return CDSC_OK;
4397
0
}
4398
4399
static int
4400
dsc_parse_cmyk_custom_colour(CDSC *dsc)
4401
0
{
4402
0
    unsigned int i, n;
4403
0
    CDSCCOLOUR *pcolour;
4404
0
    char colourname[MAXSTR];
4405
0
    float cyan, magenta, yellow, black;
4406
0
    GSBOOL blank_line;
4407
0
    if (IS_DSC(dsc->line, "%%CMYKCustomColor:"))
4408
0
        n = 18;
4409
0
    else if (IS_DSC(dsc->line, "%%+"))
4410
0
        n = 3;
4411
0
    else
4412
0
        return CDSC_ERROR; /* error */
4413
4414
0
    memset(&colourname, 0, sizeof(colourname));
4415
4416
    /* check for blank remainder of line */
4417
4418
0
    do {
4419
0
        blank_line = TRUE;
4420
0
        for (i=n; i<dsc->line_length; i++) {
4421
0
            if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4422
0
                blank_line = FALSE;
4423
0
                break;
4424
0
            }
4425
0
        }
4426
0
        if (blank_line)
4427
0
            break;
4428
0
        else {
4429
0
            magenta = yellow = black = 0.0;
4430
0
            cyan = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4431
0
            n += i;
4432
0
            if (i)
4433
0
                magenta = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4434
0
            n += i;
4435
0
            if (i)
4436
0
                yellow = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4437
0
            n += i;
4438
0
            if (i)
4439
0
                black = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4440
0
            n += i;
4441
0
            if (i)
4442
0
                dsc_copy_string(colourname, sizeof(colourname),
4443
0
                    dsc->line+n, dsc->line_length-n, &i);
4444
0
            n+=i;
4445
0
            if (i && strlen(colourname)) {
4446
0
                if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4447
0
                    pcolour = (CDSCCOLOUR *)
4448
0
                        dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4449
0
                    if (pcolour == NULL)
4450
0
                        return CDSC_ERROR; /* out of memory */
4451
0
                    memset(pcolour, 0, sizeof(CDSCCOLOUR));
4452
0
                    pcolour->name = dsc_alloc_string(dsc,
4453
0
                        colourname, (int)strlen(colourname));
4454
0
                    if (pcolour->name == NULL)
4455
0
                        return CDSC_ERROR;
4456
0
                    pcolour->type = CDSC_COLOUR_UNKNOWN;
4457
0
                    if (dsc->colours == NULL)
4458
0
                        dsc->colours = pcolour;
4459
0
                    else {
4460
0
                        CDSCCOLOUR *this_colour = dsc->colours;
4461
0
                        while (this_colour->next)
4462
0
                            this_colour = this_colour->next;
4463
0
                        this_colour->next = pcolour;
4464
0
                    }
4465
0
                }
4466
0
                pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4467
0
                pcolour->cyan = cyan;
4468
0
                pcolour->magenta = magenta;
4469
0
                pcolour->yellow = yellow;
4470
0
                pcolour->black = black;
4471
0
            }
4472
0
        }
4473
0
    } while (i != 0);
4474
0
    return CDSC_OK;
4475
0
}
4476
4477
static int
4478
dsc_parse_rgb_custom_colour(CDSC *dsc)
4479
0
{
4480
0
    unsigned int i, n;
4481
0
    CDSCCOLOUR *pcolour;
4482
0
    char colourname[MAXSTR];
4483
0
    float red, green, blue;
4484
0
    GSBOOL blank_line;
4485
0
    if (IS_DSC(dsc->line, "%%RGBCustomColor:"))
4486
0
        n = 17;
4487
0
    else if (IS_DSC(dsc->line, "%%+"))
4488
0
        n = 3;
4489
0
    else
4490
0
        return CDSC_ERROR; /* error */
4491
4492
0
    memset(&colourname, 0, sizeof(colourname));
4493
4494
    /* check for blank remainder of line */
4495
4496
0
    do {
4497
0
        blank_line = TRUE;
4498
0
        for (i=n; i<dsc->line_length; i++) {
4499
0
            if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4500
0
                blank_line = FALSE;
4501
0
                break;
4502
0
            }
4503
0
        }
4504
0
        if (blank_line)
4505
0
            break;
4506
0
        else {
4507
0
            green = blue = 0.0;
4508
0
            red = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4509
0
            n += i;
4510
0
            if (i)
4511
0
                green = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4512
0
            n += i;
4513
0
            if (i)
4514
0
                blue = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4515
0
            n += i;
4516
0
            if (i)
4517
0
                dsc_copy_string(colourname, sizeof(colourname),
4518
0
                    dsc->line+n, dsc->line_length-n, &i);
4519
0
            n+=i;
4520
0
            if (i && strlen(colourname)) {
4521
0
                if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4522
0
                    pcolour = (CDSCCOLOUR *)
4523
0
                        dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4524
0
                    if (pcolour == NULL)
4525
0
                        return CDSC_ERROR; /* out of memory */
4526
0
                    memset(pcolour, 0, sizeof(CDSCCOLOUR));
4527
0
                    pcolour->name = dsc_alloc_string(dsc,
4528
0
                        colourname, (int)strlen(colourname));
4529
0
                    if (pcolour->name == NULL)
4530
0
                        return CDSC_ERROR;
4531
0
                    pcolour->type = CDSC_COLOUR_UNKNOWN;
4532
0
                    if (dsc->colours == NULL)
4533
0
                        dsc->colours = pcolour;
4534
0
                    else {
4535
0
                        CDSCCOLOUR *this_colour = dsc->colours;
4536
0
                        while (this_colour->next)
4537
0
                            this_colour = this_colour->next;
4538
0
                        this_colour->next = pcolour;
4539
0
                    }
4540
0
                }
4541
0
                pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4542
0
                pcolour->red = red;
4543
0
                pcolour->green = green;
4544
0
                pcolour->blue = blue;
4545
0
            }
4546
0
        }
4547
0
    } while (i != 0);
4548
0
    return CDSC_OK;
4549
0
}