/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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"

/* re-use the ->unset field to determine options type */
#define MpOptionsType(o)        (o)->unset
#define MpOptionsTypeDir(o)     MpOptionsType(o) == MpDir_f_UNSET
#define MpOptionsTypeSrv(o)     MpOptionsType(o) == MpSrv_f_UNSET
#define MpOptionsTypeDir_set(o) MpOptionsType(o) = MpDir_f_UNSET
#define MpOptionsTypeSrv_set(o) MpOptionsType(o) = MpSrv_f_UNSET
#define MP_OPTIONS_TYPE_DIR     MpDir_f_UNSET
#define MP_OPTIONS_TYPE_SRV     MpSrv_f_UNSET

static modperl_opts_t flags_lookup(modperl_options_t *o,
                                   const char *str)
{
    switch (MpOptionsType(o)) {
      case MP_OPTIONS_TYPE_SRV:
        return modperl_flags_lookup_srv(str);
      case MP_OPTIONS_TYPE_DIR:
        return modperl_flags_lookup_dir(str);
      default:
        return '\0';
    };
}

static const char *type_lookup(modperl_options_t *o)
{
    switch (MpOptionsType(o)) {
      case MP_OPTIONS_TYPE_SRV:
        return "server";
      case MP_OPTIONS_TYPE_DIR:
        return "directory";
      default:
        return "unknown";
    };
}

modperl_options_t *modperl_options_new(apr_pool_t *p, int type)
{
    modperl_options_t *options =
        (modperl_options_t *)apr_pcalloc(p, sizeof(*options));

    options->opts = options->unset =
        (type == MpSrvType ? MpSrv_f_UNSET : MpDir_f_UNSET);

    return options;
}

const char *modperl_options_set(apr_pool_t *p, modperl_options_t *o,
                                const char *str)
{
    modperl_opts_t opt;
    char action = '\0';
    const char *error = NULL;

    if (*str == '+' || *str == '-') {
        action = *(str++);
    }

    if ((opt = flags_lookup(o, str)) == -1) {
        error = apr_pstrcat(p, "Invalid per-", type_lookup(o),
                            " PerlOption: ", str, NULL);

        if (MpOptionsTypeDir(o)) {
            modperl_options_t dummy;
            MpOptionsTypeSrv_set(&dummy);

            if (flags_lookup(&dummy, str) == -1) {
                error = apr_pstrcat(p, error,
                                    " (only allowed per-server)",
                                    NULL);
            }
        }

        return error;
    }
#ifndef USE_ITHREADS
    else if (MpOptionsTypeSrv(o)) {
        if (MpSrvOPT_ITHREAD_ONLY(opt)) {
            return apr_pstrcat(p, "PerlOption `", str,
                               "' requires an ithreads enabled Perl", NULL);
        }
    }
#endif

    o->opts_seen |= opt;

    if (action == '-') {
        o->opts_remove |= opt;
        o->opts_add &= ~opt;
        o->opts &= ~opt;
    }
    else if (action == '+') {
        o->opts_add |= opt;
        o->opts_remove &= ~opt;
        o->opts |= opt;
    }
    else {
        o->opts |= opt;
    }

    return NULL;
}

modperl_options_t *modperl_options_merge(apr_pool_t *p,
                                         modperl_options_t *base,
                                         modperl_options_t *add)
{
    modperl_options_t *conf = modperl_options_new(p, 0);
    memcpy((char *)conf, (const char *)base, sizeof(*base));

    if (add->opts & add->unset) {
        /* there was no explicit setting of add->opts, so we merge
         * preserve the invariant (opts_add & opts_remove) == 0
         */
        conf->opts_add =
            (conf->opts_add & ~add->opts_remove) | add->opts_add;
        conf->opts_remove =
            (conf->opts_remove & ~add->opts_add) | add->opts_remove;
        conf->opts =
            (conf->opts & ~conf->opts_remove) | conf->opts_add;
    }
    else {
        /* otherwise we just copy, because an explicit opts setting
         * overrides all earlier +/- modifiers
         */
        conf->opts = add->opts;
        conf->opts_add = add->opts_add;
        conf->opts_remove = add->opts_remove;
    }

    conf->opts_seen |= add->opts_seen;

    return conf;
}

/*
 * Local Variables:
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * End:
 */
