xref: /plan9/sys/src/cmd/gs/src/zmisc3.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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