Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/psi/zmisc3.c
Line
Count
Source (jump to first uncovered line)
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
/* Miscellaneous LanguageLevel 3 operators */
18
#include "ghost.h"
19
#include "gscspace.h"   /* for gscolor2.h */
20
#include "gsmatrix.h"   /* ditto */
21
#include "gsclipsr.h"
22
#include "gscolor2.h"
23
#include "oper.h"
24
#include "igstate.h"
25
#include "store.h"
26
27
/* - clipsave - */
28
static int
29
zclipsave(i_ctx_t *i_ctx_p)
30
1
{
31
1
    return gs_clipsave(igs);
32
1
}
33
34
/* - cliprestore - */
35
static int
36
zcliprestore(i_ctx_t *i_ctx_p)
37
3
{
38
3
    return gs_cliprestore(igs);
39
3
}
40
41
static inline bool
42
eqproc_check_type(ref *r)
43
199k
{
44
199k
    return r_has_type(r, t_array)
45
199k
           || r_has_type(r, t_mixedarray)
46
199k
           || r_has_type(r, t_shortarray)
47
199k
           || r_has_type(r, t_oparray);
48
199k
}
49
50
/* <proc1> <proc2> .eqproc <bool> */
51
/*
52
 * Test whether two procedures are equal to depth 10.
53
 * This is the equality test used by idiom recognition in 'bind'.
54
 */
55
/* Adobe specifies maximum depth of 10 but 12 is needed */
56
/* to reproduce the observed behavior. CET 31-01-05 */
57
183
#define MAX_DEPTH 12
58
typedef struct ref2_s {
59
    ref proc1, proc2;
60
} ref2_t;
61
static int
62
zeqproc(i_ctx_t *i_ctx_p)
63
99.7k
{
64
99.7k
    os_ptr op = osp;
65
99.7k
    ref2_t stack[MAX_DEPTH + 1];
66
99.7k
    ref2_t *top = stack;
67
68
99.7k
    check_op(2);
69
99.7k
    if (!eqproc_check_type(op -1) || !eqproc_check_type(op)) {
70
0
        make_false(op - 1);
71
0
        pop(1);
72
0
        return 0;
73
0
    }
74
75
99.7k
    make_array(&stack[0].proc1, 0, 1, op - 1);
76
99.7k
    make_array(&stack[0].proc2, 0, 1, op);
77
99.9k
    for (;;) {
78
99.9k
        long i;
79
80
99.9k
        if (r_size(&top->proc1) == 0) {
81
            /* Finished these arrays, go up to next level. */
82
0
            if (top == stack) {
83
                /* We're done matching: it succeeded. */
84
0
                make_true(op - 1);
85
0
                pop(1);
86
0
                return 0;
87
0
            }
88
0
            --top;
89
0
            continue;
90
0
        }
91
        /* Look at the next elements of the arrays. */
92
99.9k
        i = r_size(&top->proc1) - 1;
93
99.9k
        array_get(imemory, &top->proc1, i, &top[1].proc1);
94
99.9k
        array_get(imemory, &top->proc2, i, &top[1].proc2);
95
99.9k
        r_dec_size(&top->proc1, 1);
96
99.9k
        ++top;
97
        /*
98
         * Amazingly enough, the objects' executable attributes are not
99
         * required to match.  This means { x load } will match { /x load },
100
         * even though this is clearly wrong.
101
         */
102
#if 0
103
        if (r_has_attr(&top->proc1, a_executable) !=
104
            r_has_attr(&top->proc2, a_executable)
105
            )
106
            break;
107
#endif
108
99.9k
        if (obj_eq(imemory, &top->proc1, &top->proc2)) {
109
            /* Names don't match strings. */
110
7
            if (r_type(&top->proc1) != r_type(&top->proc2) &&
111
7
                (r_type(&top->proc1) == t_name ||
112
0
                 r_type(&top->proc2) == t_name)
113
7
                )
114
0
                break;
115
7
            --top;    /* no recursion */
116
7
            continue;
117
7
        }
118
99.9k
        if (r_is_array(&top->proc1) && r_is_array(&top->proc2) &&
119
99.9k
            r_size(&top->proc1) == r_size(&top->proc2) &&
120
99.9k
            top < stack + (MAX_DEPTH - 1)
121
99.9k
            ) {
122
            /* Descend into the arrays. */
123
183
            continue;
124
183
        }
125
99.7k
        break;
126
99.9k
    }
127
    /* An exit from the loop indicates that matching failed. */
128
99.7k
    make_false(op - 1);
129
99.7k
    pop(1);
130
99.7k
    return 0;
131
99.7k
}
132
133
/* ------ Initialization procedure ------ */
134
135
const op_def zmisc3_op_defs[] =
136
{
137
    op_def_begin_ll3(),
138
    {"0cliprestore", zcliprestore},
139
    {"0clipsave", zclipsave},
140
    {"2.eqproc", zeqproc},
141
    op_def_end(0)
142
};