xref: /plan9-contrib/sys/src/cmd/gs/src/zstring.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
1 /* Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This file is part of AFPL Ghostscript.
4 
5   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
6   distributor accepts any responsibility for the consequences of using it, or
7   for whether it serves any particular purpose or works at all, unless he or
8   she says so in writing.  Refer to the Aladdin Free Public License (the
9   "License") for full details.
10 
11   Every copy of AFPL Ghostscript must include a copy of the License, normally
12   in a plain ASCII text file named PUBLIC.  The License grants you the right
13   to copy, modify and redistribute AFPL Ghostscript, but only under certain
14   conditions described in the License.  Among other things, the License
15   requires that the copyright notice and this notice be preserved on all
16   copies.
17 */
18 
19 /*$Id: zstring.c,v 1.2 2000/09/19 19:00:55 lpd Exp $ */
20 /* String operators */
21 #include "memory_.h"
22 #include "ghost.h"
23 #include "gsutil.h"
24 #include "ialloc.h"
25 #include "iname.h"
26 #include "ivmspace.h"
27 #include "oper.h"
28 #include "store.h"
29 
30 /* The generic operators (copy, get, put, getinterval, putinterval, */
31 /* length, and forall) are implemented in zgeneric.c. */
32 
33 /* <int> .bytestring <bytestring> */
34 private int
35 zbytestring(i_ctx_t *i_ctx_p)
36 {
37     os_ptr op = osp;
38     byte *sbody;
39     uint size;
40 
41     check_int_leu(*op, max_int);
42     size = (uint)op->value.intval;
43     sbody = ialloc_bytes(size, ".bytestring");
44     if (sbody == 0)
45 	return_error(e_VMerror);
46     make_astruct(op, a_all | icurrent_space, sbody);
47     memset(sbody, 0, size);
48     return 0;
49 }
50 
51 /* <int> string <string> */
52 int
53 zstring(i_ctx_t *i_ctx_p)
54 {
55     os_ptr op = osp;
56     byte *sbody;
57     uint size;
58 
59     check_int_leu(*op, max_string_size);
60     size = op->value.intval;
61     sbody = ialloc_string(size, "string");
62     if (sbody == 0)
63 	return_error(e_VMerror);
64     make_string(op, a_all | icurrent_space, size, sbody);
65     memset(sbody, 0, size);
66     return 0;
67 }
68 
69 /* <name> .namestring <string> */
70 private int
71 znamestring(i_ctx_t *i_ctx_p)
72 {
73     os_ptr op = osp;
74 
75     check_type(*op, t_name);
76     name_string_ref(op, op);
77     return 0;
78 }
79 
80 /* <string> <pattern> anchorsearch <post> <match> -true- */
81 /* <string> <pattern> anchorsearch <string> -false- */
82 private int
83 zanchorsearch(i_ctx_t *i_ctx_p)
84 {
85     os_ptr op = osp;
86     os_ptr op1 = op - 1;
87     uint size = r_size(op);
88 
89     check_read_type(*op1, t_string);
90     check_read_type(*op, t_string);
91     if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) {
92 	os_ptr op0 = op;
93 
94 	push(1);
95 	*op0 = *op1;
96 	r_set_size(op0, size);
97 	op1->value.bytes += size;
98 	r_dec_size(op1, size);
99 	make_true(op);
100     } else
101 	make_false(op);
102     return 0;
103 }
104 
105 /* <string> <pattern> search <post> <match> <pre> -true- */
106 /* <string> <pattern> search <string> -false- */
107 private int
108 zsearch(i_ctx_t *i_ctx_p)
109 {
110     os_ptr op = osp;
111     os_ptr op1 = op - 1;
112     uint size = r_size(op);
113     uint count;
114     byte *pat;
115     byte *ptr;
116     byte ch;
117 
118     check_read_type(*op1, t_string);
119     check_read_type(*op, t_string);
120     if (size > r_size(op1)) {	/* can't match */
121 	make_false(op);
122 	return 0;
123     }
124     count = r_size(op1) - size;
125     ptr = op1->value.bytes;
126     if (size == 0)
127 	goto found;
128     pat = op->value.bytes;
129     ch = pat[0];
130     do {
131 	if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
132 	    goto found;
133 	ptr++;
134     }
135     while (count--);
136     /* No match */
137     make_false(op);
138     return 0;
139 found:
140     op->tas.type_attrs = op1->tas.type_attrs;
141     op->value.bytes = ptr;
142     r_set_size(op, size);
143     push(2);
144     op[-1] = *op1;
145     r_set_size(op - 1, ptr - op[-1].value.bytes);
146     op1->value.bytes = ptr + size;
147     r_set_size(op1, count);
148     make_true(op);
149     return 0;
150 }
151 
152 /* <obj> <pattern> .stringmatch <bool> */
153 private int
154 zstringmatch(i_ctx_t *i_ctx_p)
155 {
156     os_ptr op = osp;
157     os_ptr op1 = op - 1;
158     bool result;
159 
160     check_read_type(*op, t_string);
161     switch (r_type(op1)) {
162 	case t_string:
163 	    check_read(*op1);
164 	    goto cmp;
165 	case t_name:
166 	    name_string_ref(op1, op1);	/* can't fail */
167 cmp:
168 	    result = string_match(op1->value.const_bytes, r_size(op1),
169 				  op->value.const_bytes, r_size(op),
170 				  NULL);
171 	    break;
172 	default:
173 	    result = (r_size(op) == 1 && *op->value.bytes == '*');
174     }
175     make_bool(op1, result);
176     pop(1);
177     return 0;
178 }
179 
180 /* ------ Initialization procedure ------ */
181 
182 const op_def zstring_op_defs[] =
183 {
184     {"1.bytestring", zbytestring},
185     {"2anchorsearch", zanchorsearch},
186     {"1.namestring", znamestring},
187     {"2search", zsearch},
188     {"1string", zstring},
189     {"2.stringmatch", zstringmatch},
190     op_def_end(0)
191 };
192