1 /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zmisc3.c,v 1.6 2004/08/04 19:36:13 stefan Exp $ */
18 /* Miscellaneous LanguageLevel 3 operators */
19 #include "ghost.h"
20 #include "gscspace.h" /* for gscolor2.h */
21 #include "gsmatrix.h" /* ditto */
22 #include "gsclipsr.h"
23 #include "gscolor2.h"
24 #include "oper.h"
25 #include "igstate.h"
26 #include "store.h"
27
28 /* - clipsave - */
29 private int
zclipsave(i_ctx_t * i_ctx_p)30 zclipsave(i_ctx_t *i_ctx_p)
31 {
32 return gs_clipsave(igs);
33 }
34
35 /* - cliprestore - */
36 private int
zcliprestore(i_ctx_t * i_ctx_p)37 zcliprestore(i_ctx_t *i_ctx_p)
38 {
39 return gs_cliprestore(igs);
40 }
41
42 /* <proc1> <proc2> .eqproc <bool> */
43 /*
44 * Test whether two procedures are equal to depth 10.
45 * This is the equality test used by idiom recognition in 'bind'.
46 */
47 #define MAX_DEPTH 10 /* depth is per Adobe specification */
48 typedef struct ref2_s {
49 ref proc1, proc2;
50 } ref2_t;
51 private int
zeqproc(i_ctx_t * i_ctx_p)52 zeqproc(i_ctx_t *i_ctx_p)
53 {
54 os_ptr op = osp;
55 ref2_t stack[MAX_DEPTH + 1];
56 ref2_t *top = stack;
57
58 make_array(&stack[0].proc1, 0, 1, op - 1);
59 make_array(&stack[0].proc2, 0, 1, op);
60 for (;;) {
61 long i;
62
63 if (r_size(&top->proc1) == 0) {
64 /* Finished these arrays, go up to next level. */
65 if (top == stack) {
66 /* We're done matching: it succeeded. */
67 make_true(op - 1);
68 pop(1);
69 return 0;
70 }
71 --top;
72 continue;
73 }
74 /* Look at the next elements of the arrays. */
75 i = r_size(&top->proc1) - 1;
76 array_get(imemory, &top->proc1, i, &top[1].proc1);
77 array_get(imemory, &top->proc2, i, &top[1].proc2);
78 r_dec_size(&top->proc1, 1);
79 ++top;
80 /*
81 * Amazingly enough, the objects' executable attributes are not
82 * required to match. This means { x load } will match { /x load },
83 * even though this is clearly wrong.
84 */
85 #if 0
86 if (r_has_attr(&top->proc1, a_executable) !=
87 r_has_attr(&top->proc2, a_executable)
88 )
89 break;
90 #endif
91 if (obj_eq(imemory, &top->proc1, &top->proc2)) {
92 /* Names don't match strings. */
93 if (r_type(&top->proc1) != r_type(&top->proc2) &&
94 (r_type(&top->proc1) == t_name ||
95 r_type(&top->proc2) == t_name)
96 )
97 break;
98 --top; /* no recursion */
99 continue;
100 }
101 if (r_is_array(&top->proc1) && r_is_array(&top->proc2) &&
102 r_size(&top->proc1) == r_size(&top->proc2) &&
103 top < stack + (MAX_DEPTH - 1)
104 ) {
105 /* Descend into the arrays. */
106 continue;
107 }
108 break;
109 }
110 /* An exit from the loop indicates that matching failed. */
111 make_false(op - 1);
112 pop(1);
113 return 0;
114 }
115
116 /* ------ Initialization procedure ------ */
117
118 const op_def zmisc3_op_defs[] =
119 {
120 op_def_begin_ll3(),
121 {"0cliprestore", zcliprestore},
122 {"0clipsave", zclipsave},
123 {"2.eqproc", zeqproc},
124 op_def_end(0)
125 };
126