Coverage Report

Created: 2025-08-28 07:06

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