2016-07-26 15:18:32 +03:00
|
|
|
// vi: set ts=4 sw=4 :
|
|
|
|
// vim: set tw=75 :
|
|
|
|
|
|
|
|
// conf_meta.cpp - configfile reading routines
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
|
|
|
*
|
|
|
|
* This file is part of Metamod.
|
|
|
|
*
|
|
|
|
* Metamod is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2 of the License, or (at
|
|
|
|
* your option) any later version.
|
|
|
|
*
|
|
|
|
* Metamod is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Metamod; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* In addition, as a special exception, the author gives permission to
|
|
|
|
* link the code of this program with the Half-Life Game g_engine ("HL
|
|
|
|
* g_engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
|
|
* respects for all of the code used other than the HL g_engine and MODs
|
|
|
|
* from Valve. If you modify this file, you may extend this exception
|
|
|
|
* to your version of the file, but you are not obligated to do so. If
|
|
|
|
* you do not wish to do so, delete this exception statement from your
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-07-26 07:22:47 +07:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
MConfig::MConfig() : list(NULL), filename(NULL), debuglevel(0), gamedll(NULL), plugins_file(NULL), exec_cfg(NULL)
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize default values from the stored options struct. Has to happen
|
|
|
|
// _after_ constructor, so that all the fields are allocated (d'oh).
|
2016-07-26 15:18:32 +03:00
|
|
|
void MConfig::init(option_t* global_options)
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
list = global_options;
|
|
|
|
for (auto optp = list; optp->name; optp++)
|
2016-07-26 07:22:47 +07:00
|
|
|
set(optp, optp->init);
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
option_t* MConfig::find(const char* lookup) const
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
for (auto optp = list; optp->name; optp++)
|
|
|
|
if (!strcmp(optp->name, lookup)) {
|
|
|
|
return optp;
|
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
mBOOL MConfig::set(const char* key, const char* value)
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
option_t* optp = find(key);
|
|
|
|
|
2016-07-26 07:22:47 +07:00
|
|
|
if (optp)
|
|
|
|
return set(optp, value);
|
2016-07-26 15:18:32 +03:00
|
|
|
|
|
|
|
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
mBOOL MConfig::set(option_t* setp, const char* setstr)
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
char pathbuf[PATH_MAX ];
|
|
|
|
int* optval = (int *) setp->dest;
|
|
|
|
char** optstr = (char **) setp->dest;
|
|
|
|
// cvar_t *optcvar = (cvar_t *) setp->dest;
|
|
|
|
// SETOPT_FN optcmd = (SETOPT_FN) setp->dest;
|
2016-07-26 07:22:47 +07:00
|
|
|
|
|
|
|
if (!setstr)
|
|
|
|
return mTRUE;
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
switch (setp->type) {
|
2016-07-26 07:22:47 +07:00
|
|
|
case CF_INT:
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!isdigit(setstr[0])) {
|
|
|
|
META_ERROR("option '%s' invalid format '%s'", setp->name, setstr);
|
2016-07-26 07:22:47 +07:00
|
|
|
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
*optval = atoi(setstr);
|
2016-07-26 07:22:47 +07:00
|
|
|
META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval));
|
|
|
|
break;
|
|
|
|
case CF_BOOL:
|
2016-07-26 15:18:32 +03:00
|
|
|
if (is_yes(setstr)) {
|
|
|
|
*optval = TRUE;
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else if (is_no(setstr)) {
|
|
|
|
*optval = FALSE;
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else {
|
|
|
|
META_ERROR("option '%s' invalid format '%s'", setp->name,
|
|
|
|
setstr);
|
2016-07-26 07:22:47 +07:00
|
|
|
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
|
|
|
}
|
|
|
|
META_DEBUG(3, ("set config bool: %s = %s", setp->name, *optval ? "true" : "false"));
|
|
|
|
break;
|
|
|
|
case CF_STR:
|
|
|
|
if (*optstr)
|
|
|
|
free(*optstr);
|
2016-07-26 15:18:32 +03:00
|
|
|
*optstr = _strdup(setstr);
|
2016-07-26 07:22:47 +07:00
|
|
|
META_DEBUG(3, ("set config string: %s = %s", setp->name, *optstr));
|
|
|
|
break;
|
|
|
|
case CF_PATH:
|
|
|
|
if (*optstr)
|
|
|
|
free(*optstr);
|
|
|
|
full_gamedir_path(setstr, pathbuf);
|
2016-07-26 15:18:32 +03:00
|
|
|
*optstr = _strdup(pathbuf);
|
2016-07-26 07:22:47 +07:00
|
|
|
META_DEBUG(3, ("set config path: %s = %s", setp->name, *optstr));
|
|
|
|
break;
|
2016-07-26 15:18:32 +03:00
|
|
|
#if 0
|
|
|
|
case CF_CVAR:
|
|
|
|
CVAR_SET_STRING(optcvar->name, setstr);
|
|
|
|
META_DEBUG(3, ("set config cvar: %s = %s", optcvar->name, setstr));
|
|
|
|
break;
|
|
|
|
case CF_CMD:
|
|
|
|
optcmd(setp->name, setstr);
|
|
|
|
META_DEBUG(3, ("set config command: %s, %s",
|
|
|
|
optcvar->name, setstr));
|
|
|
|
break;
|
|
|
|
#endif
|
2016-07-26 07:22:47 +07:00
|
|
|
default:
|
2016-07-26 15:18:32 +03:00
|
|
|
META_ERROR("unrecognized config type '%d'", setp->type);
|
2016-07-26 07:22:47 +07:00
|
|
|
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mTRUE);
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
mBOOL MConfig::load(const char* fn)
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
FILE* fp;
|
|
|
|
char loadfile[PATH_MAX ];
|
2016-07-26 07:22:47 +07:00
|
|
|
char line[MAX_CONF_LEN];
|
|
|
|
char *optname, *optval;
|
2016-07-26 15:18:32 +03:00
|
|
|
option_t* optp;
|
2016-07-26 07:22:47 +07:00
|
|
|
int ln;
|
|
|
|
|
|
|
|
// Make full pathname (from gamedir if relative, collapse "..",
|
|
|
|
// backslashes, etc).
|
|
|
|
full_gamedir_path(fn, loadfile);
|
|
|
|
|
|
|
|
fp = fopen(loadfile, "r");
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!fp) {
|
|
|
|
META_ERROR("unable to open config file '%s': %s", loadfile,
|
|
|
|
strerror(errno));
|
2016-07-26 07:22:47 +07:00
|
|
|
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
|
|
}
|
|
|
|
|
|
|
|
META_DEBUG(2, ("Loading from config file: %s", loadfile));
|
2016-07-26 15:18:32 +03:00
|
|
|
for (ln = 1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) {
|
|
|
|
if (line[0] == '#')
|
2016-07-26 07:22:47 +07:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
if (line[0] == ';')
|
2016-07-26 07:22:47 +07:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
if (strnmatch(line, "//", 2))
|
|
|
|
continue;
|
|
|
|
if (!(optname = strtok(line, " \t\r\n"))) {
|
|
|
|
META_ERROR("'%s' line %d: bad config format: missing option",
|
|
|
|
loadfile, ln);
|
2016-07-26 07:22:47 +07:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!(optval = strtok(NULL, "\r\n"))) {
|
|
|
|
META_ERROR("'%s' line %d: bad config format: missing value",
|
|
|
|
loadfile, ln);
|
2016-07-26 07:22:47 +07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!(optp = find(optname))) {
|
|
|
|
META_ERROR("'%s' line %d: unknown option name '%s'",
|
|
|
|
loadfile, ln, optname);
|
2016-07-26 07:22:47 +07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!set(optp, optval)) {
|
|
|
|
META_ERROR("'%s' line %d: unable to set option '%s' value '%s'",
|
|
|
|
loadfile, ln, optname, optval);
|
2016-07-26 07:22:47 +07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
filename = _strdup(loadfile);
|
2016-07-26 07:22:47 +07:00
|
|
|
fclose(fp);
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mTRUE);
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
void MConfig::show(void) const
|
2016-07-26 07:22:47 +07:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
META_CONS("Config options from localinfo and %s:", filename);
|
2016-07-26 07:22:47 +07:00
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
for (auto optp = list; optp->name; optp++) {
|
|
|
|
int* optval = (int *) optp->dest;
|
|
|
|
char** optstr = (char **) optp->dest;
|
2016-07-26 07:22:47 +07:00
|
|
|
// cvar_t *optcvar = (cvar_t *) optp->dest;
|
|
|
|
// SETOPT_FN optcmd = (SETOPT_FN) optp->dest;
|
2016-07-26 15:18:32 +03:00
|
|
|
switch (optp->type) {
|
2016-07-26 07:22:47 +07:00
|
|
|
case CF_INT:
|
2016-07-26 15:18:32 +03:00
|
|
|
printf(" %-20s\t%d\n", optp->name, *optval);
|
2016-07-26 07:22:47 +07:00
|
|
|
break;
|
|
|
|
case CF_BOOL:
|
2016-07-26 15:18:32 +03:00
|
|
|
printf(" %-20s\t%s\n", optp->name, *optval ? "true" : "false");
|
2016-07-26 07:22:47 +07:00
|
|
|
break;
|
|
|
|
case CF_STR:
|
|
|
|
case CF_PATH:
|
2016-07-26 15:18:32 +03:00
|
|
|
printf(" %-20s\t%s\n", optp->name, *optstr ? *optstr : "");
|
2016-07-26 07:22:47 +07:00
|
|
|
break;
|
2016-07-26 15:18:32 +03:00
|
|
|
#if 0
|
|
|
|
case CF_CVAR:
|
|
|
|
printf(" %-20s\tstores in: %s\n", optp->name, optcvar->name);
|
|
|
|
break;
|
|
|
|
case CF_CMD:
|
|
|
|
printf(" %-20s\tparsed by: %d\n", optp->name, (int) optcmd);
|
|
|
|
break;
|
|
|
|
#endif
|
2016-07-26 07:22:47 +07:00
|
|
|
case CF_NONE:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|