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