<commit_before>/* Copyright 2001-2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mod_perl.h"

/*
 * mgv = ModPerl Glob Value || Mostly Glob Value
 * as close to GV as we can get without actually using a GV
 * need config structures to be free of Perl structures
 */

#define modperl_mgv_new_w_name(mgv, p, n, copy) \
mgv = modperl_mgv_new(p); \
mgv->len = strlen(n); \
mgv->name = (copy ? apr_pstrndup(p, n, mgv->len) : n)

#define modperl_mgv_new_name(mgv, p, n) \
modperl_mgv_new_w_name(mgv, p, n, 1)

#define modperl_mgv_new_namen(mgv, p, n) \
modperl_mgv_new_w_name(mgv, p, n, 0)

int modperl_mgv_equal(modperl_mgv_t *mgv1,
                      modperl_mgv_t *mgv2)
{
    for (; mgv1 && mgv2; mgv1=mgv1->next, mgv2=mgv2->next) {
        if (mgv1->hash != mgv2->hash) {
            return FALSE;
        }
        if (mgv1->len != mgv2->len) {
            return FALSE;
        }
        if (memNE(mgv1->name, mgv2->name, mgv1->len)) {
            return FALSE;
        }
    }

    return TRUE;
}

modperl_mgv_t *modperl_mgv_new(apr_pool_t *p)
{
    return (modperl_mgv_t *)apr_pcalloc(p, sizeof(modperl_mgv_t));
}

#define modperl_mgv_get_next(mgv) \
    if (mgv->name) { \
        mgv->next = modperl_mgv_new(p); \
        mgv = mgv->next; \
    }

#define modperl_mgv_hash(mgv) \
    PERL_HASH(mgv->hash, mgv->name, mgv->len)
 /* MP_TRACE_h(MP_FUNC, "%s...hash=%ld\n", mgv->name, mgv->hash) */

modperl_mgv_t *modperl_mgv_compile(pTHX_ apr_pool_t *p,
                                   register const char *name)
{
    register const char *namend;
    I32 len;
    modperl_mgv_t *symbol = modperl_mgv_new(p);
    modperl_mgv_t *mgv = symbol;

    /* @mgv = split '::', $name */
    for (namend = name; *namend; namend++) {
        if (*namend == ':' && namend[1] == ':') {
            if ((len = (namend - name)) > 0) {
                modperl_mgv_get_next(mgv);
                mgv->name = apr_palloc(p, len+3);
                Copy(name, mgv->name, len, char);
                mgv->name[len++] = ':';
                mgv->name[len++] = ':';
                mgv->name[len] = '\0';
                mgv->len = len;
                modperl_mgv_hash(mgv);
            }
            name = namend + 2;
        }
    }

    modperl_mgv_get_next(mgv);

    mgv->len = namend - name;
    mgv->name = apr_pstrndup(p, name, mgv->len);
    modperl_mgv_hash(mgv);

    return symbol;
}

void modperl_mgv_append(pTHX_ apr_pool_t *p, modperl_mgv_t *symbol,
                        const char *name)
{
    modperl_mgv_t *mgv = symbol;

    while (mgv->next) {
        mgv = mgv->next;
    }

    mgv->name = apr_pstrcat(p, mgv->name, "::", NULL);
    mgv->len += 2;
    modperl_mgv_hash(mgv);

    mgv->next = modperl_mgv_compile(aTHX_ p, name);
}

/* faster replacement for gv_fetchpv() */
GV *modperl_mgv_lookup(pTHX_ modperl_mgv_t *symbol)
{
    HV *stash = PL_defstash;
    modperl_mgv_t *mgv;

    if (!symbol->hash) {
        /* special case for MyClass->handler */
        return (GV*)sv_2mortal(newSVpvn(symbol->name, symbol->len));
    }

    for (mgv = symbol; mgv; mgv = mgv->next) {
        HE *he = hv_fetch_he(stash, mgv->name, mgv->len, mgv->hash);
        if (he) {
            if (mgv->next) {
                stash = GvHV((GV *)HeVAL(he));
            }
            else {
                return (GV *)HeVAL(he);
            }
        }
        else {
            return Nullgv;
        }
    }

    return Nullgv;
}

#ifdef USE_ITHREADS
MP_INLINE GV *modperl_mgv_lookup_autoload(pTHX_ modperl_mgv_t *symbol,
                                          server_rec *s, apr_pool_t *p)
{
    MP_dSCFG(s);
    GV *gv = modperl_mgv_lookup(aTHX_ symbol);

    if (gv || !MpSrvPARENT(scfg)) {
        return gv;
    }

    /* 
     * this VirtualHost has its own parent interpreter
     * must require the module again with this server's THX
     */
    modperl_mgv_require_module(aTHX_ symbol, s, p);

    return modperl_mgv_lookup(aTHX_ symbol);
}
#else
MP_INLINE GV *modperl_mgv_lookup_autoload(pTHX_ modperl_mgv_t *symbol,
                                          server_rec *s, apr_pool_t *p)
{
    return modperl_mgv_lookup(aTHX_ symbol);
}
#endif

/* currently used for complex filters attributes parsing */
/* XXX: may want to generalize it for any handlers */
#define MODPERL_MGV_DEEP_RESOLVE(handler, p) \
    if (handler->attrs & MP_FILTER_HAS_INIT_HANDLER) { \
        modperl_filter_resolve_init_handler(aTHX_ handler, p); \
    }

int modperl_mgv_resolve(pTHX_ modperl_handler_t *handler,
                        apr_pool_t *p, const char *name, int logfailure)
{
    CV *cv;
    GV *gv;
    HV *stash = Nullhv;
    char *handler_name = "handler";
    char *tmp;

    if (MpHandlerANON(handler)) {
        /* already resolved anonymous handler */
        return 1;
    }
    
    if (strnEQ(name, "sub ", 4)) {
        MP_TRACE_h(MP_FUNC, "handler is anonymous\n");
        MpHandlerANON_On(handler);
        MpHandlerPARSED_On(handler);
        return 1;<commit_msg>tidy up the macros PR: Obtained from: Submitted by: Reviewed by:<commit_after>/* Copyright 2001-2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mod_perl.h"

/*
 * mgv = ModPerl Glob Value || Mostly Glob Value
 * as close to GV as we can get without actually using a GV
 * need config structures to be free of Perl structures
 */

#define modperl_mgv_new_w_name(mgv, p, n, copy)         \
    mgv = modperl_mgv_new(p);                           \
    mgv->len = strlen(n);                               \
    mgv->name = (copy ? apr_pstrndup(p, n, mgv->len) : n)

#define modperl_mgv_new_name(mgv, p, n)         \
    modperl_mgv_new_w_name(mgv, p, n, 1)

#define modperl_mgv_new_namen(mgv, p, n)        \
    modperl_mgv_new_w_name(mgv, p, n, 0)

int modperl_mgv_equal(modperl_mgv_t *mgv1,
                      modperl_mgv_t *mgv2)
{
    for (; mgv1 && mgv2; mgv1=mgv1->next, mgv2=mgv2->next) {
        if (mgv1->hash != mgv2->hash) {
            return FALSE;
        }
        if (mgv1->len != mgv2->len) {
            return FALSE;
        }
        if (memNE(mgv1->name, mgv2->name, mgv1->len)) {
            return FALSE;
        }
    }

    return TRUE;
}

modperl_mgv_t *modperl_mgv_new(apr_pool_t *p)
{
    return (modperl_mgv_t *)apr_pcalloc(p, sizeof(modperl_mgv_t));
}

#define modperl_mgv_get_next(mgv)               \
    if (mgv->name) {                            \
        mgv->next = modperl_mgv_new(p);         \
        mgv = mgv->next;                        \
    }

#define modperl_mgv_hash(mgv)                   \
    PERL_HASH(mgv->hash, mgv->name, mgv->len)
 /* MP_TRACE_h(MP_FUNC, "%s...hash=%ld\n", mgv->name, mgv->hash) */

modperl_mgv_t *modperl_mgv_compile(pTHX_ apr_pool_t *p,
                                   register const char *name)
{
    register const char *namend;
    I32 len;
    modperl_mgv_t *symbol = modperl_mgv_new(p);
    modperl_mgv_t *mgv = symbol;

    /* @mgv = split '::', $name */
    for (namend = name; *namend; namend++) {
        if (*namend == ':' && namend[1] == ':') {
            if ((len = (namend - name)) > 0) {
                modperl_mgv_get_next(mgv);
                mgv->name = apr_palloc(p, len+3);
                Copy(name, mgv->name, len, char);
                mgv->name[len++] = ':';
                mgv->name[len++] = ':';
                mgv->name[len] = '\0';
                mgv->len = len;
                modperl_mgv_hash(mgv);
            }
            name = namend + 2;
        }
    }

    modperl_mgv_get_next(mgv);

    mgv->len = namend - name;
    mgv->name = apr_pstrndup(p, name, mgv->len);
    modperl_mgv_hash(mgv);

    return symbol;
}

void modperl_mgv_append(pTHX_ apr_pool_t *p, modperl_mgv_t *symbol,
                        const char *name)
{
    modperl_mgv_t *mgv = symbol;

    while (mgv->next) {
        mgv = mgv->next;
    }

    mgv->name = apr_pstrcat(p, mgv->name, "::", NULL);
    mgv->len += 2;
    modperl_mgv_hash(mgv);

    mgv->next = modperl_mgv_compile(aTHX_ p, name);
}

/* faster replacement for gv_fetchpv() */
GV *modperl_mgv_lookup(pTHX_ modperl_mgv_t *symbol)
{
    HV *stash = PL_defstash;
    modperl_mgv_t *mgv;

    if (!symbol->hash) {
        /* special case for MyClass->handler */
        return (GV*)sv_2mortal(newSVpvn(symbol->name, symbol->len));
    }

    for (mgv = symbol; mgv; mgv = mgv->next) {
        HE *he = hv_fetch_he(stash, mgv->name, mgv->len, mgv->hash);
        if (he) {
            if (mgv->next) {
                stash = GvHV((GV *)HeVAL(he));
            }
            else {
                return (GV *)HeVAL(he);
            }
        }
        else {
            return Nullgv;
        }
    }

    return Nullgv;
}

#ifdef USE_ITHREADS
MP_INLINE GV *modperl_mgv_lookup_autoload(pTHX_ modperl_mgv_t *symbol,
                                          server_rec *s, apr_pool_t *p)
{
    MP_dSCFG(s);
    GV *gv = modperl_mgv_lookup(aTHX_ symbol);

    if (gv || !MpSrvPARENT(scfg)) {
        return gv;
    }

    /* 
     * this VirtualHost has its own parent interpreter
     * must require the module again with this server's THX
     */
    modperl_mgv_require_module(aTHX_ symbol, s, p);

    return modperl_mgv_lookup(aTHX_ symbol);
}
#else
MP_INLINE GV *modperl_mgv_lookup_autoload(pTHX_ modperl_mgv_t *symbol,
                                          server_rec *s, apr_pool_t *p)
{
    return modperl_mgv_lookup(aTHX_ symbol);
}
#endif

/* currently used for complex filters attributes parsing */
/* XXX: may want to generalize it for any handlers */
#define MODPERL_MGV_DEEP_RESOLVE(handler, p)                   \
    if (handler->attrs & MP_FILTER_HAS_INIT_HANDLER) {         \
        modperl_filter_resolve_init_handler(aTHX_ handler, p); \
    }

int modperl_mgv_resolve(pTHX_ modperl_handler_t *handler,
                        apr_pool_t *p, const char *name, int logfailure)
{
    CV *cv;
    GV *gv;
    HV *stash = Nullhv;
    char *handler_name = "handler";
    char *tmp;

    if (MpHandlerANON(handler)) {
        /* already resolved anonymous handler */
        return 1;
    }
    
    if (strnEQ(name, "sub ", 4)) {
        MP_TRACE_h(MP_FUNC, "handler is anonymous\n");
        MpHandlerANON_On(handler);
        MpHandlerPARSED_On(handler);
        return 1;
{'fraction_non_alphanumeric': 0.12220461348829019, 'fraction_numerical': 0.007219580912132418, 'mean_word_length': 2.15352581898945, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '338447', 'n_tokens_mistral': 4344, 'n_tokens_neox': 4115, 'n_words': 943}