1 /* Copyright (C) 1989, 1995, 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: zstring.c,v 1.6 2004/08/04 19:36:13 stefan Exp $ */
18 /* String operators */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "gsutil.h"
22 #include "ialloc.h"
23 #include "iname.h"
24 #include "ivmspace.h"
25 #include "oper.h"
26 #include "store.h"
27
28 /* The generic operators (copy, get, put, getinterval, putinterval, */
29 /* length, and forall) are implemented in zgeneric.c. */
30
31 /* <int> .bytestring <bytestring> */
32 private int
zbytestring(i_ctx_t * i_ctx_p)33 zbytestring(i_ctx_t *i_ctx_p)
34 {
35 os_ptr op = osp;
36 byte *sbody;
37 uint size;
38
39 check_int_leu(*op, max_int);
40 size = (uint)op->value.intval;
41 sbody = ialloc_bytes(size, ".bytestring");
42 if (sbody == 0)
43 return_error(e_VMerror);
44 make_astruct(op, a_all | icurrent_space, sbody);
45 memset(sbody, 0, size);
46 return 0;
47 }
48
49 /* <int> string <string> */
50 int
zstring(i_ctx_t * i_ctx_p)51 zstring(i_ctx_t *i_ctx_p)
52 {
53 os_ptr op = osp;
54 byte *sbody;
55 uint size;
56
57 check_int_leu(*op, max_string_size);
58 size = op->value.intval;
59 sbody = ialloc_string(size, "string");
60 if (sbody == 0)
61 return_error(e_VMerror);
62 make_string(op, a_all | icurrent_space, size, sbody);
63 memset(sbody, 0, size);
64 return 0;
65 }
66
67 /* <name> .namestring <string> */
68 private int
znamestring(i_ctx_t * i_ctx_p)69 znamestring(i_ctx_t *i_ctx_p)
70 {
71 os_ptr op = osp;
72
73 check_type(*op, t_name);
74 name_string_ref(imemory, op, op);
75 return 0;
76 }
77
78 /* <string> <pattern> anchorsearch <post> <match> -true- */
79 /* <string> <pattern> anchorsearch <string> -false- */
80 private int
zanchorsearch(i_ctx_t * i_ctx_p)81 zanchorsearch(i_ctx_t *i_ctx_p)
82 {
83 os_ptr op = osp;
84 os_ptr op1 = op - 1;
85 uint size = r_size(op);
86
87 check_read_type(*op1, t_string);
88 check_read_type(*op, t_string);
89 if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) {
90 os_ptr op0 = op;
91
92 push(1);
93 *op0 = *op1;
94 r_set_size(op0, size);
95 op1->value.bytes += size;
96 r_dec_size(op1, size);
97 make_true(op);
98 } else
99 make_false(op);
100 return 0;
101 }
102
103 /* <string> <pattern> search <post> <match> <pre> -true- */
104 /* <string> <pattern> search <string> -false- */
105 private int
zsearch(i_ctx_t * i_ctx_p)106 zsearch(i_ctx_t *i_ctx_p)
107 {
108 os_ptr op = osp;
109 os_ptr op1 = op - 1;
110 uint size = r_size(op);
111 uint count;
112 byte *pat;
113 byte *ptr;
114 byte ch;
115
116 check_read_type(*op1, t_string);
117 check_read_type(*op, t_string);
118 if (size > r_size(op1)) { /* can't match */
119 make_false(op);
120 return 0;
121 }
122 count = r_size(op1) - size;
123 ptr = op1->value.bytes;
124 if (size == 0)
125 goto found;
126 pat = op->value.bytes;
127 ch = pat[0];
128 do {
129 if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
130 goto found;
131 ptr++;
132 }
133 while (count--);
134 /* No match */
135 make_false(op);
136 return 0;
137 found:
138 op->tas.type_attrs = op1->tas.type_attrs;
139 op->value.bytes = ptr;
140 r_set_size(op, size);
141 push(2);
142 op[-1] = *op1;
143 r_set_size(op - 1, ptr - op[-1].value.bytes);
144 op1->value.bytes = ptr + size;
145 r_set_size(op1, count);
146 make_true(op);
147 return 0;
148 }
149
150 /* <string> <charstring> .stringbreak <int|null> */
151 private int
zstringbreak(i_ctx_t * i_ctx_p)152 zstringbreak(i_ctx_t *i_ctx_p)
153 {
154 os_ptr op = osp;
155 uint i, j;
156
157 check_read_type(op[-1], t_string);
158 check_read_type(*op, t_string);
159 /* We can't use strpbrk here, because C doesn't allow nulls in strings. */
160 for (i = 0; i < r_size(op - 1); ++i)
161 for (j = 0; j < r_size(op); ++j)
162 if (op[-1].value.const_bytes[i] == op->value.const_bytes[j]) {
163 make_int(op - 1, i);
164 goto done;
165 }
166 make_null(op - 1);
167 done:
168 pop(1);
169 return 0;
170 }
171
172 /* <obj> <pattern> .stringmatch <bool> */
173 private int
zstringmatch(i_ctx_t * i_ctx_p)174 zstringmatch(i_ctx_t *i_ctx_p)
175 {
176 os_ptr op = osp;
177 os_ptr op1 = op - 1;
178 bool result;
179
180 check_read_type(*op, t_string);
181 switch (r_type(op1)) {
182 case t_string:
183 check_read(*op1);
184 goto cmp;
185 case t_name:
186 name_string_ref(imemory, op1, op1); /* can't fail */
187 cmp:
188 result = string_match(op1->value.const_bytes, r_size(op1),
189 op->value.const_bytes, r_size(op),
190 NULL);
191 break;
192 default:
193 result = (r_size(op) == 1 && *op->value.bytes == '*');
194 }
195 make_bool(op1, result);
196 pop(1);
197 return 0;
198 }
199
200 /* ------ Initialization procedure ------ */
201
202 const op_def zstring_op_defs[] =
203 {
204 {"1.bytestring", zbytestring},
205 {"2anchorsearch", zanchorsearch},
206 {"1.namestring", znamestring},
207 {"2search", zsearch},
208 {"1string", zstring},
209 {"2.stringbreak", zstringbreak},
210 {"2.stringmatch", zstringmatch},
211 op_def_end(0)
212 };
213