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 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 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 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 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 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 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 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