ngx_int_t
ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,
    ngx_uint_t flags)
{
    size_t           len;
    u_char          *p;
    ngx_str_t       *name;
    ngx_uint_t       i, k, n, skip, last;
    ngx_array_t     *keys, *hwc;
    ngx_hash_key_t  *hk;
    last = key->len;
    if (flags & NGX_HASH_WILDCARD_KEY) {
        n = 0;
        for (i = 0; i < key->len; i++) {
            if (key->data[i] == '*') {
                if (++n > 1) {
                    return NGX_DECLINED;
                }
            }
            if (key->data[i] == '.' && key->data[i + 1] == '.') {
                return NGX_DECLINED;
            }
        }
        if (key->len > 1 && key->data[0] == '.') {
            skip = 1;
            goto wildcard;
        }
        if (key->len > 2) {
            if (key->data[0] == '*' && key->data[1] == '.') {
                skip = 2;
                goto wildcard;
            }
            if (key->data[i - 2] == '.' && key->data[i - 1] == '*') {
                skip = 0;
                last -= 2;
                goto wildcard;
            }
        }
        if (n) {
            return NGX_DECLINED;
        }
    }
    k = 0;
    for (i = 0; i < last; i++) {
        if (!(flags & NGX_HASH_READONLY_KEY)) {
            key->data[i] = ngx_tolower(key->data[i]);
        }
        k = ngx_hash(k, key->data[i]);
    }
    k %= ha->hsize;
    name = ha->keys_hash[k].elts;
    if (name) {
        for (i = 0; i < ha->keys_hash[k].nelts; i++) {
            if (last != name[i].len) {
                continue;
            }
            if (ngx_strncmp(key->data, name[i].data, last) == 0) {
                return NGX_BUSY;
            }
        }
    } else {
        if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
                           sizeof(ngx_str_t))
            != NGX_OK)
        {
            return NGX_ERROR;
        }
    }
    name = ngx_array_push(&ha->keys_hash[k]);
    if (name == NULL) {
        return NGX_ERROR;
    }
    *name = *key;
    hk = ngx_array_push(&ha->keys);
    if (hk == NULL) {
        return NGX_ERROR;
    }
    hk->key = *key;
    hk->key_hash = ngx_hash_key(key->data, last);
    hk->value = value;
    return NGX_OK;
wildcard:
    k = ngx_hash_strlow(&key->data[skip], &key->data[skip], last - skip);
    k %= ha->hsize;
    if (skip == 1) {
        name = ha->keys_hash[k].elts;
        if (name) {
            len = last - skip;
            for (i = 0; i < ha->keys_hash[k].nelts; i++) {
                if (len != name[i].len) {
                    continue;
                }
                if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
                    return NGX_BUSY;
                }
            }
        } else {
            if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
                               sizeof(ngx_str_t))
                != NGX_OK)
            {
                return NGX_ERROR;
            }
        }
        name = ngx_array_push(&ha->keys_hash[k]);
        if (name == NULL) {
            return NGX_ERROR;
        }
        name->len = last - 1;
        name->data = ngx_pnalloc(ha->temp_pool, name->len);
        if (name->data == NULL) {
            return NGX_ERROR;
        }
        ngx_memcpy(name->data, &key->data[1], name->len);
    }
    if (skip) {
        p = ngx_pnalloc(ha->temp_pool, last);
        if (p == NULL) {
            return NGX_ERROR;
        }
        len = 0;
        n = 0;
        for (i = last - 1; i; i--) {
            if (key->data[i] == '.') {
                ngx_memcpy(&p[n], &key->data[i + 1], len);
                n += len;
                p[n++] = '.';
                len = 0;
                continue;
            }
            len++;
        }
        if (len) {
            ngx_memcpy(&p[n], &key->data[1], len);
            n += len;
        }
        p[n] = '\0';
        hwc = &ha->dns_wc_head;
        keys = &ha->dns_wc_head_hash[k];
    } else {
        last++;
        p = ngx_pnalloc(ha->temp_pool, last);
        if (p == NULL) {
            return NGX_ERROR;
        }
        ngx_cpystrn(p, key->data, last);
        hwc = &ha->dns_wc_tail;
        keys = &ha->dns_wc_tail_hash[k];
    }
    hk = ngx_array_push(hwc);
    if (hk == NULL) {
        return NGX_ERROR;
    }
    hk->key.len = last - 1;
    hk->key.data = p;
    hk->key_hash = 0;
    hk->value = value;
    name = keys->elts;
    if (name) {
        len = last - skip;
        for (i = 0; i < keys->nelts; i++) {
            if (len != name[i].len) {
                continue;
            }
            if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
                return NGX_BUSY;
            }
        }
    } else {
        if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK)
        {
            return NGX_ERROR;
        }
    }
    name = ngx_array_push(keys);
    if (name == NULL) {
        return NGX_ERROR;
    }
    name->len = last - skip;
    name->data = ngx_pnalloc(ha->temp_pool, name->len);
    if (name->data == NULL) {
        return NGX_ERROR;
    }
    ngx_memcpy(name->data, key->data + skip, name->len);
    return NGX_OK;
}
['static ngx_int_t\nngx_http_ssi_preconfiguration(ngx_conf_t *cf)\n{\n    ngx_int_t                  rc;\n    ngx_http_variable_t       *var, *v;\n    ngx_http_ssi_command_t    *cmd;\n    ngx_http_ssi_main_conf_t  *smcf;\n    for (v = ngx_http_ssi_vars; v->name.len; v++) {\n        var = ngx_http_add_variable(cf, &v->name, v->flags);\n        if (var == NULL) {\n            return NGX_ERROR;\n        }\n        var->get_handler = v->get_handler;\n        var->data = v->data;\n    }\n    smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module);\n    for (cmd = ngx_http_ssi_commands; cmd->name.len; cmd++) {\n        rc = ngx_hash_add_key(&smcf->commands, &cmd->name, cmd,\n                              NGX_HASH_READONLY_KEY);\n        if (rc == NGX_OK) {\n            continue;\n        }\n        if (rc == NGX_BUSY) {\n            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                               "conflicting SSI command \\"%V\\"", &cmd->name);\n        }\n        return NGX_ERROR;\n    }\n    return NGX_OK;\n}', 'ngx_http_variable_t *\nngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)\n{\n    ngx_int_t                   rc;\n    ngx_uint_t                  i;\n    ngx_hash_key_t             *key;\n    ngx_http_variable_t        *v;\n    ngx_http_core_main_conf_t  *cmcf;\n    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);\n    key = cmcf->variables_keys->keys.elts;\n    for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {\n        if (name->len != key[i].key.len\n            || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)\n        {\n            continue;\n        }\n        v = key[i].value;\n        if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {\n            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                               "the duplicate \\"%V\\" variable", name);\n            return NULL;\n        }\n        return v;\n    }\n    v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));\n    if (v == NULL) {\n        return NULL;\n    }\n    v->name.len = name->len;\n    v->name.data = ngx_pnalloc(cf->pool, name->len);\n    if (v->name.data == NULL) {\n        return NULL;\n    }\n    ngx_strlow(v->name.data, name->data, name->len);\n    v->set_handler = NULL;\n    v->get_handler = NULL;\n    v->data = 0;\n    v->flags = flags;\n    v->index = 0;\n    rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);\n    if (rc == NGX_ERROR) {\n        return NULL;\n    }\n    if (rc == NGX_BUSY) {\n        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                           "conflicting variable name \\"%V\\"", name);\n        return NULL;\n    }\n    return v;\n}', "ngx_int_t\nngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,\n    ngx_uint_t flags)\n{\n    size_t           len;\n    u_char          *p;\n    ngx_str_t       *name;\n    ngx_uint_t       i, k, n, skip, last;\n    ngx_array_t     *keys, *hwc;\n    ngx_hash_key_t  *hk;\n    last = key->len;\n    if (flags & NGX_HASH_WILDCARD_KEY) {\n        n = 0;\n        for (i = 0; i < key->len; i++) {\n            if (key->data[i] == '*') {\n                if (++n > 1) {\n                    return NGX_DECLINED;\n                }\n            }\n            if (key->data[i] == '.' && key->data[i + 1] == '.') {\n                return NGX_DECLINED;\n            }\n        }\n        if (key->len > 1 && key->data[0] == '.') {\n            skip = 1;\n            goto wildcard;\n        }\n        if (key->len > 2) {\n            if (key->data[0] == '*' && key->data[1] == '.') {\n                skip = 2;\n                goto wildcard;\n            }\n            if (key->data[i - 2] == '.' && key->data[i - 1] == '*') {\n                skip = 0;\n                last -= 2;\n                goto wildcard;\n            }\n        }\n        if (n) {\n            return NGX_DECLINED;\n        }\n    }\n    k = 0;\n    for (i = 0; i < last; i++) {\n        if (!(flags & NGX_HASH_READONLY_KEY)) {\n            key->data[i] = ngx_tolower(key->data[i]);\n        }\n        k = ngx_hash(k, key->data[i]);\n    }\n    k %= ha->hsize;\n    name = ha->keys_hash[k].elts;\n    if (name) {\n        for (i = 0; i < ha->keys_hash[k].nelts; i++) {\n            if (last != name[i].len) {\n                continue;\n            }\n            if (ngx_strncmp(key->data, name[i].data, last) == 0) {\n                return NGX_BUSY;\n            }\n        }\n    } else {\n        if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,\n                           sizeof(ngx_str_t))\n            != NGX_OK)\n        {\n            return NGX_ERROR;\n        }\n    }\n    name = ngx_array_push(&ha->keys_hash[k]);\n    if (name == NULL) {\n        return NGX_ERROR;\n    }\n    *name = *key;\n    hk = ngx_array_push(&ha->keys);\n    if (hk == NULL) {\n        return NGX_ERROR;\n    }\n    hk->key = *key;\n    hk->key_hash = ngx_hash_key(key->data, last);\n    hk->value = value;\n    return NGX_OK;\nwildcard:\n    k = ngx_hash_strlow(&key->data[skip], &key->data[skip], last - skip);\n    k %= ha->hsize;\n    if (skip == 1) {\n        name = ha->keys_hash[k].elts;\n        if (name) {\n            len = last - skip;\n            for (i = 0; i < ha->keys_hash[k].nelts; i++) {\n                if (len != name[i].len) {\n                    continue;\n                }\n                if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {\n                    return NGX_BUSY;\n                }\n            }\n        } else {\n            if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,\n                               sizeof(ngx_str_t))\n                != NGX_OK)\n            {\n                return NGX_ERROR;\n            }\n        }\n        name = ngx_array_push(&ha->keys_hash[k]);\n        if (name == NULL) {\n            return NGX_ERROR;\n        }\n        name->len = last - 1;\n        name->data = ngx_pnalloc(ha->temp_pool, name->len);\n        if (name->data == NULL) {\n            return NGX_ERROR;\n        }\n        ngx_memcpy(name->data, &key->data[1], name->len);\n    }\n    if (skip) {\n        p = ngx_pnalloc(ha->temp_pool, last);\n        if (p == NULL) {\n            return NGX_ERROR;\n        }\n        len = 0;\n        n = 0;\n        for (i = last - 1; i; i--) {\n            if (key->data[i] == '.') {\n                ngx_memcpy(&p[n], &key->data[i + 1], len);\n                n += len;\n                p[n++] = '.';\n                len = 0;\n                continue;\n            }\n            len++;\n        }\n        if (len) {\n            ngx_memcpy(&p[n], &key->data[1], len);\n            n += len;\n        }\n        p[n] = '\\0';\n        hwc = &ha->dns_wc_head;\n        keys = &ha->dns_wc_head_hash[k];\n    } else {\n        last++;\n        p = ngx_pnalloc(ha->temp_pool, last);\n        if (p == NULL) {\n            return NGX_ERROR;\n        }\n        ngx_cpystrn(p, key->data, last);\n        hwc = &ha->dns_wc_tail;\n        keys = &ha->dns_wc_tail_hash[k];\n    }\n    hk = ngx_array_push(hwc);\n    if (hk == NULL) {\n        return NGX_ERROR;\n    }\n    hk->key.len = last - 1;\n    hk->key.data = p;\n    hk->key_hash = 0;\n    hk->value = value;\n    name = keys->elts;\n    if (name) {\n        len = last - skip;\n        for (i = 0; i < keys->nelts; i++) {\n            if (len != name[i].len) {\n                continue;\n            }\n            if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {\n                return NGX_BUSY;\n            }\n        }\n    } else {\n        if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK)\n        {\n            return NGX_ERROR;\n        }\n    }\n    name = ngx_array_push(keys);\n    if (name == NULL) {\n        return NGX_ERROR;\n    }\n    name->len = last - skip;\n    name->data = ngx_pnalloc(ha->temp_pool, name->len);\n    if (name->data == NULL) {\n        return NGX_ERROR;\n    }\n    ngx_memcpy(name->data, key->data + skip, name->len);\n    return NGX_OK;\n}"]