2002-04-28 00:56:06 +00:00
|
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
|
* Copyright (C) 2001 Ludvig Strigeus
|
|
|
|
|
* Copyright (C) 2001/2002 The ScummVM project
|
|
|
|
|
*
|
|
|
|
|
* This program 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.
|
|
|
|
|
|
|
|
|
|
* This program 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 this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
*
|
|
|
|
|
* $Header$
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2002-04-27 17:21:38 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "config-file.h"
|
|
|
|
|
#include "scumm.h"
|
|
|
|
|
|
|
|
|
|
#define MAXLINELEN 256
|
|
|
|
|
|
2002-05-02 00:46:12 +00:00
|
|
|
|
#define xfree(p) {if (p) free(p);}
|
|
|
|
|
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
static char *ltrim(char *t)
|
|
|
|
|
{
|
2002-07-07 19:31:51 +00:00
|
|
|
|
for (; *t && (*t == ' '); t++);
|
2002-04-28 00:56:06 +00:00
|
|
|
|
return t;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
static char *rtrim(char *t)
|
|
|
|
|
{
|
|
|
|
|
int l;
|
|
|
|
|
|
|
|
|
|
for (l = strlen(t) - 1; l; l--) {
|
|
|
|
|
if (t[l] == ' ') {
|
|
|
|
|
*t = 0;
|
|
|
|
|
} else {
|
|
|
|
|
return t;
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
return t;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class hashconfig {
|
2002-04-28 00:56:06 +00:00
|
|
|
|
public:
|
2002-07-07 19:31:51 +00:00
|
|
|
|
hashconfig (const char *);
|
|
|
|
|
~hashconfig ();
|
2002-04-28 00:56:06 +00:00
|
|
|
|
bool is_domain(const char *) const;
|
|
|
|
|
const char *get(const char *) const;
|
|
|
|
|
const char *set(const char *, const char *);
|
|
|
|
|
const char *getdomain() const;
|
|
|
|
|
void flush(FILE *) const;
|
|
|
|
|
void rename(const char *);
|
|
|
|
|
void merge(const hashconfig *);
|
|
|
|
|
private:
|
|
|
|
|
char *domain;
|
|
|
|
|
char **keys, **values;
|
|
|
|
|
int nkeys;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
2002-07-16 21:03:14 +00:00
|
|
|
|
hashconfig::hashconfig (const char *dom):domain(dom ? strdup(dom) : 0),
|
2002-04-28 00:56:06 +00:00
|
|
|
|
keys(0), values(0), nkeys(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
hashconfig::~hashconfig () {
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(domain);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
bool hashconfig::is_domain(const char *d) const
|
|
|
|
|
{
|
|
|
|
|
return d && domain && !strcmp(d, domain);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
const char *hashconfig::get(const char *key) const
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
for (i = 0; i < nkeys; i++) {
|
|
|
|
|
if (!strcmp(key, keys[i])) {
|
|
|
|
|
return values[i];
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
const char *hashconfig::set(const char *key, const char *value)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nkeys; i++) {
|
|
|
|
|
if (!strcmp(key, keys[i])) {
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(values[i]);
|
2002-07-16 21:03:14 +00:00
|
|
|
|
return values[i] = value ? strdup(value) : 0;
|
2002-04-28 00:56:06 +00:00
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
|
|
|
|
nkeys++;
|
2002-05-01 17:16:47 +00:00
|
|
|
|
keys = (char **)realloc(keys, nkeys * sizeof(char *));
|
|
|
|
|
values = (char **)realloc(values, nkeys * sizeof(char *));
|
2002-07-16 21:03:14 +00:00
|
|
|
|
keys[nkeys - 1] = strdup(key);
|
|
|
|
|
return values[nkeys - 1] = value ? strdup(value) : 0;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
const char *hashconfig::getdomain() const
|
|
|
|
|
{
|
|
|
|
|
return domain;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
void hashconfig::flush(FILE *cfg_file) const
|
2002-04-28 00:56:06 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!domain)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
fprintf(cfg_file, "[%s]\n", domain);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nkeys; i++) {
|
|
|
|
|
if (values[i]) {
|
|
|
|
|
fprintf(cfg_file, "%s=%s\n", keys[i], values[i]);
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
fprintf(cfg_file, "\n");
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
void hashconfig::rename(const char *d)
|
|
|
|
|
{
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(domain);
|
2002-07-16 21:03:14 +00:00
|
|
|
|
domain = d ? strdup(d) : 0;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
void hashconfig::merge(const hashconfig *h)
|
2002-04-28 00:56:06 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < h->nkeys; i++) {
|
|
|
|
|
set(h->keys[i], h->values[i]);
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//<2F>The config-class itself.
|
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
Config::Config (const char *cfg, const char *d)
|
2002-07-16 21:03:14 +00:00
|
|
|
|
: filename(strdup(cfg)), domain(d ? strdup(d) : 0), hash(0), ndomains(0), willwrite(false)
|
2002-04-28 00:56:06 +00:00
|
|
|
|
{
|
|
|
|
|
FILE *cfg_file;
|
|
|
|
|
char t[MAXLINELEN];
|
|
|
|
|
|
|
|
|
|
if (!(cfg_file = fopen(cfg, "r"))) {
|
|
|
|
|
debug(1, "Unable to open configuration file: %s.\n", filename);
|
|
|
|
|
} else {
|
|
|
|
|
while (!feof(cfg_file)) {
|
|
|
|
|
if (!fgets(t, MAXLINELEN, cfg_file))
|
|
|
|
|
continue;
|
|
|
|
|
if (t[0] != '#') {
|
|
|
|
|
if (t[0] == '[') {
|
|
|
|
|
// It's a new domain which begins here.
|
|
|
|
|
char *p = strchr(t, ']');
|
|
|
|
|
if (!p) {
|
2002-07-07 19:31:51 +00:00
|
|
|
|
debug(1, "Config file buggy: no ] at the end of the domain name.\n");
|
2002-04-28 00:56:06 +00:00
|
|
|
|
} else {
|
|
|
|
|
*p = 0;
|
|
|
|
|
set_domain(t + 1);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// It's a new key in the domain.
|
|
|
|
|
if (!domain) {
|
2002-07-07 19:31:51 +00:00
|
|
|
|
debug(1, "Config file buggy: we have a key without a domain first.\n");
|
2002-04-28 00:56:06 +00:00
|
|
|
|
}
|
|
|
|
|
char *p = strchr(t, '\n');
|
|
|
|
|
if (p)
|
|
|
|
|
*p = 0;
|
|
|
|
|
p = strchr(t, '\r');
|
|
|
|
|
if (p)
|
|
|
|
|
*p = 0;
|
|
|
|
|
|
|
|
|
|
if (!(p = strchr(t, '='))) {
|
|
|
|
|
if (strlen(t))
|
|
|
|
|
debug(1, "Config file buggy: there is junk: %s\n", t);
|
|
|
|
|
} else {
|
|
|
|
|
char *key, *value;
|
|
|
|
|
*p = 0;
|
|
|
|
|
key = ltrim(rtrim(t));
|
|
|
|
|
value = ltrim(p + 1);
|
|
|
|
|
set(key, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
set_domain(d);
|
|
|
|
|
fclose(cfg_file);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
Config::~Config () {
|
2002-04-28 00:56:06 +00:00
|
|
|
|
int i;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(filename);
|
|
|
|
|
xfree(domain);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
delete hash[i];
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(hash);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
const char *Config::get(const char *key, const char *d) const
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!d)
|
|
|
|
|
d = domain;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
if (hash[i]->is_domain(d)) {
|
|
|
|
|
return hash[i]->get(key);
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-27 14:55:40 +00:00
|
|
|
|
const int Config::getInt(const char *key, int def, const char *d) const
|
|
|
|
|
{
|
2002-08-18 23:29:40 +00:00
|
|
|
|
const char *value = get(key, d);
|
|
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
|
return atoi(value);
|
|
|
|
|
return def;
|
|
|
|
|
}
|
2002-07-27 14:55:40 +00:00
|
|
|
|
|
2002-08-18 23:29:40 +00:00
|
|
|
|
const bool Config::getBool(const char *key, bool def, const char *d) const
|
|
|
|
|
{
|
|
|
|
|
const char *value = get(key, d);
|
|
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
|
return !scumm_stricmp(value, "true");
|
2002-07-27 14:55:40 +00:00
|
|
|
|
return def;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
const char *Config::set(const char *key, const char *value, const char *d)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!d)
|
|
|
|
|
d = domain;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
if (hash[i]->is_domain(d)) {
|
|
|
|
|
return hash[i]->set(key, value);
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
|
|
|
|
ndomains++;
|
2002-07-07 19:31:51 +00:00
|
|
|
|
hash = (hashconfig **)realloc(hash, ndomains * sizeof(hashconfig *));
|
|
|
|
|
hash[ndomains - 1] = new hashconfig (d);
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
|
|
|
|
return hash[ndomains - 1]->set(key, value);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
const char *Config::set(const char *key, int value_i, const char *d)
|
|
|
|
|
{
|
|
|
|
|
char value[MAXLINELEN];
|
|
|
|
|
sprintf(value, "%i", value_i);
|
2002-08-18 23:29:40 +00:00
|
|
|
|
return set(key, value, d);
|
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
2002-08-18 23:29:40 +00:00
|
|
|
|
const char *Config::set(const char *key, bool value_b, const char *d)
|
|
|
|
|
{
|
|
|
|
|
const char *value = value_b ? "true" : "false";
|
|
|
|
|
return set(key, value, d);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
void Config::set_domain(const char *d)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(domain);
|
2002-07-16 21:03:14 +00:00
|
|
|
|
domain = d ? strdup(d) : 0;
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
2002-04-27 17:21:38 +00:00
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
2002-04-28 00:56:06 +00:00
|
|
|
|
if (hash[i]->is_domain(domain))
|
|
|
|
|
return;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
ndomains++;
|
2002-07-07 19:31:51 +00:00
|
|
|
|
hash = (hashconfig **)realloc(hash, ndomains * sizeof(hashconfig *));
|
|
|
|
|
hash[ndomains - 1] = new hashconfig (domain);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
void Config::flush() const
|
|
|
|
|
{
|
|
|
|
|
FILE *cfg_file;
|
|
|
|
|
int i;
|
2002-07-07 19:31:51 +00:00
|
|
|
|
|
2002-05-12 21:59:03 +00:00
|
|
|
|
if (!willwrite)
|
2002-07-07 19:31:51 +00:00
|
|
|
|
return;
|
2002-04-28 00:56:06 +00:00
|
|
|
|
|
|
|
|
|
if (!(cfg_file = fopen(filename, "w"))) {
|
|
|
|
|
debug(1, "Unable to write configuration file: %s.\n", filename);
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
hash[i]->flush(cfg_file);
|
|
|
|
|
}
|
|
|
|
|
fclose(cfg_file);
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
2002-04-28 00:56:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Config::rename_domain(const char *d)
|
|
|
|
|
{
|
|
|
|
|
int i, index = -1;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
if (hash[i]->is_domain(d)) {
|
|
|
|
|
index = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
if (hash[i]->is_domain(domain)) {
|
|
|
|
|
if (index >= 0) {
|
|
|
|
|
hash[i]->merge(hash[index]);
|
|
|
|
|
hash[index]->rename(0);
|
|
|
|
|
rename_domain(d);
|
|
|
|
|
} else {
|
|
|
|
|
hash[i]->rename(d);
|
|
|
|
|
set_domain(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
void Config::delete_domain(const char *d)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ndomains; i++) {
|
|
|
|
|
if (hash[i]->is_domain(d)) {
|
|
|
|
|
hash[i]->rename(0);
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 00:56:06 +00:00
|
|
|
|
void Config::change_filename(const char *f)
|
|
|
|
|
{
|
2002-05-02 00:46:12 +00:00
|
|
|
|
xfree(filename);
|
2002-07-16 21:03:14 +00:00
|
|
|
|
filename = f ? strdup(f) : 0;
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
void Config::merge_config(const Config *c)
|
2002-04-28 00:56:06 +00:00
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
bool found;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < c->ndomains; i++) {
|
|
|
|
|
found = false;
|
|
|
|
|
for (j = 0; j < ndomains; j++) {
|
|
|
|
|
if (hash[j]->is_domain(c->hash[i]->getdomain())) {
|
|
|
|
|
hash[j]->merge(c->hash[i]);
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found) {
|
|
|
|
|
ndomains++;
|
2002-07-07 19:31:51 +00:00
|
|
|
|
hash = (hashconfig **)realloc(hash, ndomains * sizeof(hashconfig *));
|
|
|
|
|
hash[ndomains - 1] = new hashconfig (domain);
|
2002-04-28 00:56:06 +00:00
|
|
|
|
hash[ndomains - 1]->merge(c->hash[i]);
|
|
|
|
|
}
|
2002-04-27 17:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-05-12 21:59:03 +00:00
|
|
|
|
|
2002-07-07 19:31:51 +00:00
|
|
|
|
void Config::set_writing(bool w)
|
|
|
|
|
{
|
|
|
|
|
willwrite = w;
|
2002-05-12 21:59:03 +00:00
|
|
|
|
}
|