Coverage Report

Created: 2026-08-08 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pcl/pcparse.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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
/* pcparse.c */
18
/* PCL5 parser */
19
#include "stdio_.h"
20
#include "gdebug.h"
21
#include "gstypes.h"
22
#include "scommon.h"
23
#include "pcparse.h"
24
#include "pcstate.h"            /* for display_functions */
25
#include "pcursor.h"
26
#include "rtmisc.h"
27
#include "rtgmode.h"
28
#include "rtraster.h"
29
30
/* We don't know whether an Enable Display Functions takes effect while */
31
/* defining a macro.  To play it safe, we're providing both options. */
32
/* If the following #define is uncommented, E.D.F. *does* take effect */
33
/* while scanning a macro definition. */
34
/*#define DISPLAY_FUNCTIONS_IN_MACRO*/
35
36
/* ---------------- Command definition ---------------- */
37
38
/* Register a command.  Return true if this is a redefinition. */
39
static bool
40
pcl_register_command(byte * pindex, const pcl_command_definition_t * pcmd,
41
                     pcl_parser_state_t * pcl_parser_state)
42
3.28M
{
43
3.28M
    int index = pcl_parser_state->definitions->pcl_command_next_index;
44
45
3.28M
    byte prev = *pindex;
46
47
3.28M
    if (prev != 0 && prev <= index
48
16.1k
        && pcl_parser_state->definitions->pcl_command_list[prev] == pcmd)
49
0
        index = prev;
50
3.28M
    else if (index != 0
51
3.26M
             && pcl_parser_state->definitions->pcl_command_list[index] ==
52
3.26M
             pcmd);
53
3.28M
    else
54
3.28M
        pcl_parser_state->definitions->
55
3.28M
            pcl_command_list
56
3.28M
            [pcl_parser_state->definitions->pcl_command_next_index =
57
3.28M
             ++index] = (pcl_command_definition_t *) pcmd;
58
3.28M
    *pindex = index;
59
3.28M
    return (prev != 0 && prev != index);
60
3.28M
}
61
62
/* Define a command or list of commands. */
63
void
64
pcl_define_control_command(int /*char */ chr,
65
                           const pcl_command_definition_t * pcmd,
66
                           pcl_parser_state_t * pcl_parser_state)
67
144k
{
68
#ifdef DEBUG
69
    if (chr < 0
70
        || chr >=
71
        countof(pcl_parser_state->definitions->pcl_control_command_indices))
72
        if_debug1('I', "Invalid control character %d\n", chr);
73
    else if (
74
#endif
75
144k
                pcl_register_command(&pcl_parser_state->
76
144k
                                     definitions->pcl_control_command_indices
77
144k
                                     [chr], pcmd, pcl_parser_state)
78
#ifdef DEBUG
79
        )
80
        if_debug1('I', "Redefining control character %d\n", chr);
81
#endif
82
144k
    ;
83
144k
}
84
void
85
pcl_define_escape_command(int /*char */ chr,
86
                          const pcl_command_definition_t * pcmd,
87
                          pcl_parser_state_t * pcl_parser_state)
88
96.6k
{
89
#ifdef DEBUG
90
    if (chr < min_escape_2char || chr > max_escape_2char)
91
        if_debug1('I', "Invalid escape character %c\n", chr);
92
    else if (
93
#endif
94
96.6k
                pcl_register_command(&pcl_parser_state->
95
96.6k
                                     definitions->pcl_escape_command_indices
96
96.6k
                                     [chr - min_escape_2char], pcmd,
97
96.6k
                                     pcl_parser_state)
98
#ifdef DEBUG
99
        )
100
        if_debug1('I', "Redefining ESC %c\n", chr)
101
#endif
102
96.6k
            ;
103
96.6k
}
104
105
/*
106
 * Convert escape classes to second level dispatch indices.
107
 */
108
static const byte pcl_escape_class_indices[max_escape_class -
109
                                           min_escape_class + 1] = {
110
    0, 0, 0, 0, 1 /*% */ , 2 /*& */ , 0, 3 /*( */ , 4 /*) */ , 5 /***/ , 0, 0,
111
    0, 0, 0
112
};
113
114
void
115
pcl_define_class_command(int /*char */ class, int /*char */ group,
116
                         int /*char */ command,
117
                         const pcl_command_definition_t * pcmd,
118
                         pcl_parser_state_t * pcl_parser_state)
119
3.04M
{
120
#ifdef DEBUG
121
    if (class < min_escape_class || class > max_escape_class ||
122
        pcl_escape_class_indices[class - min_escape_class] == 0 ||
123
        (group != 0 && (group < min_escape_group || group > max_escape_group))
124
        || command < min_escape_command || command > max_escape_command)
125
        if_debug3('I', "Invalid command %c %c %c\n", class, group, command);
126
    else if (
127
#endif
128
3.04M
                pcl_register_command(&pcl_parser_state->
129
3.04M
                                     definitions->pcl_grouped_command_indices
130
3.04M
                                     [pcl_escape_class_indices
131
3.04M
                                      [class - min_escape_class] - 1]
132
3.04M
                                     [group ==
133
3.04M
                                      0 ? 0 : group - min_escape_group + 1]
134
3.04M
                                     [command - min_escape_command], pcmd,
135
3.04M
                                     pcl_parser_state)
136
#ifdef DEBUG
137
        )
138
        if_debug3('I', "Redefining ESC %c %c %c\n", class,
139
                  (group == 0 ? ' ' : group), command)
140
#endif
141
3.04M
            ;
142
3.04M
}
143
void
144
pcl_define_class_commands(int /*char */ class,
145
                          const pcl_grouped_command_definition_t * pgroup,
146
                          pcl_parser_state_t * pcl_parser_state)
147
515k
{
148
515k
    const pcl_grouped_command_definition_t *pgc = pgroup;
149
150
2.44M
    for (; pgc->command != 0; ++pgc)
151
1.93M
        pcl_define_class_command(class, pgc->group, pgc->command,
152
1.93M
                                 &pgc->defn, pcl_parser_state);
153
515k
}
154
155
/*
156
 * Look up an escape command.  The arguments are as follows:
157
 *  ESC x   0, 0, 'x'
158
 *  ESC ? <arg> c '?', 0, 'c'
159
 *  ESC ? b <arg> c '?', 'b', 'c'
160
 * The caller is responsible for providing valid arguments.
161
 */
162
static const pcl_command_definition_t *
163
pcl_get_command_definition(pcl_parser_state_t * pcl_parser_state,
164
                           int /*char */ class,
165
                           int /*char */ group,
166
                           int /*char */ command)
167
461k
{
168
461k
    const pcl_command_definition_t *cdefn = 0;
169
170
461k
    if (class == 0) {
171
202k
        if (command >= min_escape_2char && command <= max_escape_2char)
172
26.6k
            cdefn = pcl_parser_state->definitions->pcl_command_list
173
26.6k
                [pcl_parser_state->
174
26.6k
                 definitions->pcl_escape_command_indices[command -
175
26.6k
                                                         min_escape_2char]];
176
259k
    } else {
177
259k
        int class_index = pcl_escape_class_indices[class - min_escape_class];
178
179
259k
        if (class_index)
180
257k
            cdefn = pcl_parser_state->definitions->pcl_command_list
181
257k
                [pcl_parser_state->
182
257k
                 definitions->pcl_grouped_command_indices[class_index - 1]
183
257k
                 [group ? group - min_escape_group + 1 : 0]
184
257k
                 [command - min_escape_command]
185
257k
                ];
186
259k
    }
187
#ifdef DEBUG
188
    if (cdefn == 0) {
189
        if (class == 0)
190
            if_debug1('I', "ESC %c undefined\n", command);
191
        else if (group == 0)
192
            if_debug2('I', "ESC %c %c undefined\n", class, command);
193
        else
194
            if_debug3('I', "ESC %c %c %c undefined\n", class, group, command);
195
    }
196
#endif
197
461k
    return cdefn;
198
461k
}
199
200
/* ---------------- Parsing ---------------- */
201
202
/* Initialize the parser state. */
203
int
204
pcl_process_init(pcl_parser_state_t * pst, pcl_state_t * pcs)
205
19.5k
{
206
19.5k
    pcl_args_t args;
207
19.5k
    int code = 0;
208
19.5k
    pst->scan_type = scanning_none;
209
19.5k
    pst->args.data = 0;
210
19.5k
    pst->args.data_on_heap = false;
211
19.5k
    pst->short_hand = false;
212
19.5k
    pst->min_bytes_needed = 0;
213
214
    /*
215
     * RTL Files should start with a PCL escape sequence to enter the
216
     * GL/2 parser but many do not, so we start in HPGL.  If an escape
217
     * sequence is detected the parse mode returns to PCL.
218
     */
219
220
19.5k
    if (pcs->personality == rtl) {
221
0
        arg_set_uint(&args, 0);
222
0
        code = rtl_enter_hpgl_mode(&args, pcs);
223
0
    }
224
19.5k
    return code;
225
19.5k
}
226
227
/* Adjust the argument value according to the command's argument type. */
228
/* Return 1 if the command should be ignored. */
229
static int
230
pcl_adjust_arg(pcl_args_t * pargs, const pcl_command_definition_t * pdefn)
231
241k
{
232
241k
    uint acts = pdefn->actions;
233
234
241k
    if (value_is_neg(&pargs->value)) {
235
8.32k
        switch (acts & pca_neg_action) {
236
0
            case pca_neg_clamp:
237
0
                arg_set_uint(pargs, 0);
238
0
                break;
239
191
            case pca_neg_error:
240
191
                return e_Range;
241
0
            case pca_neg_ignore:
242
0
                return 1;
243
8.13k
            default:           /* case pca_neg_ok */
244
8.13k
                ;
245
8.32k
        }
246
233k
    } else if (pargs->value.i > 32767)  /* overflowed int range */
247
272
        switch (acts & pca_big_action) {
248
8
            case pca_big_clamp:
249
8
                arg_set_uint(pargs, 32767);
250
8
                break;
251
149
            case pca_big_error:
252
149
                return e_Range;
253
14
            case pca_big_ignore:
254
14
                return 1;
255
101
            default:           /* case pca_big_ok */
256
101
                ;
257
272
        }
258
241k
    return 0;
259
241k
}
260
261
/* Append some just-scanned input data to the macro being defined. */
262
static int
263
append_macro(const byte * from, const byte * to, pcl_state_t * pcs)
264
84
{
265
84
    if (pcs->macro_definition != NULL) {
266
84
        uint count = to - from;
267
84
        uint size = gs_object_size(pcs->memory, pcs->macro_definition);
268
84
        byte *new_defn =
269
84
            gs_resize_object(pcs->memory, pcs->macro_definition, size + count,
270
84
                             "append_macro");
271
272
84
        if (new_defn == 0)
273
0
            return_error(e_Memory);
274
84
        memcpy(new_defn + size, from + 1, count);
275
84
        pcs->macro_definition = new_defn;
276
84
    }
277
84
    return 0;
278
84
}
279
280
#ifdef DEBUG
281
static void
282
debug_dump_char(gs_memory_t *mem, char chr)
283
{
284
    dmprintf1(mem, (chr >= 33 && chr <= 126 ?
285
                    "%c" : "\\%03o"), (unsigned char)chr);
286
    if (chr == '\\')
287
        dmprintf1(mem, "%c", '\\');
288
    return;
289
}
290
#endif
291
292
/* Process a buffer of PCL commands. */
293
int
294
pcl_process(pcl_parser_state_t * pst, pcl_state_t * pcs,
295
            stream_cursor_read * pr)
296
2.33M
{
297
2.33M
    const byte *p = pr->ptr;
298
2.33M
    const byte *rlimit = pr->limit;
299
2.33M
    int code = 0;
300
2.33M
    int bytelen = 0;
301
2.33M
    bool in_macro = pcs->defining_macro;
302
    /* Record how much of the input we've copied into a macro */
303
    /* in the process of being defined. */
304
2.33M
    const byte *macro_p = p;
305
306
2.46M
top:
307
    /* Reset the parameter scanner */
308
25.3M
#define avalue pst->args.value
309
2.46M
#define param_init()\
310
12.0M
  (avalue.type = pcv_none, avalue.i = 0)
311
312
#ifdef DISPLAY_FUNCTIONS_IN_MACRO
313
#  define do_display_functions() 1
314
#else
315
2.46M
#  define do_display_functions() (!in_macro)
316
2.46M
#endif
317
318
2.46M
    if (rlimit - p < pst->min_bytes_needed) {
319
621
        pst->min_bytes_needed = 0;
320
621
        p = rlimit;
321
621
        goto x;
322
2.46M
    } else {
323
2.46M
        pst->min_bytes_needed = 0;
324
2.46M
    }
325
326
15.7M
    while (p < rlimit) {
327
13.4M
        byte chr = 0x00; /* silence a compiler warning */
328
13.4M
        const pcl_command_definition_t *cdefn = NULL;
329
13.4M
        switch (pst->scan_type) {
330
2.85k
            case scanning_data:
331
2.85k
                {               /* Accumulate command data in a buffer. */
332
2.85k
                    uint count = uint_arg(&pst->args);
333
2.85k
                    uint pos = pst->data_pos;
334
335
2.85k
                    if (pos < count) {
336
2.09k
                        uint avail = rlimit - p;
337
2.09k
                        uint copy = min(count - pos, avail);
338
339
2.09k
                        memcpy(pst->args.data + pos, p + 1, copy);
340
2.09k
                        pst->data_pos += copy;
341
2.09k
                        p += copy;
342
2.09k
                        continue;
343
2.09k
                    }
344
                    /* Invoke the command. */
345
761
                    cdefn = pcl_get_command_definition(pst,
346
761
                                                       pst->param_class,
347
761
                                                       pst->param_group,
348
761
                                                       pst->args.command);
349
761
                    if (pst->short_hand) {
350
1
                        pst->scan_type = scanning_parameter;
351
1
                    } else
352
760
                        pst->scan_type = scanning_none;
353
761
                    break;
354
2.85k
                }
355
1.06M
            case scanning_display:
356
1.06M
                {
357
                    /* Display, don't execute, all characters. */
358
1.06M
                    chr = *++p;
359
1.06M
                    if (chr == ESC) {
360
59.5k
                        int index;
361
362
59.5k
                        if (p >= rlimit)
363
35
                            goto x;
364
59.5k
                        if (p[1] >= min_escape_2char
365
4.25k
                            && p[1] <= max_escape_2char
366
2.13k
                            && (index =
367
2.13k
                                pst->
368
2.13k
                                definitions->pcl_escape_command_indices[p[1] -
369
2.13k
                                                                        min_escape_2char])
370
2.13k
                            != 0
371
216
                            && pst->definitions->
372
216
                            pcl_command_list[index]->proc ==
373
216
                            pcl_disable_display_functions) {
374
38
                            if (do_display_functions()) {
375
38
                                pst->args.command = chr;
376
38
                                code = pcl_plain_char(&pst->args, pcs);
377
38
                                if (code < 0)
378
0
                                    goto x;
379
38
                            }
380
38
                            pst->args.command = chr = *++p;
381
38
                            pcl_disable_display_functions(&pst->args, pcs);
382
38
                            pst->scan_type = scanning_none;
383
38
                        }
384
59.5k
                    }
385
1.06M
                    if (do_display_functions()) {
386
1.06M
                        if (chr == CR) {
387
4.36k
                            code = pcl_do_CR(pcs);
388
4.36k
                            if (code >= 0)
389
4.36k
                                code = pcl_do_LF(pcs);
390
1.06M
                        } else {
391
1.06M
                            pst->args.command = chr;
392
1.06M
                            code = pcl_plain_char(&pst->args, pcs);
393
1.06M
                        }
394
1.06M
                        if (code < 0)
395
0
                            goto x;
396
1.06M
                    }
397
1.06M
                    continue;
398
1.06M
                }
399
1.06M
            case scanning_parameter:
400
760k
                for (;;) {
401
760k
                    if (p >= rlimit)
402
340
                        goto x;
403
760k
                    chr = *++p;
404
                    /*
405
                     * The parser for numbers is very lenient, and accepts
406
                     * many strings that aren't valid numbers.  If this
407
                     * ever becomes a problem, we can tighten it up....
408
                     */
409
760k
                    if (pst->garbage_in_parameter) {
410
35.8k
                        if (chr < ' ' || chr > '?') {
411
2.64k
                            pst->garbage_in_parameter = false; /* no garbage anymore */
412
2.64k
                            break;
413
2.64k
                        }
414
724k
                    } else {
415
724k
                        if (chr >= '0' && chr <= '9') {
416
428k
                            chr -= '0';
417
428k
                            if (value_is_float(&avalue))
418
8.69k
                                avalue.fraction += (chr / (pst->scale *= 10));
419
420k
                            else
420
420k
                                avalue.type |= pcv_int,
421
420k
                                    avalue.i = avalue.i * 10 + chr;
422
428k
                        } else if (chr == '-')
423
10.5k
                            avalue.type |= pcv_neg;
424
284k
                        else if (chr == '+')
425
1.00k
                            avalue.type |= pcv_pos;
426
283k
                        else if (chr == '.')
427
4.74k
                            avalue.type |= pcv_float,
428
4.74k
                                avalue.fraction = 0, pst->scale = 1.0;
429
279k
                        else if (chr == ' ')
430
759
                            continue;
431
278k
                        else if (chr >= ' ' && chr <= '?') {        /* Ignore garbage nearby in the code space. */
432
                            /* skip the remainder until a chr outside this range is found */
433
9.81k
                            if (avalue.type != pcv_none)
434
2.65k
                                pst->garbage_in_parameter = true;
435
9.81k
                            continue;
436
9.81k
                        } else
437
268k
                            break;
438
724k
                    }
439
760k
                }
440
#ifdef DEBUG
441
                if (gs_debug_c('i')) {
442
                    dmprintf(pcs->memory, "ESC ");
443
                    debug_dump_char(pcs->memory, pst->param_class);
444
                    dmprintf(pcs->memory, " ");
445
                    debug_dump_char(pcs->memory, pst->param_group);
446
                    if (value_is_present(&avalue)) {
447
                        dmputc(pcs->memory, ' ');
448
                        if (value_is_signed(&avalue))
449
                            dmputc(pcs->memory,
450
                                   (value_is_neg(&avalue) ? '-' : '+'));
451
                        if (value_is_float(&avalue))
452
                            dmprintf1(pcs->memory, "%g",
453
                                      avalue.i + avalue.fraction);
454
                        else
455
                            dmprintf1(pcs->memory, "%u", avalue.i);
456
                    }
457
                    dmprintf1(pcs->memory, " %c\n", chr);
458
                }
459
#endif
460
271k
                pst->short_hand = false;
461
271k
                if (chr >= min_escape_command + 32 &&
462
102k
                    chr <= max_escape_command + 32) {
463
98.5k
                    pst->short_hand = true;
464
98.5k
                    chr -= 32;
465
172k
                } else if (chr >= min_escape_command &&
466
164k
                           chr <= max_escape_command)
467
160k
                    pst->scan_type = scanning_none;
468
12.3k
                else {
469
12.3k
                    pst->scan_type = scanning_none;
470
                    /* Rescan the out-of-place character. */
471
12.3k
                    --p;
472
12.3k
                    continue;
473
12.3k
                }
474
                /* Dispatch on param_class, param_group, and chr. */
475
258k
                cdefn = pcl_get_command_definition(pst,
476
258k
                                                   pst->param_class,
477
258k
                                                   pst->param_group, chr);
478
258k
                if (cdefn) {
479
241k
                    if_debug1m('i', pcs->memory, "   [%s]\n", cdefn->cname);
480
241k
                    code = pcl_adjust_arg(&pst->args, cdefn);
481
241k
                    if (code < 0)
482
0
                        goto x;
483
241k
                    if (cdefn->actions & pca_byte_data) {
484
71.0k
                        uint count = uint_arg(&pst->args);
485
486
71.0k
                        if ((count > 0) && (rlimit - p < count)) {
487
1.26k
                            pst->args.data =
488
1.26k
                                gs_alloc_bytes(pcs->memory, count,
489
1.26k
                                               "command data");
490
1.26k
                            if (pst->args.data == 0) {
491
0
                                --p;
492
0
                                code = gs_note_error(e_Memory);
493
0
                                (void)pcl_grestore(pcs);
494
0
                                goto x;
495
0
                            }
496
1.26k
                            pst->args.data_on_heap = true;
497
1.26k
                            pst->args.command = chr;
498
1.26k
                            pst->data_pos = 0;
499
1.26k
                            pst->scan_type = scanning_data;
500
1.26k
                            continue;
501
1.26k
                        }
502
69.8k
                        pst->args.data = (byte *) (p + 1);
503
69.8k
                        pst->args.data_on_heap = false;
504
69.8k
                        p += count;
505
69.8k
                    }
506
240k
                    break;
507
241k
                }
508
17.0k
                param_init();
509
17.0k
                continue;
510
12.0M
            case scanning_none:
511
12.0M
                if (pcs->parse_other) { /* HPGL/2 mode */
512
172k
                    pr->ptr = p;
513
172k
                    code = (*pcs->parse_other)
514
172k
                        (pcs->parse_data, pcs, pr);
515
172k
                    p = pr->ptr;
516
172k
                    if (code < 0 || (code == 0 && pcs->parse_other))
517
//                        goto x;
518
125k
                        goto top;
519
172k
                }
520
521
11.9M
                chr = *++p;
522
                /* check for multi-byte scanning */
523
11.9M
                bytelen = pcl_char_bytelen(chr, pcs->text_parsing_method);
524
11.9M
                if (bytelen == 0) {
525
12
                    bytelen = 1;        /* invalid utf-8 leading char */
526
12
                }
527
11.9M
                if (bytelen > 1) {
528
                    /* check if we need more data */
529
410k
                    if ((p + bytelen - 1) > rlimit) {
530
41
                        pst->min_bytes_needed = 2;
531
41
                        --p;
532
41
                        goto x;
533
41
                    }
534
410k
                    if_debug2m('i', pcs->memory, "%x%x\n", p[0], p[1]);
535
410k
                    code = pcl_text(p, bytelen, pcs, false);
536
410k
                    if (code < 0)
537
0
                        goto x;
538
                    /* now pass over the remaining bytes */
539
410k
                    p += (bytelen - 1);
540
410k
                    cdefn = NULL;
541
11.5M
                } else if (chr != ESC) {
542
#ifdef DEBUG
543
                    if (gs_debug_c('i')) {
544
                        if_debug1m('i', pcs->memory, "[i%d] ", bytelen);
545
                        debug_dump_char(pcs->memory, chr);
546
                        if_debug0m('i', pcs->memory, "\n");
547
                    }
548
#endif
549
11.1M
                    cdefn = pst->definitions->pcl_command_list
550
11.1M
                        [chr < 33 ?
551
5.40M
                         pst->definitions->pcl_control_command_indices[chr] :
552
11.1M
                         pst->definitions->pcl_control_command_indices[1]];
553
11.1M
                    if ((cdefn == 0 || cdefn->proc == pcl_plain_char) &&
554
10.3M
                        !in_macro && !pcs->parse_other
555
10.3M
                        && !pcs->raster_state.graphics_mode) {
556
                        /* Look ahead for a run of plain text.  We can
557
                           be very conservative about this, because
558
                           this is only a performance enhancement. */
559
10.3M
                        const byte *str = p;
560
561
15.8M
                        while (p < rlimit && p[1] >= 32 && p[1] <= 127) {
562
#ifdef DEBUG
563
                            if (gs_debug_c('i')) {
564
                                if (p == str)
565
                                    if_debug1m('i', pcs->memory, "[i%d] ", bytelen);
566
                                debug_dump_char(pcs->memory, p[1]);
567
                            }
568
#endif
569
5.50M
                            ++p;
570
5.50M
                        }
571
572
10.3M
                        if_debug0m('i', pcs->memory, "\n");
573
10.3M
                        code = pcl_text(str, (uint) (p + 1 - str),
574
10.3M
                                        pcs, false);
575
10.3M
                        if (code < 0)
576
0
                            goto x;
577
10.3M
                        cdefn = NULL;
578
10.3M
                    }
579
11.1M
                } else {
580
376k
                    if (p >= rlimit) {
581
1.20k
                        pst->min_bytes_needed = 2;
582
1.20k
                        --p;
583
1.20k
                        goto x;
584
1.20k
                    }
585
375k
                    chr = *++p;
586
375k
                    if (chr < min_escape_class || chr > max_escape_class) {
587
202k
                        cdefn = pcl_get_command_definition(pst, 0, 0, chr);
588
202k
                        if (!cdefn) {
589
                            /* Skip the ESC, back up
590
                               to the char following the
591
                               ESC. */
592
188k
                            --p;
593
#ifdef DEBUG
594
                            if (gs_debug_c('i')) {
595
                                debug_dump_char(pcs->memory, '\033');
596
                            }
597
#endif
598
188k
                            continue;
599
188k
                        }
600
#ifdef DEBUG
601
                        if (gs_debug_c('i')) {
602
                            dmprintf(pcs->memory, "ESC ");
603
                            debug_dump_char(pcs->memory, chr);
604
                            dmprintf(pcs->memory, "\n");
605
                            dmprintf1(pcs->memory, "   [%s]\n", cdefn->cname);
606
                        }
607
#endif
608
202k
                    } else {
609
173k
                        if (p >= rlimit) {
610
171
                            p -= 2;
611
171
                            pst->min_bytes_needed = 3;
612
171
                            goto x;
613
171
                        }
614
172k
                        pst->param_class = chr;
615
172k
                        chr = *++p;
616
172k
                        if (chr < min_escape_group || chr > max_escape_group) { /* Class but no group */
617
30.6k
                            --p;
618
30.6k
                            chr = 0;
619
30.6k
                        }
620
172k
                        pst->param_group = chr;
621
172k
                        pst->scan_type = scanning_parameter;
622
172k
                        pst->garbage_in_parameter = false;
623
172k
                        param_init();
624
172k
                        continue;
625
173k
                    }
626
375k
                }
627
11.6M
                break;
628
13.4M
        }
629
11.8M
        if (cdefn == NULL) {
630
10.7M
            param_init();
631
10.7M
            continue;
632
10.7M
        }
633
1.05M
        if (!in_macro || (cdefn->actions & pca_in_macro)) {
634
            /* This might be the end-of-macro command. */
635
            /* Make sure all the data through this point */
636
            /* has been captured in the macro definition. */
637
1.04M
            if (in_macro) {
638
11
                code = append_macro(macro_p, p, pcs);
639
11
                macro_p = p;
640
11
                if (code < 0)
641
0
                    goto x;
642
11
            }
643
1.04M
            pst->args.command = chr;
644
1.04M
            if (!pcs->raster_state.graphics_mode ||
645
109k
                (cdefn->actions & pca_raster_graphics) ||
646
5.20k
                (code = pcl_end_graphics_mode_implicit(pcs,
647
5.20k
                                                       cdefn->
648
5.20k
                                                       actions &
649
5.20k
                                                       pca_dont_lockout_in_rtl))
650
1.04M
                >= 0) {
651
1.04M
                if ((pcs->personality != rtl) || ((pcs->personality == rtl)
652
0
                                                  && (cdefn->
653
0
                                                      actions & pca_in_rtl)))
654
1.04M
                    code = (*cdefn->proc) (&pst->args, pcs);
655
1.04M
            }
656
            /*
657
             * If we allocated a buffer for command data,
658
             * and the command didn't take possession of it,
659
             * free it now.
660
             */
661
1.04M
            if (pst->args.data_on_heap && pst->args.data) {
662
745
                gs_free_object(pcs->memory, pst->args.data, "command data");
663
745
                pst->args.data = 0;
664
745
            }
665
1.04M
            if (code == e_Unimplemented) {
666
#if e_Unimplemented != 0
667
                if_debug0m('i', pcs->memory, "Unimplemented\n");
668
#endif
669
1.04M
            } else if (code < 0)
670
5.56k
                break;
671
1.04M
            if (pcs->display_functions) {
672
                /* This calls for a special parsing state. */
673
135
                pst->scan_type = scanning_display;
674
135
            }
675
1.04M
            if (pcs->defining_macro && !in_macro) {
676
                /* We just started a macro definition. */
677
39
                if (pst->scan_type != scanning_none) {
678
                    /* macro was defined with an incomple combined command */
679
                    /* start definition of macro with esc&f preloaded */
680
1
                    static const byte macro_prefix[4] = " \033&f";
681
682
1
                    code = append_macro(&macro_prefix[0], &macro_prefix[3], pcs);
683
1
                    if (code < 0)
684
0
                        goto x;
685
1
                }
686
39
                macro_p = p;
687
39
            }
688
1.04M
            in_macro = pcs->defining_macro;
689
1.04M
        } else {
690
            /*
691
             * If we allocated a buffer for command data,
692
             * free it now.
693
             */
694
6.34k
            if (pst->args.data_on_heap && pst->args.data) {
695
16
                gs_free_object(pcs->memory, pst->args.data, "command data");
696
16
                pst->args.data = 0;
697
16
            }
698
6.34k
        }
699
1.04M
        param_init();
700
1.04M
    }
701
2.33M
  x:pr->ptr = p;
702
    /* Append the last bit of data to the macro, if defining. */
703
2.33M
    if (in_macro) {
704
72
        int mcode = append_macro(macro_p, p, pcs);
705
706
72
        if (mcode < 0 && code >= 0)
707
0
            code = mcode;
708
72
    }
709
2.33M
    if (code < 0) {
710
        /* This avoids memento squeeze leaks. */
711
5.56k
        (void) pcl_complete_raster(pcs);
712
5.56k
    }
713
2.33M
    return code;
714
2.46M
}
715
716
/* inialize the pcl command counter */
717
int
718
pcl_init_command_index(pcl_parser_state_t * pcl_parser_state,
719
                       pcl_state_t * pcs)
720
16.1k
{
721
16.1k
    pcl_command_definitions_t *definitions =
722
16.1k
        (pcl_command_definitions_t *) gs_alloc_bytes(pcs->memory,
723
16.1k
                                                     sizeof
724
16.1k
                                                     (pcl_command_definitions_t),
725
16.1k
                                                     "pcl_init_command_index");
726
727
    /* fatal */
728
16.1k
    if (definitions == 0)
729
0
        return -1;
730
    /* we should set these individually but each field is properly
731
       initialized to zero */
732
16.1k
    memset(definitions, 0, sizeof(pcl_command_definitions_t));
733
    /* plug command definitions into the parser state and a pointer
734
       for the command definitions into pcl's state for use by macros,
735
       I don't like this but the alternative is getting the parser
736
       state to the code that executer macros which is inconvenient at
737
       this time */
738
16.1k
    pcs->pcl_commands = pcl_parser_state->definitions = definitions;
739
16.1k
    return 0;
740
16.1k
}
741
742
/* for now deallocates the memory associated with the command definitions */
743
int
744
pcl_parser_shutdown(pcl_parser_state_t * pcl_parser_state, gs_memory_t * mem)
745
16.1k
{
746
16.1k
    gs_free_object(mem, pcl_parser_state->definitions, "pcl_parser_shutdown");
747
16.1k
    return 0;
748
16.1k
}
749
/* ---------------- Initialization ---------------- */
750
751
int
752
pcparse_do_reset(pcl_state_t * pcs, pcl_reset_type_t type)
753
49.4k
{
754
49.4k
    if (type & (pcl_reset_initial | pcl_reset_printer))
755
49.4k
        pcs->parse_other = 0;
756
757
49.4k
    return 0;
758
49.4k
}
759
760
const pcl_init_t pcparse_init = {
761
    0, pcparse_do_reset
762
};