Coverage Report

Created: 2026-08-08 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pxl/pxparse.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* pxparse.c */
18
/* PCL XL parser */
19
20
#include "memory_.h"
21
#include "gdebug.h"
22
#include "gserrors.h"
23
#include "gsio.h"
24
#include "gstypes.h"
25
#include "plparse.h"
26
#include "pxattr.h"
27
#include "pxenum.h"
28
#include "pxerrors.h"
29
#include "pxoper.h"
30
#include "pxtag.h"
31
#include "pxvalue.h"
32
#include "pxparse.h"            /* requires pxattr.h, pxvalue.h */
33
#include "pxptable.h"           /* requires pxenum.h, pxoper.h, pxvalue.h */
34
#include "pxstate.h"
35
#include "pxpthr.h"
36
#include "gsstruct.h"
37
#include "pxgstate.h"           /* Prototype for px_high_level_pattern */
38
39
/*
40
 * We define the syntax of each possible tag by 4 parameters:
41
 *  - The minimum number of input bytes required to parse it;
42
 *  - A mask and match value for the state(s) in which it is legal;
43
 *  - A transition mask to be xor'ed with the state.
44
 * See pxparse.h for the state mask values.
45
 */
46
typedef struct px_tag_syntax_s
47
{
48
    byte min_input;
49
    byte state_value;
50
    byte state_mask;
51
    byte state_transition;
52
} px_tag_syntax_t;
53
54
/* Define the common syntaxes. */
55
#define N (ptsData|ptsReading)  /* normal state */
56
#define I {1,0,0,0}             /* illegal or unusual */
57
#define P {1,ptsInPage,ptsInPage|N,0}   /* ordinary operator */
58
#define C {1,ptsInSession,ptsInSession|N,0}     /* control operator */
59
#define R(p,r,t)  /* reading operator */\
60
 {1,ptsInSession|p|r,ptsInSession|p|N,t}
61
#define D(n) {n,0,ptsData,ptsData}      /* data type */
62
#define DI D(1)                 /* invalid data type */
63
#define A(n) {n,ptsData,ptsData,ptsData}        /* attribute */
64
65
/* Define the syntax of all tags. */
66
static const px_tag_syntax_t tag_syntax[256] = {
67
/*0x*/
68
    I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
69
/*1x*/
70
    I, I, I, I, I, I, I, I, I, I, I, {2, 0, 0, 0}, I, I, I, I,
71
/*2x*/
72
    I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
73
/*3x*/
74
    I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
75
/*4x*/
76
    {2, 0, ptsInSession | N, 0},
77
    {1, 0, ptsInSession | N, ptsInSession},
78
    {1, ptsInSession, ptsInSession | ptsInPage | N, ptsInSession},
79
    {1, ptsInSession, ptsInSession | ptsInPage | N, ptsInPage},
80
    {1, ptsInPage, ptsInPage | N, ptsInPage},
81
    P, {1, 1, 1, 0}, C,
82
    C, C, P, P, P, P, P, R(0, 0, ptsReadingFont),
83
/*5x*/
84
    R(0, ptsReadingFont, 0),
85
    R(0, ptsReadingFont, ptsReadingFont),
86
    R(0, 0, ptsReadingChar),
87
    R(0, ptsReadingChar, 0),
88
    R(0, ptsReadingChar, ptsReadingChar),
89
    C, P, P,
90
    P, P, P,
91
    {1, ptsInSession, ptsInSession | ptsExecStream | N, ptsReadingStream},
92
    {1, ptsInSession | ptsReadingStream, ptsInSession | ptsExecStream | N, 0},
93
    {1, ptsInSession | ptsReadingStream, ptsInSession | ptsExecStream | N,
94
     ptsReadingStream},
95
    {1, ptsInSession, ptsInSession | ptsReadingStream | N, 0},
96
    P,
97
/*6x*/
98
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
99
/*7x*/
100
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
101
/*8x*/
102
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
103
/*9x*/
104
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
105
/*ax*/
106
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
107
/*bx*/
108
    R(ptsInPage, 0, ptsReadingImage),
109
    R(ptsInPage, ptsReadingImage, 0),
110
    R(ptsInPage, ptsReadingImage, ptsReadingImage),
111
    R(ptsInPage, 0, ptsReadingRastPattern),
112
    R(ptsInPage, ptsReadingRastPattern, 0),
113
    R(ptsInPage, ptsReadingRastPattern, ptsReadingRastPattern),
114
    R(ptsInPage, 0, ptsReadingScan),
115
    P,
116
    R(ptsInPage, ptsReadingScan, ptsReadingScan),
117
    R(ptsInPage, ptsReadingScan, 0),
118
    P, P, P, P, P, P,
119
/*cx*/
120
    D(2), D(3), D(5), D(3), D(5), D(5), DI, DI,
121
    D(3), D(3), D(3), D(3), D(3), D(3), DI, DI,
122
/*dx*/
123
    D(3), D(5), D(9), D(5), D(9), D(9), DI, DI,
124
    DI, DI, DI, DI, DI, DI, DI, DI,
125
/*ex*/
126
    D(5), D(9), D(17), D(9), D(17), D(17), DI, DI,
127
    DI, DI, DI, DI, DI, DI, DI, DI,
128
/*fx*/
129
    I, I, I, I, I, I, I, I,
130
    A(2), A(3), {5, 0, 0, 0}, {2, 0, 0, 0}, I, I, I, I
131
};
132
#undef I
133
#undef P
134
#undef C
135
#undef R
136
#undef D
137
#undef DI
138
#undef A
139
140
/* Allocate a parser state. */
141
px_parser_state_t *
142
px_process_alloc(gs_memory_t * memory)
143
16.1k
{
144
16.1k
    px_parser_state_t *st = (px_parser_state_t *) gs_alloc_bytes(memory,
145
16.1k
                                                                 sizeof
146
16.1k
                                                                 (px_parser_state_t),
147
16.1k
                                                                 "px_process_alloc");
148
149
16.1k
    if (st == 0)
150
0
        return 0;
151
16.1k
    st->memory = memory;
152
16.1k
    px_process_init(st, true);
153
16.1k
    return st;
154
16.1k
}
155
156
/* Release a parser state. */
157
void
158
px_process_release(px_parser_state_t * st)
159
16.1k
{
160
16.1k
    gs_free_object(st->memory, st, "px_process_alloc");
161
16.1k
}
162
163
/* Initialize the parser state. */
164
void
165
px_process_init(px_parser_state_t * st, bool big_endian)
166
33.4k
{
167
33.4k
    st->big_endian = big_endian;
168
33.4k
    st->operator_count = 0;
169
33.4k
    st->parent_operator_count = 0;
170
33.4k
    st->last_operator = pxtNull;
171
33.4k
    st->saved_count = 0;
172
33.4k
    st->data_left = 0;
173
33.4k
    st->macro_state = ptsInitial;
174
33.4k
    st->stack_count = 0;
175
33.4k
    st->data_proc = 0;
176
33.4k
    {
177
33.4k
        int i;
178
179
701k
        for (i = 0; i < max_px_args; ++i)
180
668k
            st->args.pv[i] = 0;
181
33.4k
    }
182
33.4k
    st->args.parser = 0;        /* for garbage collector */
183
33.4k
    memset(st->attribute_indices, 0, px_attribute_next);
184
33.4k
}
185
186
/* Get numeric values from the input. */
187
41.8k
#define get_uint16(st, p) uint16at(p, st->big_endian)
188
80.2k
#define get_sint16(st, p) sint16at(p, st->big_endian)
189
3.15k
#define get_uint32(st, p) uint32at(p, st->big_endian)
190
21
#define get_sint32(st, p) sint32at(p, st->big_endian)
191
2.43k
#define get_real32(st, p) real32at(p, st->big_endian)
192
193
/* Move an array to the heap for persistence if needed. */
194
/* See pxoper.h for details. */
195
static int
196
px_save_array(px_value_t * pv, px_state_t * pxs, client_name_t cname,
197
              uint nbytes)
198
672
{
199
672
    if (pv->type & pxd_on_heap) {       /* Turn off the "on heap" bit, to prevent freeing. */
200
0
        pv->type &= ~pxd_on_heap;
201
672
    } else {                    /* Allocate a heap copy.  Only the first nbytes bytes */
202
        /* of the data are valid. */
203
672
        uint num_elements = pv->value.array.size;
204
672
        uint elt_size = value_size(pv);
205
672
        byte *copy = gs_alloc_byte_array(pxs->memory, num_elements,
206
672
                                         elt_size, cname);
207
208
672
        if (copy == 0)
209
0
            return_error(errorInsufficientMemory);
210
672
        memcpy(copy, pv->value.array.data, nbytes);
211
672
        pv->value.array.data = copy;
212
672
    }
213
672
    return 0;
214
672
}
215
216
/* Clear the stack and the attribute indices, */
217
/* and free heap-allocated arrays. */
218
#define clear_stack()\
219
217k
        for ( ; sp > st->stack; --sp )\
220
112k
          { if ( sp->type & pxd_on_heap )\
221
112k
              gs_free_object(memory, (void *)sp->value.array.data,\
222
112k
                             "px stack pop");\
223
112k
            st->attribute_indices[sp->attribute] = 0;\
224
112k
          }
225
226
/* Define data tracing if debugging. */
227
#ifdef DEBUG
228
#  define trace_data(mem, format, cast, ptr, count)\
229
                  do\
230
                    { uint i_;\
231
                      for ( i_ = 0; i_ < count; ++i_ )\
232
                        dmprintf1(mem, format, (cast)((ptr)[i_]));\
233
                      dmputc(mem, '\n');\
234
                    }\
235
                  while (0)
236
static void
237
trace_array_data(const gs_memory_t * mem, const char *label,
238
                 const px_value_t * pav)
239
{
240
    px_data_type_t type = pav->type;
241
    const byte *ptr = pav->value.array.data;
242
    uint count = pav->value.array.size;
243
    bool big_endian = (type & pxd_big_endian) != 0;
244
    bool text = (type & pxd_ubyte) != 0;
245
    uint i;
246
247
    dmputs(mem, label);
248
    dmputs(mem, (type & pxd_ubyte ? " <" : " {"));
249
    for (i = 0; i < count; ++i) {
250
        if (!(i & 15) && i) {
251
            const char *p;
252
253
            dmputs(mem, "\n  ");
254
            for (p = label; *p; ++p)
255
                dmputc(mem, ' ');
256
        }
257
        if (type & pxd_ubyte) {
258
            dmprintf1(mem, "%02x ", ptr[i]);
259
            if (ptr[i] < 32 || ptr[i] > 126)
260
                text = false;
261
        } else if (type & pxd_uint16)
262
            dmprintf1(mem, "%u ", uint16at(ptr + i * 2, big_endian));
263
        else if (type & pxd_sint16)
264
            dmprintf1(mem, "%d ", sint16at(ptr + i * 2, big_endian));
265
        else if (type & pxd_uint32)
266
            dmprintf1(mem, "%lu ", (ulong) uint32at(ptr + i * 4, big_endian));
267
        else if (type & pxd_sint32)
268
            dmprintf1(mem, "%ld ", (long)sint32at(ptr + i * 4, big_endian));
269
        else if (type & pxd_real32)
270
            dmprintf1(mem, "%g ", real32at(ptr + i * 4, big_endian));
271
        else
272
            dmputs(mem, "? ");
273
    }
274
    dmputs(mem, (type & pxd_ubyte ? ">\n" : "}\n"));
275
    if (text) {
276
        dmputs(mem, "%chars: \"");
277
        debug_print_string(mem, ptr, count);
278
        dmputs(mem, "\"\n");
279
    }
280
}
281
#  define trace_array(mem,pav)\
282
     if ( gs_debug_c('I') )\
283
       trace_array_data(mem,"array:", pav)
284
#else
285
#  define trace_data(mem, format, cast, ptr, count) DO_NOTHING
286
12.2k
#  define trace_array(mem,pav) DO_NOTHING
287
#endif
288
289
/* Process a buffer of PCL XL commands. */
290
int
291
px_process(px_parser_state_t * st, /* lgtm [cpp/use-of-goto] */
292
           px_state_t * pxs, stream_cursor_read * pr)
293
6.16k
{
294
6.16k
    const byte *orig_p = pr->ptr;
295
6.16k
    const byte *next_p = orig_p;        /* start of data not copied to saved */
296
6.16k
    const byte *p;
297
6.16k
    const byte *rlimit;
298
6.16k
    px_value_t *sp = &st->stack[st->stack_count];
299
300
114k
#define stack_limit &st->stack[max_stack - 1]
301
6.16k
    gs_memory_t *memory = st->memory;
302
6.16k
    int code = 0;
303
6.16k
    uint left;
304
6.16k
    uint min_left;
305
6.16k
    px_tag_t tag;
306
6.16k
    const px_tag_syntax_t *syntax = 0;
307
308
6.16k
    st->args.parser = st;
309
6.16k
    st->parent_operator_count = 0;      /* in case of error */
310
    /* Check for leftover data from the previous call. */
311
6.31k
  parse:if (st->saved_count) { /* Fill up the saved buffer so we can make progress. */
312
217
        int move = min(sizeof(st->saved) - st->saved_count,
313
217
                       pr->limit - next_p);
314
315
217
        memcpy(&st->saved[st->saved_count], next_p + 1, move);
316
217
        next_p += move;
317
217
        p = st->saved - 1;
318
217
        rlimit = p + st->saved_count + move;
319
6.09k
    } else {                    /* No leftover data, just read from the input. */
320
6.09k
        p = next_p;
321
6.09k
        rlimit = pr->limit;
322
6.09k
    }
323
35.4k
  top:if (st->data_left) {     /* We're in the middle of reading an array or data block. */
324
15.0k
        if (st->data_proc) {    /* This is a data block. */
325
14.8k
            uint avail = min(rlimit - p, st->data_left);
326
14.8k
            uint used;
327
328
14.8k
            st->args.source.available = avail;
329
14.8k
            st->args.source.data = p + 1;
330
14.8k
            code = (*st->data_proc) (&st->args, pxs);
331
            /* If we get a 'remap_color' error, it means we are dealing with a
332
             * pattern, and the device supports high level patterns. So we must
333
             * use our high level pattern implementation.
334
             */
335
14.8k
            if (code == gs_error_Remap_Color) {
336
0
                code = px_high_level_pattern(pxs->pgs);
337
0
                code = (*st->data_proc) (&st->args, pxs);
338
0
            }
339
14.8k
            used = st->args.source.data - (p + 1);
340
#ifdef DEBUG
341
            if (gs_debug_c('I')) {
342
                px_value_t data_array;
343
344
                data_array.type = pxd_ubyte;
345
                data_array.value.array.data = p + 1;
346
                data_array.value.array.size = used;
347
                trace_array_data(pxs->memory, "data:", &data_array);
348
            }
349
#endif
350
14.8k
            p = st->args.source.data - 1;
351
14.8k
            st->data_left -= used;
352
14.8k
            if (code < 0) {
353
46
                st->args.source.position = 0;
354
46
                goto x;
355
14.7k
            } else if ((code == pxNeedData)
356
14.3k
                       || (code == pxPassThrough && st->data_left != 0)) {
357
430
                code = 0;       /* exit for more data */
358
430
                goto x;
359
14.3k
            } else {
360
14.3k
                st->args.source.position = 0;
361
14.3k
                st->data_proc = 0;
362
14.3k
                if (st->data_left != 0) {
363
90
                    code = gs_note_error(errorExtraData);
364
90
                    goto x;
365
90
                }
366
14.2k
                clear_stack();
367
14.2k
            }
368
14.8k
        } else {                /* This is an array. */
369
172
            uint size = sp->value.array.size;
370
172
            uint scale = value_size(sp);
371
172
            uint nbytes = size * scale;
372
172
            byte *dest =
373
172
                (byte *) sp->value.array.data + nbytes - st->data_left;
374
375
172
            left = rlimit - p;
376
172
            if (left < st->data_left) { /* We still don't have enough data to fill the array. */
377
18
                memcpy(dest, p + 1, left);
378
18
                st->data_left -= left;
379
18
                p = rlimit;
380
18
                code = 0;
381
18
                goto x;
382
18
            }
383
            /* Complete the array and continue parsing. */
384
154
            memcpy(dest, p + 1, st->data_left);
385
154
            trace_array(memory, sp);
386
154
            p += st->data_left;
387
154
        }
388
14.4k
        st->data_left = 0;
389
20.4k
    } else if (st->data_proc) { /* An operator is awaiting data. */
390
        /* Skip white space until we find some. */
391
14.6k
        code = 0;               /* in case we exit */
392
        /* special case - VendorUnique has a length attribute which
393
           we've already parsed and error checked */
394
14.6k
        if (st->data_proc == pxVendorUnique) {
395
0
            st->data_left =
396
0
                st->stack[st->attribute_indices[pxaVUDataLength]].value.i;
397
0
            goto top;
398
14.6k
        } else {
399
14.7k
            while ((left = rlimit - p) != 0) {
400
14.7k
                switch ((tag = p[1])) {
401
149
                case pxtNull:
402
149
                case pxtHT:
403
150
                case pxtLF:
404
151
                case pxtVT:
405
152
                case pxtFF:
406
152
                case pxtCR:
407
152
                    ++p;
408
152
                    continue;
409
1.10k
                case pxt_dataLength:
410
1.10k
                    if (left < 5)
411
0
                        goto x; /* can't look ahead */
412
1.10k
                    st->data_left = get_uint32(st, p + 2);
413
1.10k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
414
1.10k
                               p[1], st->data_left);
415
1.10k
                    p += 5;
416
1.10k
                    goto top;
417
13.4k
                case pxt_dataLengthByte:
418
13.4k
                    if (left < 2)
419
30
                        goto x; /* can't look ahead */
420
13.4k
                    st->data_left = p[2];
421
13.4k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
422
13.4k
                               p[1], st->data_left);
423
13.4k
                    p += 2;
424
13.4k
                    goto top;
425
68
                default:
426
68
                    {
427
68
                        code = gs_note_error(errorMissingData);
428
68
                        goto x;
429
13.4k
                    }
430
14.7k
                }
431
14.7k
            }
432
14.6k
        }
433
14.6k
    }
434
20.2k
    st->args.source.position = 0;
435
20.2k
    st->args.source.available = 0;
436
399k
    while ((left = rlimit - p) != 0 &&
437
398k
           left >= (min_left = (syntax = &tag_syntax[tag = p[1]])->min_input)
438
398k
        ) {
439
398k
        int count;
440
441
#ifdef DEBUG
442
        if (gs_debug_c('i')) {
443
            dmprintf1(memory, "tag=  0x%02x  ", tag);
444
            if (tag == pxt_attr_ubyte || tag == pxt_attr_uint16) {
445
                px_attribute_t attr =
446
                    (tag == pxt_attr_ubyte ? p[2] : get_uint16(st, p + 2));
447
                const char *aname = px_attribute_names[attr];
448
449
                if (aname)
450
                    dmprintf1(memory, "   @%s\n", aname);
451
                else
452
                    dmprintf1(memory, "   attribute %u ???\n", attr);
453
            } else {
454
                const char *format;
455
                const char *tname;
456
                bool operator = false;
457
458
                if (tag < 0x40)
459
                    format = "%s\n", tname = px_tag_0_names[tag];
460
                else if (tag < 0xc0)
461
                    format = "%s", tname = px_operator_names[tag - 0x40],
462
                        operator = true;
463
                else {
464
                    tname = px_tag_c0_names[tag - 0xc0];
465
                    if (tag < 0xf0)
466
                        format = "      %s";    /* data values follow */
467
                    else
468
                        format = "%s\n";
469
                }
470
                if (tname) {
471
                    dmprintf1(memory, format, tname);
472
                    if (operator)
473
                        dmprintf1(memory, " (%ld)\n", st->operator_count + 1);
474
                } else
475
                    dmputs(memory, "???\n");
476
            }
477
        }
478
#endif
479
398k
        if ((st->macro_state & syntax->state_mask) != syntax->state_value) {
480
            /*
481
             * We should probably distinguish here between
482
             * out-of-context operators and illegal tags, but it's too
483
             * much trouble.
484
             */
485
1.04k
            code = gs_note_error(errorIllegalOperatorSequence);
486
1.04k
            if (tag >= 0x40 && tag < 0xc0)
487
801
                st->last_operator = tag;
488
1.04k
            goto x;
489
1.04k
        }
490
397k
        st->macro_state ^= syntax->state_transition;
491
397k
        switch (tag >> 3) {
492
42.0k
            case 0:
493
42.0k
                switch (tag) {
494
41.8k
                    case pxtNull:
495
41.8k
                        ++p;
496
41.8k
                        continue;
497
178
                    default:
498
178
                        break;
499
42.0k
                }
500
178
                break;
501
507
            case 1:
502
507
                switch (tag) {
503
222
                    case pxtHT:
504
319
                    case pxtLF:
505
325
                    case pxtVT:
506
381
                    case pxtFF:
507
485
                    case pxtCR:
508
485
                        ++p;
509
485
                        continue;
510
22
                    default:
511
22
                        break;
512
507
                }
513
22
                break;
514
2.42k
            case 3:
515
2.42k
                if (tag == pxt1b) {     /* ESC *//* Check for UEL */
516
2.40k
                    if (memcmp(p + 1, "\033%-12345X", min(left, 9)))
517
388
                        break;  /* not UEL, error */
518
2.01k
                    if (left < 9)
519
2
                        goto x; /* need more data */
520
2.01k
                    p += 9;
521
2.01k
                    code = e_ExitLanguage;
522
2.01k
                    goto x;
523
2.01k
                }
524
22
                break;
525
17.2k
            case 4:
526
17.2k
                switch (tag) {
527
17.0k
                    case pxtSpace:
528
                        /* break; will error, compatible with lj */
529
                        /* ++p;continue; silently ignores the space */
530
17.0k
                        ++p;
531
17.0k
                        continue;
532
243
                    default:
533
243
                        break;
534
17.2k
                }
535
243
                break;
536
4.65k
            case 8:
537
7.43k
            case 9:
538
9.80k
            case 10:
539
10.0k
            case 11:
540
22.5k
            case 12:
541
42.7k
            case 13:
542
46.2k
            case 14:
543
55.0k
            case 15:
544
81.2k
            case 16:
545
81.3k
            case 17:
546
89.6k
            case 18:
547
100k
            case 19:
548
101k
            case 20:
549
105k
            case 21:
550
105k
            case 22:
551
106k
            case 23:
552
                /* Operators */
553
                /* Make sure that we have all the required attributes, */
554
                /* and no attributes that are neither required nor */
555
                /* optional.  (It's up to the operator to make any */
556
                /* more precise checks than this. */
557
106k
                st->operator_count++;
558
                /* if this is a passthrough operator we have to tell
559
                   the passthrough module if this operator was
560
                   preceded by another passthrough operator or a
561
                   different xl operator */
562
106k
                if (tag == pxtPassThrough) {
563
46
                    pxpcl_passthroughcontiguous(pxs, st->last_operator == tag);
564
105k
                } else if (st->last_operator == pxtPassThrough) {
565
0
                    pxpcl_endpassthroughcontiguous(pxs);
566
0
                }
567
568
106k
                st->last_operator = tag;
569
106k
                {
570
106k
                    const px_operator_definition_t *pod =
571
106k
                        &px_operator_definitions[tag - 0x40];
572
106k
                    int left = sp - st->stack;
573
106k
                    const byte /*px_attribute_t */  * pal = pod->attrs;
574
106k
                    px_value_t **ppv = st->args.pv;
575
106k
                    bool required = true;
576
106k
                    code = 0;
577
                    /*
578
                     * Scan the attributes.  Illegal attributes take priority
579
                     * over missing attributes, which in turn take priority
580
                     * over illegal data types.
581
                     */
582
519k
                    for (;; ++pal, ++ppv) {
583
519k
                        px_attribute_t attr = *pal;
584
519k
                        uint index;
585
586
519k
                        if (!attr) {    /*
587
                                         * We've reached the end of either the required or
588
                                         * the optional attribute list.
589
                                         */
590
212k
                            if (!required)
591
106k
                                break;
592
106k
                            required = false;
593
106k
                            --ppv;      /* cancel incrementing */
594
106k
                            continue;
595
212k
                        }
596
307k
                        if ((index = st->attribute_indices[attr]) == 0) {
597
194k
                            if (required)
598
132
                                code = gs_note_error(errorMissingAttribute);
599
194k
                            else
600
194k
                                *ppv = 0;
601
194k
                        } else {        /* Check the attribute data type and value. */
602
113k
                            px_value_t *pv = *ppv = &st->stack[index];
603
113k
                            const px_attr_value_type_t *pavt =
604
113k
                                &px_attr_value_types[attr];
605
113k
                            int acode;
606
607
113k
                            if ((~pavt->mask & pv->type &
608
113k
                                 (pxd_structure | pxd_representation)) ||
609
112k
                                (pavt->mask == (pxd_scalar | pxd_ubyte) &&
610
46.1k
                                 (pv->value.i < 0
611
46.1k
                                  || pv->value.i > pavt->limit))
612
113k
                                ) {
613
33
                                if (code >= 0)
614
33
                                    code =
615
33
                                        gs_note_error
616
33
                                        (errorIllegalAttributeDataType);
617
33
                            }
618
113k
                            if (pavt->proc != 0
619
14.7k
                                && (acode = (*pavt->proc) (pv)) < 0) {
620
9
                                if (code >= 0)
621
6
                                    code = acode;
622
9
                            }
623
113k
                            --left;
624
113k
                        }
625
307k
                    }
626
627
                    /* Make sure there are no attributes left over. */
628
106k
                    if (left)
629
105
                        code = gs_note_error(errorIllegalAttribute);
630
106k
                    if (code >= 0) {
631
105k
                        st->args.source.phase = 0;
632
105k
                        code = (*pod->proc) (&st->args, pxs);
633
                        /* If we get a 'remap_color' error, it means we are dealing with a
634
                         * pattern, and the device supports high level patterns. So we must
635
                         * use our high level pattern implementation.
636
                         */
637
105k
                        if (code == gs_error_Remap_Color) {
638
0
                            code = px_high_level_pattern(pxs->pgs);
639
0
                            if (code < 0)
640
0
                                goto x;
641
0
                            code = (*pod->proc) (&st->args, pxs);
642
0
                        }
643
105k
                    }
644
106k
                    if (code < 0)
645
437
                        goto x;
646
                    /* Check whether the operator wanted source data. */
647
105k
                    if (code == pxNeedData) {
648
14.5k
                        if (!pxs->data_source_open) {
649
0
                            code = gs_note_error(errorDataSourceNotOpen);
650
0
                            goto x;
651
0
                        }
652
14.5k
                        st->data_proc = pod->proc;
653
14.5k
                        ++p;
654
14.5k
                        goto top;
655
14.5k
                    }
656
105k
                }
657
91.0k
                clear_stack();
658
91.0k
                ++p;
659
91.0k
                continue;
660
75.7k
            case 24:
661
75.7k
                sp[1].type = pxd_scalar;
662
75.7k
                count = 1;
663
75.7k
                goto data;
664
24.4k
            case 26:
665
24.4k
                sp[1].type = pxd_xy;
666
24.4k
                count = 2;
667
24.4k
                goto data;
668
2.35k
            case 28:
669
2.35k
                sp[1].type = pxd_box;
670
2.35k
                count = 4;
671
2.35k
                goto data;
672
                /* Scalar, point, and box data */
673
102k
              data:{
674
102k
                    int i;
675
676
102k
                    if (sp == stack_limit) {
677
0
                        code = gs_note_error(errorInternalOverflow);
678
0
                        goto x;
679
0
                    }
680
102k
                    ++sp;
681
102k
                    sp->attribute = 0;
682
102k
                    p += 2;
683
#ifdef DEBUG
684
#  define trace_scalar(mem, format, cast, alt)\
685
                  if ( gs_debug_c('i') )\
686
                    trace_data(mem, format, cast, sp->value.alt, count)
687
#else
688
102k
#  define trace_scalar(mem, format, cast, alt) DO_NOTHING
689
102k
#endif
690
102k
                    switch (tag & 7) {
691
60.1k
                        case pxt_ubyte & 7:
692
60.1k
                            sp->type |= pxd_ubyte;
693
120k
                            for (i = 0; i < count; ++p, ++i)
694
60.1k
                                sp->value.ia[i] = *p;
695
74.1k
                          dux:trace_scalar(pxs->memory, " %lu", ulong,
696
74.1k
                                         ia);
697
74.1k
                            --p;
698
74.1k
                            continue;
699
12.9k
                        case pxt_uint16 & 7:
700
12.9k
                            sp->type |= pxd_uint16;
701
31.3k
                            for (i = 0; i < count; p += 2, ++i)
702
18.4k
                                sp->value.ia[i] = get_uint16(st, p);
703
12.9k
                            goto dux;
704
1.02k
                        case pxt_uint32 & 7:
705
1.02k
                            sp->type |= pxd_uint32;
706
2.04k
                            for (i = 0; i < count; p += 4, ++i)
707
1.02k
                                sp->value.ia[i] = get_uint32(st, p);
708
1.02k
                            goto dux;
709
27.2k
                        case pxt_sint16 & 7:
710
27.2k
                            sp->type |= pxd_sint16;
711
80.2k
                            for (i = 0; i < count; p += 2, ++i)
712
53.0k
                                sp->value.ia[i] = get_sint16(st, p);
713
27.2k
                          dsx:trace_scalar(pxs->memory, " %ld", long,
714
27.2k
                                         ia);
715
27.2k
                            --p;
716
27.2k
                            continue;
717
7
                        case pxt_sint32 & 7:
718
7
                            sp->type |= pxd_sint32;
719
21
                            for (i = 0; i < count; p += 4, ++i)
720
14
                                sp->value.ia[i] = get_sint32(st, p);
721
7
                            goto dsx;
722
1.09k
                        case pxt_real32 & 7:
723
1.09k
                            sp->type |= pxd_real32;
724
2.43k
                            for (i = 0; i < count; p += 4, ++i)
725
1.33k
                                sp->value.ra[i] = get_real32(st, p);
726
1.09k
                            trace_scalar(pxs->memory, " %g", double, ra);
727
728
1.09k
                            --p;
729
1.09k
                            continue;
730
6
                        default:
731
6
                            break;
732
102k
                    }
733
102k
                }
734
6
                break;
735
12.3k
            case 25:
736
                /* Array data */
737
12.3k
                {
738
12.3k
                    const byte *dp;
739
12.3k
                    uint nbytes;
740
741
12.3k
                    if (sp == stack_limit) {
742
0
                        code = gs_note_error(errorInternalOverflow);
743
0
                        goto x;
744
0
                    }
745
12.3k
                    switch (p[2]) {
746
1.90k
                        case pxt_ubyte:
747
1.90k
                            sp[1].value.array.size = p[3];
748
1.90k
                            dp = p + 4;
749
1.90k
                            break;
750
10.4k
                        case pxt_uint16:
751
10.4k
                            if (left < 4) {
752
9
                                if_debug0m('i', memory, "...\n");
753
                                /* Undo the state transition. */
754
9
                                st->macro_state ^= syntax->state_transition;
755
9
                                goto x;
756
9
                            }
757
10.4k
                            sp[1].value.array.size = get_uint16(st, p + 3);
758
10.4k
                            dp = p + 5;
759
10.4k
                            break;
760
33
                        default:
761
33
                            st->last_operator = tag;    /* for error message */
762
33
                            code = gs_note_error(errorIllegalTag);
763
33
                            goto x;
764
12.3k
                    }
765
12.3k
                    nbytes = sp[1].value.array.size;
766
12.3k
                    if_debug1m('i', memory, "[%u]\n", sp[1].value.array.size);
767
12.3k
                    switch (tag) {
768
12.3k
                        case pxt_ubyte_array:
769
12.3k
                            sp[1].type = pxd_array | pxd_ubyte;
770
12.3k
                          array:++sp;
771
12.3k
                            if (st->big_endian)
772
0
                                sp->type |= pxd_big_endian;
773
12.3k
                            sp->value.array.data = dp;
774
12.3k
                            sp->attribute = 0;
775
                            /* Check whether we have enough data for the entire */
776
                            /* array. */
777
12.3k
                            if (rlimit + 1 - dp < nbytes) {     /* Exit now, continue reading when we return. */
778
223
                                uint avail = rlimit + 1 - dp;
779
780
223
                                code = px_save_array(sp, pxs, "partial array",
781
223
                                                     avail);
782
223
                                if (code < 0)
783
0
                                    goto x;
784
223
                                sp->type |= pxd_on_heap;
785
223
                                st->data_left = nbytes - avail;
786
223
                                st->data_proc = 0;
787
223
                                p = rlimit;
788
223
                                goto x;
789
223
                            }
790
12.0k
                            p = dp + nbytes - 1;
791
12.0k
                            trace_array(memory, sp);
792
12.0k
                            continue;
793
2
                        case pxt_uint16_array:
794
2
                            sp[1].type = pxd_array | pxd_uint16;
795
4
                          a16:nbytes <<= 1;
796
4
                            goto array;
797
0
                        case pxt_uint32_array:
798
0
                            sp[1].type = pxd_array | pxd_uint32;
799
2
                          a32:nbytes <<= 2;
800
2
                            goto array;
801
2
                        case pxt_sint16_array:
802
2
                            sp[1].type = pxd_array | pxd_sint16;
803
2
                            goto a16;
804
1
                        case pxt_sint32_array:
805
1
                            sp[1].type = pxd_array | pxd_sint32;
806
1
                            goto a32;
807
1
                        case pxt_real32_array:
808
1
                            sp[1].type = pxd_array | pxd_real32;
809
1
                            goto a32;
810
2
                        default:
811
2
                            break;
812
12.3k
                    }
813
2
                    break;
814
12.3k
                }
815
2
                break;
816
114k
            case 31:
817
114k
                {
818
114k
                    px_attribute_t attr;
819
114k
                    const byte *pnext;
820
821
114k
                    switch (tag) {
822
113k
                        case pxt_attr_ubyte:
823
113k
                            attr = p[2];
824
113k
                            pnext = p + 2;
825
113k
                            goto a;
826
1
                        case pxt_attr_uint16:
827
1
                            attr = get_uint16(st, p + 2);
828
1
                            pnext = p + 3;
829
113k
                          a:if (attr >=
830
113k
                                px_attribute_next)
831
89
                                break;
832
                            /*
833
                             * We could check the attribute value type here, but
834
                             * in order to match the behavior of the H-P printers,
835
                             * we don't do it until we see the operator.
836
                             *
837
                             * It is legal to specify the same attribute more than
838
                             * once; the last value has priority.  If this happens,
839
                             * since the order of attributes doesn't matter, we can
840
                             * just replace the former value on the stack.
841
                             */
842
113k
                            sp->attribute = attr;
843
113k
                            if (st->attribute_indices[attr] != 0) {
844
9
                                px_value_t *old_sp =
845
9
                                    &st->stack[st->attribute_indices[attr]];
846
                                /* If the old value is on the heap, free it. */
847
9
                                if (old_sp->type & pxd_on_heap)
848
0
                                    gs_free_object(memory,
849
9
                                                   (void *)old_sp->value.
850
9
                                                   array.data,
851
9
                                                   "old value for duplicate attribute");
852
9
                                *old_sp = *sp--;
853
9
                            } else
854
113k
                                st->attribute_indices[attr] = sp - st->stack;
855
113k
                            p = pnext;
856
113k
                            continue;
857
32
                        case pxt_dataLength:
858
                            /*
859
                             * Unexpected data length operators are normally not
860
                             * allowed, but there might be a zero-length data
861
                             * block immediately following a zero-size image,
862
                             * which doesn't ask for any data.
863
                             */
864
32
                            if (uint32at(p + 2, true /*arbitrary */ ) == 0) {
865
1
                                p += 5;
866
1
                                continue;
867
1
                            }
868
31
                            break;
869
31
                        case pxt_dataLengthByte:
870
                            /* See the comment under pxt_dataLength above. */
871
29
                            if (p[2] == 0) {
872
19
                                p += 2;
873
19
                                continue;
874
19
                            }
875
10
                            break;
876
209
                        default:
877
209
                            break;
878
114k
                    }
879
114k
                }
880
339
                break;
881
372
            default:
882
372
                break;
883
397k
        }
884
        /* Unknown tag value.  Report an error. */
885
1.57k
        st->last_operator = tag;        /* for error message */
886
1.57k
        code = gs_note_error(errorIllegalTag);
887
1.57k
        break;
888
397k
    }
889
6.31k
  x:                           /* Save any leftover input. */
890
6.31k
    left = rlimit - p;
891
6.31k
    if (rlimit != pr->limit) {  /* We were reading saved input. */
892
217
        if (left <= next_p - orig_p) {  /* We finished reading the previously saved input. */
893
            /* Continue reading current input, unless we got an error. */
894
215
            p = next_p -= left;
895
215
            rlimit = pr->limit;
896
215
            st->saved_count = 0;
897
215
            if (code >= 0)
898
149
                goto parse;
899
215
        } else {                /* There's still some previously saved input left over. */
900
2
            memmove(st->saved, p + 1, st->saved_count = left);
901
2
            p = next_p;
902
2
            rlimit = pr->limit;
903
2
            left = rlimit - p;
904
2
        }
905
217
    }
906
    /* Except in case of error, save any remaining input. */
907
6.16k
    if (code >= 0) {
908
859
        if (left + st->saved_count > sizeof(st->saved)) {       /* Fatal error -- shouldn't happen! */
909
8
            code = gs_note_error(errorInternalOverflow);
910
8
            st->saved_count = 0;
911
851
        } else {
912
851
            memcpy(&st->saved[st->saved_count], p + 1, left);
913
851
            st->saved_count += left;
914
851
            p = rlimit;
915
851
        }
916
859
    }
917
6.16k
    pr->ptr = p;
918
6.16k
    st->stack_count = sp - st->stack;
919
    /* Move to the heap any arrays whose data was being referenced */
920
    /* directly in the input buffer. */
921
9.52k
    for (; sp > st->stack; --sp)
922
3.35k
        if ((sp->type & (pxd_array | pxd_on_heap)) == pxd_array) {
923
449
            int code = px_save_array(sp, pxs, "px stack array to heap",
924
449
                                     sp->value.array.size * value_size(sp));
925
926
449
            if (code < 0)
927
0
                break;
928
449
            sp->type |= pxd_on_heap;
929
449
        }
930
6.16k
    if (code < 0 && syntax != 0) {      /* Undo the state transition. */
931
5.31k
        st->macro_state ^= syntax->state_transition;
932
5.31k
    }
933
6.16k
    return code;
934
6.31k
}
935
936
uint
937
px_parser_data_left(px_parser_state_t * pxp)
938
6
{
939
6
    return pxp->data_left;
940
6
}