static zend_string *browscap_intern_str_ci( browscap_parser_ctx *ctx, zend_string *str, zend_bool persistent) { zend_string *lcname; zend_string *interned; ALLOCA_FLAG(use_heap); ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(str), use_heap); zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(str), ZSTR_LEN(str)); interned = zend_hash_find_ptr(&ctx->str_interned, lcname); if (interned) { zend_string_addref(interned); } else { interned = zend_string_dup(lcname, persistent); zend_hash_add_new_ptr(&ctx->str_interned, interned, interned); } ZSTR_ALLOCA_FREE(lcname, use_heap); return interned; }
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len) { zend_constant *c; ALLOCA_FLAG(use_heap) if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) { char *lcname = do_alloca(name_len + 1, use_heap); zend_str_tolower_copy(lcname, name, name_len); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) { if (c->flags & CONST_CS) { c = NULL; } } else { c = zend_get_special_constant(name, name_len); } free_alloca(lcname, use_heap); } return c ? &c->value : NULL; }
static zend_class_entry * spl_find_ce_by_name(zend_string *name, zend_bool autoload) { zend_class_entry *ce; if (!autoload) { zend_string *lc_name = zend_string_alloc(name->len, 0); zend_str_tolower_copy(lc_name->val, name->val, name->len); ce = zend_hash_find_ptr(EG(class_table), lc_name); zend_string_free(lc_name); } else { ce = zend_lookup_class(name); } if (ce == NULL) { php_error_docref(NULL, E_WARNING, "Class %s does not exist%s", name->val, autoload ? " and could not be loaded" : ""); return NULL; } return ce; }
static inline zend_constant *zend_get_constant_str_impl(const char *name, size_t name_len) { zend_constant *c; ALLOCA_FLAG(use_heap) if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) { char *lcname = do_alloca(name_len + 1, use_heap); zend_str_tolower_copy(lcname, name, name_len); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) { if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) { c = NULL; } } else { c = zend_get_special_constant(name, name_len); } free_alloca(lcname, use_heap); } return c; }
ZEND_API zval *zend_get_constant(zend_string *name) { zend_constant *c; ALLOCA_FLAG(use_heap) if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) { char *lcname = do_alloca(ZSTR_LEN(name) + 1, use_heap); zend_str_tolower_copy(lcname, ZSTR_VAL(name), ZSTR_LEN(name)); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, ZSTR_LEN(name))) != NULL) { if (c->flags & CONST_CS) { c = NULL; } } else { c = zend_get_special_constant(ZSTR_VAL(name), ZSTR_LEN(name)); } free_alloca(lcname, use_heap); } return c ? &c->value : NULL; }
/* {{{ pthreads_get_method will attempt to apply pthreads specific modifiers */ zend_function * pthreads_get_method(PTHREADS_GET_METHOD_PASSTHRU_D) { zend_class_entry *scope; zend_function *call; zend_function *callable; char *lcname; int access = 0; PTHREAD thread = PTHREADS_FETCH_FROM(*pobject); if (thread) { switch((access=pthreads_modifiers_get(thread->modifiers, method TSRMLS_CC))){ case ZEND_ACC_PRIVATE: case ZEND_ACC_PROTECTED: scope = Z_OBJCE_PP(pobject); lcname = (char*) calloc(1, methodl+1); zend_str_tolower_copy(lcname, method, methodl); if (zend_hash_find(&scope->function_table, lcname, methodl+1, (void**)&call)==SUCCESS) { callable = (zend_function*) emalloc(sizeof(zend_function)); callable->type = ZEND_OVERLOADED_FUNCTION; callable->common.function_name = call->common.function_name; callable->common.fn_flags = ZEND_ACC_PUBLIC; callable->common.scope = scope; callable->common.arg_info = call->common.arg_info; callable->common.num_args = call->common.num_args; callable->common.required_num_args = call->common.required_num_args; #if PHP_VERSION_ID < 50400 callable->common.pass_rest_by_reference = call->common.pass_rest_by_reference; callable->common.return_reference = call->common.return_reference; #endif free(lcname); return callable; } free(lcname); /* TODO : if not found ? switch to default ? or return some error ? */ default: call = zend_handlers->get_method(PTHREADS_GET_METHOD_PASSTHRU_C); } } else call = zend_handlers->get_method(PTHREADS_GET_METHOD_PASSTHRU_C); return call; } /* }}} */
static inline int unserialize_allowed_class( zend_string *class_name, php_unserialize_data_t *var_hashx) { HashTable *classes = (*var_hashx)->allowed_classes; zend_string *lcname; int res; ALLOCA_FLAG(use_heap) if(classes == NULL) { return 1; } if(!zend_hash_num_elements(classes)) { return 0; } ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap); zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name)); res = zend_hash_exists(classes, lcname); ZSTR_ALLOCA_FREE(lcname, use_heap); return res; }
static zend_class_entry * spl_find_ce_by_name(char *name, int len, zend_bool autoload TSRMLS_DC) { zend_class_entry **ce; int found; if (!autoload) { char *lc_name; lc_name = do_alloca(len + 1); zend_str_tolower_copy(lc_name, name, len); found = zend_hash_find(EG(class_table), lc_name, len +1, (void **) &ce); free_alloca(lc_name); } else { found = zend_lookup_class(name, len, &ce TSRMLS_CC); } if (found != SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s does not exist%s", name, autoload ? " and could not be loaded" : ""); return NULL; } return *ce; }
/** * Check whether a class with a certain name exists * @param classname * @param len * @param autoload * @return bool */ bool class_exists(const char *classname, size_t len, bool autoload) { // we need the tsrm_ls variable TSRMLS_FETCH(); // we're going to load a class-entry zend_class_entry **ce; // should we autoload the class? if (autoload) { // no auto-load if (SUCCESS != zend_lookup_class(classname, len, &ce TSRMLS_CC)) return false; // the found "class" could also be an interface or trait, which we do no want return ((*ce)->ce_flags & (ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT - ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) == 0; } else { // starting slashes can be ignored if (len > 0 && classname[0] == '\\') { classname++; len--; } // all classes are in lowercase in the hash, so we make // a temporary buffer for storing the lowercase class name // (is this smart? memory allocation is expensive!) std::unique_ptr<char[]> lc_name(new char[len + 1]); // copy the name to lowercase, but ignore the starting slash (if there is one) zend_str_tolower_copy(lc_name.get(), classname, len); // see if there is a class with this name if (SUCCESS != zend_hash_find(EG(class_table), lc_name.get(), len + 1, (void **) &ce)) return false; // the found "class" could also be an interface or trait, which we do no want return !(((*ce)->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); } }
PDO_API char *php_pdo_str_tolower_dup(const char *src, int len) /* {{{ */ { char *dest = emalloc(len + 1); zend_str_tolower_copy(dest, src, len); return dest; }
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_ulong flags) { zend_constant *c; const char *colon; zend_class_entry *ce = NULL; zend_string *class_name; const char *name = cname->val; size_t name_len = cname->len; /* Skip leading \\ */ if (name[0] == '\\') { name += 1; name_len -= 1; cname = NULL; } if ((colon = zend_memrchr(name, ':', name_len)) && colon > name && (*(colon - 1) == ':')) { int class_name_len = colon - name - 1; size_t const_name_len = name_len - class_name_len - 2; zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0); char *lcname; zval *ret_constant = NULL; ALLOCA_FLAG(use_heap) class_name = zend_string_init(name, class_name_len, 0); lcname = do_alloca(class_name_len + 1, use_heap); zend_str_tolower_copy(lcname, name, class_name_len); if (!scope) { if (EG(current_execute_data)) { scope = EG(scope); } else { scope = CG(active_class_entry); } } if (class_name_len == sizeof("self")-1 && !memcmp(lcname, "self", sizeof("self")-1)) { if (UNEXPECTED(!scope)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access self:: when no class scope is active"); return NULL; } ce = scope; } else if (class_name_len == sizeof("parent")-1 && !memcmp(lcname, "parent", sizeof("parent")-1)) { if (UNEXPECTED(!scope)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access parent:: when no class scope is active"); return NULL; } else if (UNEXPECTED(!scope->parent)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access parent:: when current class scope has no parent"); return NULL; } else { ce = scope->parent; } } else if (class_name_len == sizeof("static")-1 && !memcmp(lcname, "static", sizeof("static")-1)) { ce = zend_get_called_scope(EG(current_execute_data)); if (UNEXPECTED(!ce)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access static:: when no class scope is active"); return NULL; } } else { ce = zend_fetch_class(class_name, flags); } free_alloca(lcname, use_heap); if (ce) { ret_constant = zend_hash_find(&ce->constants_table, constant_name); if (ret_constant == NULL) { if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val); zend_string_release(class_name); zend_string_free(constant_name); return NULL; } } else if (Z_ISREF_P(ret_constant)) { ret_constant = Z_REFVAL_P(ret_constant); } } zend_string_release(class_name); zend_string_free(constant_name); if (ret_constant && Z_CONSTANT_P(ret_constant)) { if (UNEXPECTED(zval_update_constant_ex(ret_constant, 1, ce) != SUCCESS)) { return NULL; } } return ret_constant; } /* non-class constant */ if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) { /* compound constant name */ int prefix_len = colon - name; size_t const_name_len = name_len - prefix_len - 1; const char *constant_name = colon + 1; char *lcname; size_t lcname_len; ALLOCA_FLAG(use_heap) lcname_len = prefix_len + 1 + const_name_len; lcname = do_alloca(lcname_len + 1, use_heap); zend_str_tolower_copy(lcname, name, prefix_len); /* Check for namespace constant */ lcname[prefix_len] = '\\'; memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) { /* try lowercase */ zend_str_tolower(lcname + prefix_len + 1, const_name_len); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) { if ((c->flags & CONST_CS) != 0) { c = NULL; } } } free_alloca(lcname, use_heap); if (c) { return &c->value; } /* name requires runtime resolution, need to check non-namespaced name */ if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) { return zend_get_constant_str(constant_name, const_name_len); } return NULL; } if (cname) { return zend_get_constant(cname); } else { return zend_get_constant_str(name, name_len); } }
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags) { zend_constant *c; const char *colon; zend_class_entry *ce = NULL; const char *name = ZSTR_VAL(cname); size_t name_len = ZSTR_LEN(cname); /* Skip leading \\ */ if (name[0] == '\\') { name += 1; name_len -= 1; cname = NULL; } if ((colon = zend_memrchr(name, ':', name_len)) && colon > name && (*(colon - 1) == ':')) { int class_name_len = colon - name - 1; size_t const_name_len = name_len - class_name_len - 2; zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0); zend_string *class_name = zend_string_init(name, class_name_len, 0); zval *ret_constant = NULL; if (zend_string_equals_literal_ci(class_name, "self")) { if (UNEXPECTED(!scope)) { zend_throw_error(NULL, "Cannot access self:: when no class scope is active"); goto failure; } ce = scope; } else if (zend_string_equals_literal_ci(class_name, "parent")) { if (UNEXPECTED(!scope)) { zend_throw_error(NULL, "Cannot access parent:: when no class scope is active"); goto failure; } else if (UNEXPECTED(!scope->parent)) { zend_throw_error(NULL, "Cannot access parent:: when current class scope has no parent"); goto failure; } else { ce = scope->parent; } } else if (zend_string_equals_literal_ci(class_name, "static")) { ce = zend_get_called_scope(EG(current_execute_data)); if (UNEXPECTED(!ce)) { zend_throw_error(NULL, "Cannot access static:: when no class scope is active"); goto failure; } } else { ce = zend_fetch_class(class_name, flags); } if (ce) { zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, constant_name); if (c == NULL) { if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { zend_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); goto failure; } ret_constant = NULL; } else { if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); goto failure; } ret_constant = &c->value; } } if (ret_constant && Z_CONSTANT_P(ret_constant)) { if (Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) { if (IS_CONSTANT_VISITED(ret_constant)) { zend_throw_error(NULL, "Cannot declare self-referencing constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); ret_constant = NULL; goto failure; } MARK_CONSTANT_VISITED(ret_constant); } if (UNEXPECTED(zval_update_constant_ex(ret_constant, ce) != SUCCESS)) { RESET_CONSTANT_VISITED(ret_constant); ret_constant = NULL; goto failure; } RESET_CONSTANT_VISITED(ret_constant); } failure: zend_string_release(class_name); zend_string_free(constant_name); return ret_constant; } /* non-class constant */ if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) { /* compound constant name */ int prefix_len = colon - name; size_t const_name_len = name_len - prefix_len - 1; const char *constant_name = colon + 1; char *lcname; size_t lcname_len; ALLOCA_FLAG(use_heap) lcname_len = prefix_len + 1 + const_name_len; lcname = do_alloca(lcname_len + 1, use_heap); zend_str_tolower_copy(lcname, name, prefix_len); /* Check for namespace constant */ lcname[prefix_len] = '\\'; memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) { /* try lowercase */ zend_str_tolower(lcname + prefix_len + 1, const_name_len); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) { if ((c->flags & CONST_CS) != 0) { c = NULL; } } } free_alloca(lcname, use_heap); if (c) { return &c->value; } /* name requires runtime resolution, need to check non-namespaced name */ if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) { return zend_get_constant_str(constant_name, const_name_len); } return NULL; } if (cname) { return zend_get_constant(cname); } else { return zend_get_constant_str(name, name_len); } }
/* {{{ pthreads_call_method */ int pthreads_call_method(PTHREADS_CALL_METHOD_PASSTHRU_D) { zval ***argv = NULL, zmethod, *zresult; zend_function *call = NULL; zend_fcall_info info; zend_fcall_info_cache cache; zend_class_entry *scope; int called = -1, argc = ZEND_NUM_ARGS(), access = ZEND_ACC_PUBLIC, mlength = 0; char *lcname; zend_bool unprotect; if (getThis()) { PTHREAD thread = PTHREADS_FETCH; if (thread) { switch((access=pthreads_modifiers_get(thread->modifiers, method TSRMLS_CC))){ case ZEND_ACC_PRIVATE: case ZEND_ACC_PROTECTED: { scope = Z_OBJCE_P(getThis()); /* * Stop invalid private method calls */ if (access == ZEND_ACC_PRIVATE && !PTHREADS_IN_THREAD(thread)) { zend_error_noreturn( E_ERROR, "pthreads detected an attempt to call private method %s::%s from outside the threading context", scope->name, method ); return FAILURE; } /* * Get arguments from stack */ if (ZEND_NUM_ARGS()) { argv = safe_emalloc(sizeof(zval **), argc, 0); if (argv) { zend_get_parameters_array_ex(argc, argv); } } mlength = strlen(method); lcname = calloc(1, mlength+1); zend_str_tolower_copy(lcname, method, mlength); if (zend_hash_find(&scope->function_table, lcname, mlength+1, (void**)&call)==SUCCESS) { if (call) { /* * Make protected method call */ { if (access != ZEND_ACC_PROTECTED || pthreads_modifiers_protect(thread->modifiers, method, &unprotect TSRMLS_CC)) { ZVAL_STRINGL(&zmethod, method, strlen(method), 0); info.size = sizeof(info); info.object_ptr = getThis(); info.function_name = &zmethod; info.retval_ptr_ptr = &zresult; info.no_separation = 1; info.symbol_table = NULL; info.param_count = argc; info.params = argv; cache.initialized = 1; cache.function_handler = call; cache.calling_scope = EG(called_scope); cache.called_scope = scope; cache.object_ptr = getThis(); if ((called=zend_call_function(&info, &cache TSRMLS_CC))!=SUCCESS) { zend_error_noreturn( E_ERROR, "pthreads has experienced an internal error while calling %s method %s::%s and cannot continue", (access == ZEND_ACC_PROTECTED) ? "protected" : "private", scope->name, method ); } else { #if PHP_VERSION_ID > 50399 { zend_op_array *ops = (zend_op_array*) call; if (ops) { if (ops->run_time_cache) { efree(ops->run_time_cache); ops->run_time_cache = NULL; } } } #endif if (!return_value_used) { zval_ptr_dtor(&zresult); } else { ZVAL_ZVAL(return_value, zresult, 1, 1); } } if (access == ZEND_ACC_PROTECTED) { pthreads_modifiers_unprotect(thread->modifiers, method, unprotect TSRMLS_CC); } } else { zend_error_noreturn( E_ERROR, "pthreads has experienced an internal error while calling %s method %s::%s and cannot continue", (access == ZEND_ACC_PROTECTED) ? "protected" : "private", scope->name, method ); called = FAILURE; } } } else { zend_error_noreturn( E_ERROR, "pthreads has experienced an internal error while finding %s method %s::%s and cannot continue", (access == ZEND_ACC_PROTECTED) ? "protected" : "private", scope->name, method ); called = FAILURE; } } /* * Free unstacked arguments */ if (argc) { efree(argv); } free(lcname); return called; } break; } } } switch (called) { case -1: return zend_handlers->call_method(PTHREADS_CALL_METHOD_PASSTHRU_C); default: return called; } } /* }}} */
static int browser_reg_compare( zval *entry_zv, int num_args, va_list args, zend_hash_key *key) /* {{{ */ { browscap_entry *entry = Z_PTR_P(entry_zv); zend_string *agent_name = va_arg(args, zend_string *); browscap_entry **found_entry_ptr = va_arg(args, browscap_entry **); browscap_entry *found_entry = *found_entry_ptr; ALLOCA_FLAG(use_heap); zend_string *pattern_lc, *regex; const char *cur; int i; pcre *re; int re_options; pcre_extra *re_extra; /* Agent name too short */ if (ZSTR_LEN(agent_name) < browscap_get_minimum_length(entry)) { return 0; } /* Quickly discard patterns where the prefix doesn't match. */ if (zend_binary_strcasecmp( ZSTR_VAL(agent_name), entry->prefix_len, ZSTR_VAL(entry->pattern), entry->prefix_len) != 0) { return 0; } /* Lowercase the pattern, the agent name is already lowercase */ ZSTR_ALLOCA_ALLOC(pattern_lc, ZSTR_LEN(entry->pattern), use_heap); zend_str_tolower_copy(ZSTR_VAL(pattern_lc), ZSTR_VAL(entry->pattern), ZSTR_LEN(entry->pattern)); /* Check if the agent contains the "contains" portions */ cur = ZSTR_VAL(agent_name) + entry->prefix_len; for (i = 0; i < BROWSCAP_NUM_CONTAINS; i++) { if (entry->contains_len[i] != 0) { cur = zend_memnstr(cur, ZSTR_VAL(pattern_lc) + entry->contains_start[i], entry->contains_len[i], ZSTR_VAL(agent_name) + ZSTR_LEN(agent_name)); if (!cur) { ZSTR_ALLOCA_FREE(pattern_lc, use_heap); return 0; } cur += entry->contains_len[i]; } } /* See if we have an exact match, if so, we're done... */ if (zend_string_equals(agent_name, pattern_lc)) { *found_entry_ptr = entry; ZSTR_ALLOCA_FREE(pattern_lc, use_heap); return ZEND_HASH_APPLY_STOP; } regex = browscap_convert_pattern(entry->pattern, 0); re = pcre_get_compiled_regex(regex, &re_extra, &re_options); if (re == NULL) { ZSTR_ALLOCA_FREE(pattern_lc, use_heap); zend_string_release(regex); return 0; } if (pcre_exec(re, re_extra, ZSTR_VAL(agent_name), ZSTR_LEN(agent_name), 0, re_options, NULL, 0) == 0) { /* If we've found a possible browser, we need to do a comparison of the number of characters changed in the user agent being checked versus the previous match found and the current match. */ if (found_entry) { size_t i, prev_len = 0, curr_len = 0; zend_string *previous_match = found_entry->pattern; zend_string *current_match = entry->pattern; for (i = 0; i < ZSTR_LEN(previous_match); i++) { switch (ZSTR_VAL(previous_match)[i]) { case '?': case '*': /* do nothing, ignore these characters in the count */ break; default: ++prev_len; } } for (i = 0; i < ZSTR_LEN(current_match); i++) { switch (ZSTR_VAL(current_match)[i]) { case '?': case '*': /* do nothing, ignore these characters in the count */ break; default: ++curr_len; } } /* Pick which browser pattern replaces the least amount of characters when compared to the original user agent string... */ if (prev_len < curr_len) { *found_entry_ptr = entry; } } else { *found_entry_ptr = entry; } } ZSTR_ALLOCA_FREE(pattern_lc, use_heap); zend_string_release(regex); return 0; }
static zend_string *browscap_convert_pattern(zend_string *pattern, int persistent) /* {{{ */ { size_t i, j=0; char *t; zend_string *res; char *lc_pattern; ALLOCA_FLAG(use_heap); res = zend_string_alloc(browscap_compute_regex_len(pattern), persistent); t = ZSTR_VAL(res); lc_pattern = do_alloca(ZSTR_LEN(pattern) + 1, use_heap); zend_str_tolower_copy(lc_pattern, ZSTR_VAL(pattern), ZSTR_LEN(pattern)); t[j++] = '~'; t[j++] = '^'; for (i = 0; i < ZSTR_LEN(pattern); i++, j++) { switch (lc_pattern[i]) { case '?': t[j] = '.'; break; case '*': t[j++] = '.'; t[j] = '*'; break; case '.': t[j++] = '\\'; t[j] = '.'; break; case '\\': t[j++] = '\\'; t[j] = '\\'; break; case '(': t[j++] = '\\'; t[j] = '('; break; case ')': t[j++] = '\\'; t[j] = ')'; break; case '~': t[j++] = '\\'; t[j] = '~'; break; case '+': t[j++] = '\\'; t[j] = '+'; break; default: t[j] = lc_pattern[i]; break; } } t[j++] = '$'; t[j++] = '~'; t[j]=0; ZSTR_LEN(res) = j; free_alloca(lc_pattern, use_heap); return res; }