Changeset 909
- Timestamp:
- 06/10/07 13:55:02 (1 year ago)
- Files:
-
- 1.8.3/branches/devel/CHANGES.183 (modified) (2 diffs)
- 1.8.3/branches/devel/game/txt/hlp/pennfunc.hlp (modified) (4 diffs)
- 1.8.3/branches/devel/hdrs/externs.h (modified) (2 diffs)
- 1.8.3/branches/devel/src/bsd.c (modified) (1 diff)
- 1.8.3/branches/devel/src/function.c (modified) (11 diffs)
- 1.8.3/branches/devel/src/funlist.c (modified) (11 diffs)
- 1.8.3/branches/devel/src/funmath.c (modified) (2 diffs)
- 1.8.3/branches/devel/src/funmisc.c (modified) (1 diff)
- 1.8.3/branches/devel/src/htab.c (modified) (2 diffs)
- 1.8.3/branches/devel/src/lock.c (modified) (1 diff)
- 1.8.3/branches/devel/src/utils.c (modified) (2 diffs)
- 1.8.3/branches/devel/src/wild.c (modified) (1 diff)
- 1.8.3/branches/devel/test/testletq.pl (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
1.8.3/branches/devel/CHANGES.183
r900 r909 36 36 time zone the time is displayed for: UTC or the server's. [SW] 37 37 * fn() by Javelin 38 * letq(). Suggested by Nathan Baum. [SW] 38 39 39 40 Fixes: 40 41 * Assorted compiler warning fixes. [SW] 41 * Won't compileon OS X 10.3. Reported by Viila. [SW]42 * Compile fix on OS X 10.3. Reported by Viila. [SW] 42 43 * @sql wasn't enabled if Sqlite3 was the only database turned on. 43 44 Reported by qa'toq. … … 52 53 * User locks were broken in the last patch. Reported by Michael Brazaitis. 53 54 [SW] 55 * ./configure --without-ssl works. Reported by Starr. [SW] 54 56 55 57 Version 1.8.3 patchlevel 2 May 16, 2007 1.8.3/branches/devel/game/txt/hlp/pennfunc.hlp
r892 r909 224 224 clone() create() die() dig() firstof() 225 225 functions() isdbref() isint() isnum() isobjid() 226 isword() l ocalize() link() list() lnum()227 null() numversion() objeval() open() pcreate()228 r-function rand() s-function scan() set()229 set q() setr() soundex() soundslike() speak()230 tel() textentries() textfile() valid() wipe()231 @@()226 isword() letq() localize() link() list() 227 lnum() null() numversion() objeval() open() 228 pcreate() r-function rand() s-function scan() 229 set() setq() setr() soundex() soundslike() 230 speak() tel() textentries() textfile() valid() 231 wipe() @@() 232 232 233 233 & @@() … … 1975 1975 1976 1976 nslemit() is a wizard-only variation that works like @nslemit. 1977 1977 & LETQ() 1978 letq([<reg1>, <value1>,...<regN>, <valueN>], <expr>)) 1979 1980 letq() saves the current values of the given q-registers, sets them 1981 to new values, evaluates <expr> and then restores the saved registers. 1982 It does not restore registers that are not listed. None of the values 1983 can see the updated contents of the registers -- they are only visible 1984 to <expr>. 1985 1986 Example: 1987 1988 > think [setr(A, 1)]:[letq(A, 2, %qA)]:%qA 1989 1:2:1 1990 1991 See also: setq(), setr(), localize(), ulocal() 1978 1992 & LEXITS() 1979 1993 lexits(<object>) … … 2098 2112 You say, "Outside-Inside-Outside" 2099 2113 2100 See also: setq(), setr(), r(), ulocal(), uldefault(), s()2114 See also: letq(), setq(), setr(), r(), ulocal(), uldefault(), s() 2101 2115 & LOCATE() 2102 2116 locate(<looker>, <name>, <parameters>) … … 3472 3486 Object says "bar" 3473 3487 Object says "foo" 3474 3475 3488 & SETUNION() 3476 3489 setunion(<list1>, <list2>[,<delimiter>[, <sort type>[, <osep>]]]) 1.8.3/branches/devel/hdrs/externs.h
r905 r909 547 547 char *errmess; 548 548 } ufun_attrib; 549 externint fetch_ufun_attrib(char *attrname, dbref executor,550 ufun_attrib * ufun, int accept_lambda);551 externint call_ufun(ufun_attrib * ufun, char **wenv_args, int wenv_argc,552 char *ret, dbref executor, dbref enactor,553 PE_Info *pe_info);554 extern int call_attrib(dbref thing, const char *attrname,555 const char *wenv_args[], int wenv_argc, char *ret,556 dbref enactor, PE_Info *pe_info);557 extern int member(dbref thing, dbref list);558 extern int recursive_member(dbref disallow, dbref from, int count);559 extern dbref remove_first(dbref first, dbref what);560 extern dbref reverse(dbref list);561 extern Malloc_t mush_malloc(size_t size,562 const char *check) __attribute_malloc__;563 externvoid mush_free(Malloc_t restrict ptr, const char *restrict check);564 externlong get_random_long(long low, long high);565 externchar *fullalias(dbref it);566 externchar *shortalias(dbref it);567 externchar *shortname(dbref it);568 externdbref absolute_room(dbref it);549 int fetch_ufun_attrib(char *attrname, dbref executor, 550 ufun_attrib * ufun, int accept_lambda); 551 int call_ufun(ufun_attrib * ufun, char **wenv_args, int wenv_argc, 552 char *ret, dbref executor, dbref enactor, PE_Info *pe_info); 553 int call_attrib(dbref thing, const char *attrname, 554 const char *wenv_args[], int wenv_argc, char *ret, 555 dbref enactor, PE_Info *pe_info); 556 int member(dbref thing, dbref list); 557 int recursive_member(dbref disallow, dbref from, int count); 558 dbref remove_first(dbref first, dbref what); 559 dbref reverse(dbref list); 560 void *mush_malloc(size_t bytes, const char *check) __attribute_malloc__; 561 void *mush_calloc(size_t count, size_t size, 562 const char *check) __attribute_malloc__; 563 void mush_free(Malloc_t restrict ptr, const char *restrict check); 564 long get_random_long(long low, long high); 565 char *fullalias(dbref it); 566 char *shortalias(dbref it); 567 char *shortname(dbref it); 568 dbref absolute_room(dbref it); 569 569 int can_interact(dbref from, dbref to, int type); 570 570 … … 621 621 void save_global_regs(const char *funcname, char *preserve[]); 622 622 void restore_global_regs(const char *funcname, char *preserve[]); 623 void save_partial_global_reg(const char *funcname, char 624 *preserve[], int num); 625 void restore_partial_global_regs(const char *funcname, char 626 *preserve[]); 623 627 void free_global_regs(const char *funcname, char *preserve[]); 624 628 void init_global_regs(char *preserve[]); 1.8.3/branches/devel/src/bsd.c
r905 r909 1886 1886 1887 1887 if (!d->raw_input) { 1888 d->raw_input = 1889 (unsigned char *) mush_malloc(sizeof(char) * MAX_COMMAND_LEN, 1890 "descriptor_raw_input"); 1888 d->raw_input = mush_malloc(MAX_COMMAND_LEN, "descriptor_raw_input"); 1891 1889 if (!d->raw_input) 1892 1890 mush_panic("Out of memory"); 1.8.3/branches/devel/src/function.c
r905 r909 44 44 */ 45 45 46 /** Save a single q-register 47 */ 48 void 49 save_partial_global_reg(const char *funcname, char *preserve[], int i) 50 { 51 preserve[i] = mush_strdup(global_eval_context.renv[i], funcname); 52 } 53 54 /** Restore q-registers saved with save_partial_global_reg() 55 */ 56 void 57 restore_partial_global_regs(const char *funcname, char *preserve[]) 58 { 59 int i; 60 for (i = 0; i < NUMQ; i++) { 61 if (preserve[i]) { 62 mush_strncpy(global_eval_context.renv[i], preserve[i], BUFFER_LEN); 63 mush_free(preserve[i], funcname); 64 } 65 } 66 } 67 46 68 /** Save a copy of the q-registers. 47 69 * \param funcname name of function calling (for memory leak testing) … … 56 78 preserve[i] = NULL; 57 79 else { 58 preserve[i] = (char *) mush_malloc(BUFFER_LEN, funcname); 59 strcpy(preserve[i], global_eval_context.renv[i]); 80 preserve[i] = mush_strdup(global_eval_context.renv[i], funcname); 60 81 } 61 82 } … … 72 93 for (i = 0; i < NUMQ; i++) { 73 94 if (preserve[i]) { 74 strcpy(global_eval_context.renv[i], preserve[i]);95 mush_strncpy(global_eval_context.renv[i], preserve[i], BUFFER_LEN); 75 96 mush_free(preserve[i], funcname); 76 97 preserve[i] = NULL; … … 169 190 valr[i] = NULL; 170 191 else { 171 valr[i] = (char *) mush_malloc(BUFFER_LEN, funcname); 172 strcpy(valr[i], global_eval_context.rnxt[i]); 192 valr[i] = mush_strdup(global_eval_context.rnxt[i], funcname); 173 193 } 174 194 } … … 178 198 valw[i] = NULL; 179 199 else { 180 valw[i] = (char *) mush_malloc(BUFFER_LEN, funcname); 181 strcpy(valw[i], global_eval_context.wnxt[i]); 200 valw[i] = mush_strdup(global_eval_context.wnxt[i], funcname); 182 201 } 183 202 } … … 200 219 if (preserver[i]) { 201 220 /* There was a former address, so we can restore to it */ 202 strcpy(global_eval_context.rnxt[i], valr[i]);221 mush_strncpy(global_eval_context.rnxt[i], valr[i], BUFFER_LEN); 203 222 mush_free(valr[i], funcname); 204 223 valr[i] = NULL; … … 209 228 if (preservew[i]) { 210 229 /* There was a former address, so we can restore to it */ 211 strcpy(global_eval_context.wnxt[i], valw[i]);230 mush_strncpy(global_eval_context.wnxt[i], valw[i], BUFFER_LEN); 212 231 mush_free(valw[i], funcname); 213 232 valw[i] = NULL; … … 436 455 {"LEFT", fun_left, 2, 2, FN_REG}, 437 456 {"LEMIT", fun_lemit, 1, -1, FN_REG}, 457 {"LETQ", fun_letq, 1, INT_MAX, FN_NOPARSE}, 438 458 {"LEXITS", fun_dbwalker, 1, 1, FN_REG}, 439 459 {"LFLAGS", fun_lflags, 0, 1, FN_REG}, … … 853 873 function_init_postconfig(void) 854 874 { 855 userfn_tab = 856 (USERFN_ENTRY *) mush_malloc(MAX_GLOBAL_FNS * sizeof(USERFN_ENTRY), 857 "userfn_tab"); 875 userfn_tab = mush_calloc(MAX_GLOBAL_FNS, sizeof(USERFN_ENTRY), "userfn_tab"); 858 876 } 859 877 … … 1187 1205 int n = 0; 1188 1206 1189 funclist = mush_ malloc(sizeof(FUN *) * userfn_count, "function.fp.list");1207 funclist = mush_calloc(userfn_count, sizeof(FUN *), "function.fp.list"); 1190 1208 notify(player, T("Function Name Dbref # Attrib")); 1191 1209 for (fp = (FUN *) hash_firstentry(&htab_user_function); … … 1208 1226 /* just print out the list of available functions */ 1209 1227 safe_str(T("User functions:"), tbuf1, &bp); 1210 funcnames = mush_ malloc(sizeof(char *) * userfn_count, "function.list");1228 funcnames = mush_calloc(userfn_count, sizeof(char *), "function.list"); 1211 1229 for (fp = (FUN *) hash_firstentry(&htab_user_function); 1212 1230 fp; fp = (FUN *) hash_nextentry(&htab_user_function)) { 1.8.3/branches/devel/src/funlist.c
r905 r909 225 225 /* Break up the two lists into their respective elements. */ 226 226 227 ptrs1 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");228 ptrs2 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");227 ptrs1 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 228 ptrs2 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 229 229 230 230 /* ptrs3 is destructively modified, but it's a copy of ptrs2, so we 231 231 * make it a straight copy of ptrs2 and freearr() on ptrs2. */ 232 ptrs3 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");232 ptrs3 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 233 233 234 234 if (!ptrs1 || !ptrs2) … … 263 263 * NULL to handle duplicates 264 264 */ 265 results = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");265 results = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 266 266 if (!results) 267 267 mush_panic("Unable to allocate memory in fun_munge"); … … 316 316 } 317 317 318 ptrs = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");319 wordlist = (char *)mush_malloc(BUFFER_LEN, "string");318 ptrs = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 319 wordlist = mush_malloc(BUFFER_LEN, "string"); 320 320 if (!ptrs || !wordlist) 321 321 mush_panic("Unable to allocate memory in fun_elements"); … … 786 786 return; 787 787 788 a1 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");789 a2 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");788 a1 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 789 a2 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 790 790 if (!a1 || !a2) 791 791 mush_panic("Unable to allocate memory in fun_inter"); … … 916 916 return; 917 917 918 a1 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");919 a2 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");918 a1 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 919 a2 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 920 920 if (!a1 || !a2) 921 921 mush_panic("Unable to allocate memory in fun_setunion"); … … 1054 1054 return; 1055 1055 1056 a1 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");1057 a2 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");1056 a1 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 1057 a2 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 1058 1058 if (!a1 || !a2) 1059 1059 mush_panic("Unable to allocate memory in fun_diff"); … … 1175 1175 return; 1176 1176 1177 a1 = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");1177 a1 = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 1178 1178 1179 1179 if (!a1) … … 1183 1183 n1 = list2arr_ansi(a1, MAX_SORTSIZE, args[0], sep); 1184 1184 1185 a2 = mush_ malloc(n1 *sizeof(char *), "ptrarray");1185 a2 = mush_calloc(n1, sizeof(char *), "ptrarray"); 1186 1186 if (!a2) 1187 1187 mush_panic("Unable to allocate memory in fun_unique"); … … 2061 2061 } 2062 2062 2063 words = (char **) mush_malloc(sizeof(char *) * BUFFER_LEN, "wordlist");2063 words = mush_calloc(BUFFER_LEN, sizeof(char *), "wordlist"); 2064 2064 2065 2065 origcount = count = list2arr_ansi(words, BUFFER_LEN, args[0], sep); 2066 2066 if (count == 0) { 2067 mush_free( (Malloc_t)words, "wordlist");2067 mush_free(words, "wordlist"); 2068 2068 return; 2069 2069 } … … 2075 2075 } 2076 2076 freearr(words, origcount); 2077 mush_free( (Malloc_t)words, "wordlist");2077 mush_free(words, "wordlist"); 2078 2078 } 2079 2079 … … 2106 2106 osep[1] = '\0'; 2107 2107 2108 orig = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");2109 repl = (char **) mush_malloc(MAX_SORTSIZE *sizeof(char *), "ptrarray");2108 orig = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 2109 repl = mush_calloc(MAX_SORTSIZE, sizeof(char *), "ptrarray"); 2110 2110 /* Turn them into lists */ 2111 2111 ocount = list2arr(orig, MAX_SORTSIZE, args[0], sep); 1.8.3/branches/devel/src/funmath.c
r905 r909 1798 1798 1799 1799 /* Allocate memory */ 1800 ptr = (char **) mush_malloc(sizeof(char *) * BUFFER_LEN, "string");1800 ptr = mush_calloc(BUFFER_LEN, sizeof(char *), "string"); 1801 1801 1802 1802 nptr = list2arr(ptr, BUFFER_LEN, args[1], sep); … … 1806 1806 if (!op) { 1807 1807 safe_str(T("#-1 UNKNOWN OPERATION"), buff, bp); 1808 mush_free( (Malloc_t)ptr, "string");1808 mush_free(ptr, "string"); 1809 1809 return; 1810 1810 } 1811 1811 op->func(ptr, nptr, buff, bp); 1812 1812 1813 mush_free( (Malloc_t)ptr, "string");1813 mush_free(ptr, "string"); 1814 1814 } 1815 1815 1.8.3/branches/devel/src/funmisc.c
r905 r909 195 195 } else 196 196 safe_str(T("#-1 REGISTER OUT OF RANGE"), buff, bp); 197 } 198 } 199 200 FUNCTION(fun_letq) 201 { 202 char **values = NULL; 203 int *regs = NULL; 204 int npairs; 205 int n; 206 char tbuf[BUFFER_LEN], *tbp; 207 char *preserve[NUMQ]; 208 const char *p; 209 210 if ((nargs % 2) != 1) { 211 safe_str(T("#-1 FUNCTION (letq) EXPECTS AN ODD NUMBER OF ARGUMENTS"), 212 buff, bp); 213 return; 214 } 215 216 npairs = (nargs - 1) / 2; 217 218 for (n = 0; n < NUMQ; n++) 219 preserve[n] = NULL; 220 221 if (npairs) { 222 values = mush_calloc(npairs, sizeof(char *), "letq.values"); 223 if (!values) { 224 safe_str(T("#-1 UNABLE TO ALLOCATE MEMORY"), buff, bp); 225 return; 226 } 227 228 regs = mush_calloc(npairs, sizeof(int), "letq.registers"); 229 if (!regs) { 230 safe_str(T("#-1 UNABLE TO ALLOCATE MEMORY"), buff, bp); 231 mush_free(values, "letq.values"); 232 return; 233 } 234 235 for (n = 0; n < npairs; n++) { 236 int i = n * 2; 237 238 tbp = tbuf; 239 p = args[i]; 240 process_expression(tbuf, &tbp, &p, executor, caller, enactor, PE_DEFAULT, 241 PT_DEFAULT, pe_info); 242 *tbp = '\0'; 243 regs[n] = qreg_indexes[(unsigned char) tbuf[0]]; 244 if (regs[n] < 0) { 245 safe_str(T("#-1 REGISTER OUT OF RANGE"), buff, bp); 246 goto cleanup; 247 } 248 249 tbp = tbuf; 250 p = args[i + 1]; 251 process_expression(tbuf, &tbp, &p, executor, caller, enactor, PE_DEFAULT, 252 PT_DEFAULT, pe_info); 253 *tbp = '\0'; 254 values[n] = mush_strdup(tbuf, "letq.value"); 255 if (!values[n]) { 256 safe_str(T("#-1 UNABLE TO ALLOCATE MEMORY"), buff, bp); 257 goto cleanup; 258 } 259 } 260 261 for (n = 0; n < npairs; n++) { 262 save_partial_global_reg("letq", preserve, regs[n]); 263 mush_strncpy(global_eval_context.renv[regs[n]], values[n], BUFFER_LEN); 264 } 265 } 266 p = args[nargs - 1]; 267 process_expression(buff, bp, &p, executor, caller, enactor, PE_DEFAULT, 268 PT_DEFAULT, pe_info); 269 270 cleanup: 271 if (regs) 272 mush_free(regs, "letq.regs"); 273 if (values) { 274 restore_partial_global_regs("letq", preserve); 275 for (n = 0; n < npairs; n++) 276 mush_free(values[n], "letq.value"); 277 mush_free(values, "letq.values"); 197 278 } 198 279 } 1.8.3/branches/devel/src/htab.c
r905 r909 163 163 hash_init(HASHTAB *htab, int size, int data_size, void (*free_data) (void *)) 164 164 { 165 int i;166 167 165 htab->mask = get_hashmask(&size); 168 166 htab->hashsize = size; 169 167 htab->entries = 0; 170 htab->buckets = mush_malloc(size * sizeof(HASHENT *), "hash_buckets"); 171 for (i = 0; i < size; i++) 172 htab->buckets[i] = NULL; 173 168 htab->buckets = mush_calloc(size, sizeof(HASHENT *), "hash_buckets"); 174 169 htab->entry_size = data_size; 175 170 htab->free_data = free_data; … … 257 252 htab->hashsize = size; 258 253 newarr = 259 (HASHENT **) mush_ malloc(size *sizeof(struct hashentry *), "hash_buckets");254 (HASHENT **) mush_calloc(size, sizeof(struct hashentry *), "hash_buckets"); 260 255 htab->buckets = newarr; 261 for (i = 0; i < size; i++)262 newarr[i] = NULL;263 256 264 257 for (i = 0; i < osize; i++) { 1.8.3/branches/devel/src/lock.c
r905 r909 306 306 size_t n; 307 307 308 ll = mush_ malloc(sizeof(lock_list) * LOCKS_PER_PAGE, "lock_page");308 ll = mush_calloc(LOCKS_PER_PAGE, sizeof(lock_list), "lock_page"); 309 309 310 310 if (!ll) 1.8.3/branches/devel/src/utils.c
r905 r909 64 64 * \return allocated block of memory or NULL. 65 65 */ 66 Malloc_t 67 mush_malloc(size_t size, const char *check) 68 { 69 Malloc_t ptr; 66 void * 67 mush_malloc(size_t bytes, const char *check) 68 { 69 void *ptr; 70 ptr = malloc(bytes); 71 if (!ptr) 72 do_log(LT_ERR, 0, 0, "mush_malloc failed to malloc %lu bytes for %s", 73 (unsigned long) bytes, check); 70 74 add_check(check); 71 ptr = malloc(size); 72 if (ptr == NULL) 73 do_log(LT_ERR, 0, 0, "mush_malloc failed to malloc %lu bytes for %s", 74 (unsigned long) size, check); 75 return ptr; 76 } 77 78 /** A calloc wrapper that tracks type of allocation. 79 * Use in preference to calloc() when possible to enable 80 * memory leak checking. 81 * \param count number of elements to allocate 82 * \param size size of each element 83 * \param check string to label allocation with 84 * \return allocated zeroed out block or NULL 85 */ 86 void * 87 mush_calloc(size_t count, size_t size, const char *check) 88 { 89 void *ptr; 90 91 ptr = calloc(count, size); 92 if (!ptr) 93 do_rawlog(LT_ERR, "mush_calloc failed to allocate %lu bytes for %s", 94 (unsigned long) (size * count), check); 95 add_check(check); 75 96 return ptr; 76 97 } … … 83 104 */ 84 105 void 85 mush_free(Malloc_t RESTRICT ptr, const char *RESTRICT check 86 __attribute__ ((__unused__))) 106 mush_free(void *RESTRICT ptr, const char *RESTRICT check) 87 107 { 88 108 del_check(check); 1.8.3/branches/devel/src/wild.c
r905 r909 560 560 */ 561 561 562 for (i = 0; i < nmatches && i < subpatterns && len > 1; i++) {562 for (i = 0; i < nmatches && (int) i < subpatterns && (size_t) len > i; i++) { 563 563 ssize_t sublen; 564 564 const char *submatch;
