Coverage Report

Created: 2026-09-14 07:34

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
11.0k
{
144
11.0k
    px_parser_state_t *st = (px_parser_state_t *) gs_alloc_bytes(memory,
145
11.0k
                                                                 sizeof
146
11.0k
                                                                 (px_parser_state_t),
147
11.0k
                                                                 "px_process_alloc");
148
149
11.0k
    if (st == 0)
150
0
        return 0;
151
11.0k
    st->memory = memory;
152
11.0k
    px_process_init(st, true);
153
11.0k
    return st;
154
11.0k
}
155
156
/* Release a parser state. */
157
void
158
px_process_release(px_parser_state_t * st)
159
11.0k
{
160
11.0k
    gs_free_object(st->memory, st, "px_process_alloc");
161
11.0k
}
162
163
/* Initialize the parser state. */
164
void
165
px_process_init(px_parser_state_t * st, bool big_endian)
166
27.5k
{
167
27.5k
    st->big_endian = big_endian;
168
27.5k
    st->operator_count = 0;
169
27.5k
    st->parent_operator_count = 0;
170
27.5k
    st->last_operator = pxtNull;
171
27.5k
    st->saved_count = 0;
172
27.5k
    st->data_left = 0;
173
27.5k
    st->macro_state = ptsInitial;
174
27.5k
    st->stack_count = 0;
175
27.5k
    st->data_proc = 0;
176
27.5k
    {
177
27.5k
        int i;
178
179
577k
        for (i = 0; i < max_px_args; ++i)
180
550k
            st->args.pv[i] = 0;
181
27.5k
    }
182
27.5k
    st->args.parser = 0;        /* for garbage collector */
183
27.5k
    memset(st->attribute_indices, 0, px_attribute_next);
184
27.5k
}
185
186
/* Get numeric values from the input. */
187
39.9k
#define get_uint16(st, p) uint16at(p, st->big_endian)
188
78.0k
#define get_sint16(st, p) sint16at(p, st->big_endian)
189
2.99k
#define get_uint32(st, p) uint32at(p, st->big_endian)
190
26
#define get_sint32(st, p) sint32at(p, st->big_endian)
191
2.36k
#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
650
{
199
650
    if (pv->type & pxd_on_heap) {       /* Turn off the "on heap" bit, to prevent freeing. */
200
0
        pv->type &= ~pxd_on_heap;
201
650
    } else {                    /* Allocate a heap copy.  Only the first nbytes bytes */
202
        /* of the data are valid. */
203
650
        uint num_elements = pv->value.array.size;
204
650
        uint elt_size = value_size(pv);
205
650
        byte *copy = gs_alloc_byte_array(pxs->memory, num_elements,
206
650
                                         elt_size, cname);
207
208
650
        if (copy == 0)
209
0
            return_error(errorInsufficientMemory);
210
650
        memcpy(copy, pv->value.array.data, nbytes);
211
650
        pv->value.array.data = copy;
212
650
    }
213
650
    return 0;
214
650
}
215
216
/* Clear the stack and the attribute indices, */
217
/* and free heap-allocated arrays. */
218
#define clear_stack()\
219
210k
        for ( ; sp > st->stack; --sp )\
220
108k
          { if ( sp->type & pxd_on_heap )\
221
108k
              gs_free_object(memory, (void *)sp->value.array.data,\
222
108k
                             "px stack pop");\
223
108k
            st->attribute_indices[sp->attribute] = 0;\
224
108k
          }
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.0k
#  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
5.86k
{
294
5.86k
    const byte *orig_p = pr->ptr;
295
5.86k
    const byte *next_p = orig_p;        /* start of data not copied to saved */
296
5.86k
    const byte *p;
297
5.86k
    const byte *rlimit;
298
5.86k
    px_value_t *sp = &st->stack[st->stack_count];
299
300
110k
#define stack_limit &st->stack[max_stack - 1]
301
5.86k
    gs_memory_t *memory = st->memory;
302
5.86k
    int code = 0;
303
5.86k
    uint left;
304
5.86k
    uint min_left;
305
5.86k
    px_tag_t tag;
306
5.86k
    const px_tag_syntax_t *syntax = 0;
307
308
5.86k
    st->args.parser = st;
309
5.86k
    st->parent_operator_count = 0;      /* in case of error */
310
    /* Check for leftover data from the previous call. */
311
6.01k
  parse:if (st->saved_count) { /* Fill up the saved buffer so we can make progress. */
312
210
        int move = min(sizeof(st->saved) - st->saved_count,
313
210
                       pr->limit - next_p);
314
315
210
        memcpy(&st->saved[st->saved_count], next_p + 1, move);
316
210
        next_p += move;
317
210
        p = st->saved - 1;
318
210
        rlimit = p + st->saved_count + move;
319
5.80k
    } else {                    /* No leftover data, just read from the input. */
320
5.80k
        p = next_p;
321
5.80k
        rlimit = pr->limit;
322
5.80k
    }
323
33.5k
  top:if (st->data_left) {     /* We're in the middle of reading an array or data block. */
324
14.2k
        if (st->data_proc) {    /* This is a data block. */
325
14.0k
            uint avail = min(rlimit - p, st->data_left);
326
14.0k
            uint used;
327
328
14.0k
            st->args.source.available = avail;
329
14.0k
            st->args.source.data = p + 1;
330
14.0k
            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.0k
            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.0k
            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.0k
            p = st->args.source.data - 1;
351
14.0k
            st->data_left -= used;
352
14.0k
            if (code < 0) {
353
46
                st->args.source.position = 0;
354
46
                goto x;
355
14.0k
            } else if ((code == pxNeedData)
356
13.5k
                       || (code == pxPassThrough && st->data_left != 0)) {
357
411
                code = 0;       /* exit for more data */
358
411
                goto x;
359
13.5k
            } else {
360
13.5k
                st->args.source.position = 0;
361
13.5k
                st->data_proc = 0;
362
13.5k
                if (st->data_left != 0) {
363
82
                    code = gs_note_error(errorExtraData);
364
82
                    goto x;
365
82
                }
366
13.5k
                clear_stack();
367
13.5k
            }
368
14.0k
        } else {                /* This is an array. */
369
175
            uint size = sp->value.array.size;
370
175
            uint scale = value_size(sp);
371
175
            uint nbytes = size * scale;
372
175
            byte *dest =
373
175
                (byte *) sp->value.array.data + nbytes - st->data_left;
374
375
175
            left = rlimit - p;
376
175
            if (left < st->data_left) { /* We still don't have enough data to fill the array. */
377
19
                memcpy(dest, p + 1, left);
378
19
                st->data_left -= left;
379
19
                p = rlimit;
380
19
                code = 0;
381
19
                goto x;
382
19
            }
383
            /* Complete the array and continue parsing. */
384
156
            memcpy(dest, p + 1, st->data_left);
385
156
            trace_array(memory, sp);
386
156
            p += st->data_left;
387
156
        }
388
13.6k
        st->data_left = 0;
389
19.3k
    } else if (st->data_proc) { /* An operator is awaiting data. */
390
        /* Skip white space until we find some. */
391
13.8k
        code = 0;               /* in case we exit */
392
        /* special case - VendorUnique has a length attribute which
393
           we've already parsed and error checked */
394
13.8k
        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
13.8k
        } else {
399
14.3k
            while ((left = rlimit - p) != 0) {
400
14.3k
                switch ((tag = p[1])) {
401
457
                case pxtNull:
402
457
                case pxtHT:
403
458
                case pxtLF:
404
459
                case pxtVT:
405
460
                case pxtFF:
406
460
                case pxtCR:
407
460
                    ++p;
408
460
                    continue;
409
1.05k
                case pxt_dataLength:
410
1.05k
                    if (left < 5)
411
0
                        goto x; /* can't look ahead */
412
1.05k
                    st->data_left = get_uint32(st, p + 2);
413
1.05k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
414
1.05k
                               p[1], st->data_left);
415
1.05k
                    p += 5;
416
1.05k
                    goto top;
417
12.7k
                case pxt_dataLengthByte:
418
12.7k
                    if (left < 2)
419
29
                        goto x; /* can't look ahead */
420
12.7k
                    st->data_left = p[2];
421
12.7k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
422
12.7k
                               p[1], st->data_left);
423
12.7k
                    p += 2;
424
12.7k
                    goto top;
425
66
                default:
426
66
                    {
427
66
                        code = gs_note_error(errorMissingData);
428
66
                        goto x;
429
12.7k
                    }
430
14.3k
                }
431
14.3k
            }
432
13.8k
        }
433
13.8k
    }
434
19.1k
    st->args.source.position = 0;
435
19.1k
    st->args.source.available = 0;
436
360k
    while ((left = rlimit - p) != 0 &&
437
360k
           left >= (min_left = (syntax = &tag_syntax[tag = p[1]])->min_input)
438
360k
        ) {
439
360k
        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
360k
        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
946
            code = gs_note_error(errorIllegalOperatorSequence);
486
946
            if (tag >= 0x40 && tag < 0xc0)
487
720
                st->last_operator = tag;
488
946
            goto x;
489
946
        }
490
359k
        st->macro_state ^= syntax->state_transition;
491
359k
        switch (tag >> 3) {
492
32.1k
            case 0:
493
32.1k
                switch (tag) {
494
31.9k
                    case pxtNull:
495
31.9k
                        ++p;
496
31.9k
                        continue;
497
175
                    default:
498
175
                        break;
499
32.1k
                }
500
175
                break;
501
520
            case 1:
502
520
                switch (tag) {
503
221
                    case pxtHT:
504
319
                    case pxtLF:
505
325
                    case pxtVT:
506
380
                    case pxtFF:
507
497
                    case pxtCR:
508
497
                        ++p;
509
497
                        continue;
510
23
                    default:
511
23
                        break;
512
520
                }
513
23
                break;
514
2.33k
            case 3:
515
2.33k
                if (tag == pxt1b) {     /* ESC *//* Check for UEL */
516
2.32k
                    if (memcmp(p + 1, "\033%-12345X", min(left, 9)))
517
373
                        break;  /* not UEL, error */
518
1.95k
                    if (left < 9)
519
2
                        goto x; /* need more data */
520
1.94k
                    p += 9;
521
1.94k
                    code = e_ExitLanguage;
522
1.94k
                    goto x;
523
1.95k
                }
524
15
                break;
525
379
            case 4:
526
379
                switch (tag) {
527
158
                    case pxtSpace:
528
                        /* break; will error, compatible with lj */
529
                        /* ++p;continue; silently ignores the space */
530
158
                        ++p;
531
158
                        continue;
532
221
                    default:
533
221
                        break;
534
379
                }
535
221
                break;
536
4.48k
            case 8:
537
7.16k
            case 9:
538
9.46k
            case 10:
539
9.71k
            case 11:
540
21.9k
            case 12:
541
41.4k
            case 13:
542
44.8k
            case 14:
543
53.3k
            case 15:
544
78.8k
            case 16:
545
78.8k
            case 17:
546
86.8k
            case 18:
547
97.3k
            case 19:
548
98.4k
            case 20:
549
101k
            case 21:
550
102k
            case 22:
551
102k
            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
102k
                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
102k
                if (tag == pxtPassThrough) {
563
45
                    pxpcl_passthroughcontiguous(pxs, st->last_operator == tag);
564
102k
                } else if (st->last_operator == pxtPassThrough) {
565
0
                    pxpcl_endpassthroughcontiguous(pxs);
566
0
                }
567
568
102k
                st->last_operator = tag;
569
102k
                {
570
102k
                    const px_operator_definition_t *pod =
571
102k
                        &px_operator_definitions[tag - 0x40];
572
102k
                    int left = sp - st->stack;
573
102k
                    const byte /*px_attribute_t */  * pal = pod->attrs;
574
102k
                    px_value_t **ppv = st->args.pv;
575
102k
                    bool required = true;
576
102k
                    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
502k
                    for (;; ++pal, ++ppv) {
583
502k
                        px_attribute_t attr = *pal;
584
502k
                        uint index;
585
586
502k
                        if (!attr) {    /*
587
                                         * We've reached the end of either the required or
588
                                         * the optional attribute list.
589
                                         */
590
205k
                            if (!required)
591
102k
                                break;
592
102k
                            required = false;
593
102k
                            --ppv;      /* cancel incrementing */
594
102k
                            continue;
595
205k
                        }
596
297k
                        if ((index = st->attribute_indices[attr]) == 0) {
597
187k
                            if (required)
598
129
                                code = gs_note_error(errorMissingAttribute);
599
187k
                            else
600
187k
                                *ppv = 0;
601
187k
                        } else {        /* Check the attribute data type and value. */
602
109k
                            px_value_t *pv = *ppv = &st->stack[index];
603
109k
                            const px_attr_value_type_t *pavt =
604
109k
                                &px_attr_value_types[attr];
605
109k
                            int acode;
606
607
109k
                            if ((~pavt->mask & pv->type &
608
109k
                                 (pxd_structure | pxd_representation)) ||
609
109k
                                (pavt->mask == (pxd_scalar | pxd_ubyte) &&
610
44.2k
                                 (pv->value.i < 0
611
44.2k
                                  || pv->value.i > pavt->limit))
612
109k
                                ) {
613
32
                                if (code >= 0)
614
32
                                    code =
615
32
                                        gs_note_error
616
32
                                        (errorIllegalAttributeDataType);
617
32
                            }
618
109k
                            if (pavt->proc != 0
619
14.4k
                                && (acode = (*pavt->proc) (pv)) < 0) {
620
11
                                if (code >= 0)
621
8
                                    code = acode;
622
11
                            }
623
109k
                            --left;
624
109k
                        }
625
297k
                    }
626
627
                    /* Make sure there are no attributes left over. */
628
102k
                    if (left)
629
99
                        code = gs_note_error(errorIllegalAttribute);
630
102k
                    if (code >= 0) {
631
102k
                        st->args.source.phase = 0;
632
102k
                        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
102k
                        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
102k
                    }
644
102k
                    if (code < 0)
645
426
                        goto x;
646
                    /* Check whether the operator wanted source data. */
647
102k
                    if (code == pxNeedData) {
648
13.8k
                        if (!pxs->data_source_open) {
649
0
                            code = gs_note_error(errorDataSourceNotOpen);
650
0
                            goto x;
651
0
                        }
652
13.8k
                        st->data_proc = pod->proc;
653
13.8k
                        ++p;
654
13.8k
                        goto top;
655
13.8k
                    }
656
102k
                }
657
88.3k
                clear_stack();
658
88.3k
                ++p;
659
88.3k
                continue;
660
72.7k
            case 24:
661
72.7k
                sp[1].type = pxd_scalar;
662
72.7k
                count = 1;
663
72.7k
                goto data;
664
23.6k
            case 26:
665
23.6k
                sp[1].type = pxd_xy;
666
23.6k
                count = 2;
667
23.6k
                goto data;
668
2.27k
            case 28:
669
2.27k
                sp[1].type = pxd_box;
670
2.27k
                count = 4;
671
2.27k
                goto data;
672
                /* Scalar, point, and box data */
673
98.7k
              data:{
674
98.7k
                    int i;
675
676
98.7k
                    if (sp == stack_limit) {
677
0
                        code = gs_note_error(errorInternalOverflow);
678
0
                        goto x;
679
0
                    }
680
98.7k
                    ++sp;
681
98.7k
                    sp->attribute = 0;
682
98.7k
                    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
98.7k
#  define trace_scalar(mem, format, cast, alt) DO_NOTHING
689
98.7k
#endif
690
98.7k
                    switch (tag & 7) {
691
57.9k
                        case pxt_ubyte & 7:
692
57.9k
                            sp->type |= pxd_ubyte;
693
115k
                            for (i = 0; i < count; ++p, ++i)
694
57.9k
                                sp->value.ia[i] = *p;
695
71.0k
                          dux:trace_scalar(pxs->memory, " %lu", ulong,
696
71.0k
                                         ia);
697
71.0k
                            --p;
698
71.0k
                            continue;
699
12.1k
                        case pxt_uint16 & 7:
700
12.1k
                            sp->type |= pxd_uint16;
701
29.6k
                            for (i = 0; i < count; p += 2, ++i)
702
17.4k
                                sp->value.ia[i] = get_uint16(st, p);
703
12.1k
                            goto dux;
704
968
                        case pxt_uint32 & 7:
705
968
                            sp->type |= pxd_uint32;
706
1.94k
                            for (i = 0; i < count; p += 4, ++i)
707
972
                                sp->value.ia[i] = get_uint32(st, p);
708
968
                            goto dux;
709
26.5k
                        case pxt_sint16 & 7:
710
26.5k
                            sp->type |= pxd_sint16;
711
78.0k
                            for (i = 0; i < count; p += 2, ++i)
712
51.5k
                                sp->value.ia[i] = get_sint16(st, p);
713
26.5k
                          dsx:trace_scalar(pxs->memory, " %ld", long,
714
26.5k
                                         ia);
715
26.5k
                            --p;
716
26.5k
                            continue;
717
9
                        case pxt_sint32 & 7:
718
9
                            sp->type |= pxd_sint32;
719
26
                            for (i = 0; i < count; p += 4, ++i)
720
17
                                sp->value.ia[i] = get_sint32(st, p);
721
9
                            goto dsx;
722
1.06k
                        case pxt_real32 & 7:
723
1.06k
                            sp->type |= pxd_real32;
724
2.36k
                            for (i = 0; i < count; p += 4, ++i)
725
1.30k
                                sp->value.ra[i] = get_real32(st, p);
726
1.06k
                            trace_scalar(pxs->memory, " %g", double, ra);
727
728
1.06k
                            --p;
729
1.06k
                            continue;
730
3
                        default:
731
3
                            break;
732
98.7k
                    }
733
98.7k
                }
734
3
                break;
735
12.1k
            case 25:
736
                /* Array data */
737
12.1k
                {
738
12.1k
                    const byte *dp;
739
12.1k
                    uint nbytes;
740
741
12.1k
                    if (sp == stack_limit) {
742
0
                        code = gs_note_error(errorInternalOverflow);
743
0
                        goto x;
744
0
                    }
745
12.1k
                    switch (p[2]) {
746
1.82k
                        case pxt_ubyte:
747
1.82k
                            sp[1].value.array.size = p[3];
748
1.82k
                            dp = p + 4;
749
1.82k
                            break;
750
10.3k
                        case pxt_uint16:
751
10.3k
                            if (left < 4) {
752
10
                                if_debug0m('i', memory, "...\n");
753
                                /* Undo the state transition. */
754
10
                                st->macro_state ^= syntax->state_transition;
755
10
                                goto x;
756
10
                            }
757
10.2k
                            sp[1].value.array.size = get_uint16(st, p + 3);
758
10.2k
                            dp = p + 5;
759
10.2k
                            break;
760
32
                        default:
761
32
                            st->last_operator = tag;    /* for error message */
762
32
                            code = gs_note_error(errorIllegalTag);
763
32
                            goto x;
764
12.1k
                    }
765
12.1k
                    nbytes = sp[1].value.array.size;
766
12.1k
                    if_debug1m('i', memory, "[%u]\n", sp[1].value.array.size);
767
12.1k
                    switch (tag) {
768
12.1k
                        case pxt_ubyte_array:
769
12.1k
                            sp[1].type = pxd_array | pxd_ubyte;
770
12.1k
                          array:++sp;
771
12.1k
                            if (st->big_endian)
772
0
                                sp->type |= pxd_big_endian;
773
12.1k
                            sp->value.array.data = dp;
774
12.1k
                            sp->attribute = 0;
775
                            /* Check whether we have enough data for the entire */
776
                            /* array. */
777
12.1k
                            if (rlimit + 1 - dp < nbytes) {     /* Exit now, continue reading when we return. */
778
224
                                uint avail = rlimit + 1 - dp;
779
780
224
                                code = px_save_array(sp, pxs, "partial array",
781
224
                                                     avail);
782
224
                                if (code < 0)
783
0
                                    goto x;
784
224
                                sp->type |= pxd_on_heap;
785
224
                                st->data_left = nbytes - avail;
786
224
                                st->data_proc = 0;
787
224
                                p = rlimit;
788
224
                                goto x;
789
224
                            }
790
11.8k
                            p = dp + nbytes - 1;
791
11.8k
                            trace_array(memory, sp);
792
11.8k
                            continue;
793
1
                        case pxt_uint16_array:
794
1
                            sp[1].type = pxd_array | pxd_uint16;
795
2
                          a16:nbytes <<= 1;
796
2
                            goto array;
797
0
                        case pxt_uint32_array:
798
0
                            sp[1].type = pxd_array | pxd_uint32;
799
0
                          a32:nbytes <<= 2;
800
0
                            goto array;
801
1
                        case pxt_sint16_array:
802
1
                            sp[1].type = pxd_array | pxd_sint16;
803
1
                            goto a16;
804
0
                        case pxt_sint32_array:
805
0
                            sp[1].type = pxd_array | pxd_sint32;
806
0
                            goto a32;
807
0
                        case pxt_real32_array:
808
0
                            sp[1].type = pxd_array | pxd_real32;
809
0
                            goto a32;
810
2
                        default:
811
2
                            break;
812
12.1k
                    }
813
2
                    break;
814
12.1k
                }
815
2
                break;
816
110k
            case 31:
817
110k
                {
818
110k
                    px_attribute_t attr;
819
110k
                    const byte *pnext;
820
821
110k
                    switch (tag) {
822
109k
                        case pxt_attr_ubyte:
823
109k
                            attr = p[2];
824
109k
                            pnext = p + 2;
825
109k
                            goto a;
826
1
                        case pxt_attr_uint16:
827
1
                            attr = get_uint16(st, p + 2);
828
1
                            pnext = p + 3;
829
109k
                          a:if (attr >=
830
109k
                                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
109k
                            sp->attribute = attr;
843
109k
                            if (st->attribute_indices[attr] != 0) {
844
10
                                px_value_t *old_sp =
845
10
                                    &st->stack[st->attribute_indices[attr]];
846
                                /* If the old value is on the heap, free it. */
847
10
                                if (old_sp->type & pxd_on_heap)
848
0
                                    gs_free_object(memory,
849
10
                                                   (void *)old_sp->value.
850
10
                                                   array.data,
851
10
                                                   "old value for duplicate attribute");
852
10
                                *old_sp = *sp--;
853
10
                            } else
854
109k
                                st->attribute_indices[attr] = sp - st->stack;
855
109k
                            p = pnext;
856
109k
                            continue;
857
27
                        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
27
                            if (uint32at(p + 2, true /*arbitrary */ ) == 0) {
865
1
                                p += 5;
866
1
                                continue;
867
1
                            }
868
26
                            break;
869
30
                        case pxt_dataLengthByte:
870
                            /* See the comment under pxt_dataLength above. */
871
30
                            if (p[2] == 0) {
872
21
                                p += 2;
873
21
                                continue;
874
21
                            }
875
9
                            break;
876
185
                        default:
877
185
                            break;
878
110k
                    }
879
110k
                }
880
309
                break;
881
354
            default:
882
354
                break;
883
359k
        }
884
        /* Unknown tag value.  Report an error. */
885
1.47k
        st->last_operator = tag;        /* for error message */
886
1.47k
        code = gs_note_error(errorIllegalTag);
887
1.47k
        break;
888
359k
    }
889
6.01k
  x:                           /* Save any leftover input. */
890
6.01k
    left = rlimit - p;
891
6.01k
    if (rlimit != pr->limit) {  /* We were reading saved input. */
892
210
        if (left <= next_p - orig_p) {  /* We finished reading the previously saved input. */
893
            /* Continue reading current input, unless we got an error. */
894
208
            p = next_p -= left;
895
208
            rlimit = pr->limit;
896
208
            st->saved_count = 0;
897
208
            if (code >= 0)
898
148
                goto parse;
899
208
        } 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
210
    }
906
    /* Except in case of error, save any remaining input. */
907
5.86k
    if (code >= 0) {
908
840
        if (left + st->saved_count > sizeof(st->saved)) {       /* Fatal error -- shouldn't happen! */
909
10
            code = gs_note_error(errorInternalOverflow);
910
10
            st->saved_count = 0;
911
830
        } else {
912
830
            memcpy(&st->saved[st->saved_count], p + 1, left);
913
830
            st->saved_count += left;
914
830
            p = rlimit;
915
830
        }
916
840
    }
917
5.86k
    pr->ptr = p;
918
5.86k
    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.08k
    for (; sp > st->stack; --sp)
922
3.21k
        if ((sp->type & (pxd_array | pxd_on_heap)) == pxd_array) {
923
426
            int code = px_save_array(sp, pxs, "px stack array to heap",
924
426
                                     sp->value.array.size * value_size(sp));
925
926
426
            if (code < 0)
927
0
                break;
928
426
            sp->type |= pxd_on_heap;
929
426
        }
930
5.86k
    if (code < 0 && syntax != 0) {      /* Undo the state transition. */
931
5.02k
        st->macro_state ^= syntax->state_transition;
932
5.02k
    }
933
5.86k
    return code;
934
6.01k
}
935
936
uint
937
px_parser_data_left(px_parser_state_t * pxp)
938
4
{
939
4
    return pxp->data_left;
940
4
}