Coverage Report

Created: 2026-04-09 07:06

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