Coverage Report

Created: 2025-06-10 07:06

/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
0
{
31
0
    return gs_clipsave(igs);
32
0
}
33
34
/* - cliprestore - */
35
static int
36
zcliprestore(i_ctx_t *i_ctx_p)
37
1
{
38
1
    return gs_cliprestore(igs);
39
1
}
40
41
static inline bool
42
eqproc_check_type(ref *r)
43
100
{
44
100
    return r_has_type(r, t_array)
45
100
           || r_has_type(r, t_mixedarray)
46
100
           || r_has_type(r, t_shortarray)
47
100
           || r_has_type(r, t_oparray);
48
100
}
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
2
#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
50
{
64
50
    os_ptr op = osp;
65
50
    ref2_t stack[MAX_DEPTH + 1];
66
50
    ref2_t *top = stack;
67
68
50
    check_op(2);
69
50
    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
50
    make_array(&stack[0].proc1, 0, 1, op - 1);
76
50
    make_array(&stack[0].proc2, 0, 1, op);
77
52
    for (;;) {
78
52
        long i;
79
80
52
        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
52
        i = r_size(&top->proc1) - 1;
93
52
        array_get(imemory, &top->proc1, i, &top[1].proc1);
94
52
        array_get(imemory, &top->proc2, i, &top[1].proc2);
95
52
        r_dec_size(&top->proc1, 1);
96
52
        ++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
52
        if (obj_eq(imemory, &top->proc1, &top->proc2)) {
109
            /* Names don't match strings. */
110
0
            if (r_type(&top->proc1) != r_type(&top->proc2) &&
111
0
                (r_type(&top->proc1) == t_name ||
112
0
                 r_type(&top->proc2) == t_name)
113
0
                )
114
0
                break;
115
0
            --top;    /* no recursion */
116
0
            continue;
117
0
        }
118
52
        if (r_is_array(&top->proc1) && r_is_array(&top->proc2) &&
119
52
            r_size(&top->proc1) == r_size(&top->proc2) &&
120
52
            top < stack + (MAX_DEPTH - 1)
121
52
            ) {
122
            /* Descend into the arrays. */
123
2
            continue;
124
2
        }
125
50
        break;
126
52
    }
127
    /* An exit from the loop indicates that matching failed. */
128
50
    make_false(op - 1);
129
50
    pop(1);
130
50
    return 0;
131
50
}
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
};