Coverage Report

Created: 2022-10-31 07:00

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