summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-01-25 09:43:09 -0800
committerBen Longbons <b.r.longbons@gmail.com>2014-01-25 10:14:44 -0800
commit34f0540da418b01dd4d49f6ecf72569d3cfecfdf (patch)
treebf7c4623b0d794e4db8c72b0906bb40807d62ba8 /src/common
parent9a4c3a44476f3306a8deed8a836e8fbc25ceb55f (diff)
downloadtmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.tar.gz
tmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.tar.bz2
tmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.tar.xz
tmwa-34f0540da418b01dd4d49f6ecf72569d3cfecfdf.zip
Implement unified config parsing (mostly)
Diffstat (limited to 'src/common')
-rw-r--r--src/common/config_parse.cpp154
-rw-r--r--src/common/config_parse.hpp36
-rw-r--r--src/common/core.cpp18
-rw-r--r--src/common/core.hpp5
-rw-r--r--src/common/utils.cpp22
-rw-r--r--src/common/utils.hpp2
-rw-r--r--src/common/version.cpp18
-rw-r--r--src/common/version.hpp35
8 files changed, 258 insertions, 32 deletions
diff --git a/src/common/config_parse.cpp b/src/common/config_parse.cpp
new file mode 100644
index 0000000..d677d8e
--- /dev/null
+++ b/src/common/config_parse.cpp
@@ -0,0 +1,154 @@
+#include "config_parse.hpp"
+// config_parse.hpp - Framework for per-server config parsers.
+//
+// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#include "../strings/xstring.hpp"
+#include "../strings/zstring.hpp"
+
+#include "../io/cxxstdio.hpp"
+#include "../io/line.hpp"
+
+#include "version.hpp"
+
+#include "../poison.hpp"
+
+bool is_comment(XString line)
+{
+ return not line or line.startswith("//");
+}
+
+template<class ZS>
+inline
+bool config_split_impl(ZS line, XString *key, ZS *value)
+{
+ // unconditionally fail if line contains control characters
+ if (std::find_if(line.begin(), line.end(),
+ [](unsigned char c) { return c < ' '; }
+ ) != line.end())
+ return false;
+ // try to find a colon, fail if not found
+ typename ZS::iterator colon = std::find(line.begin(), line.end(), ':');
+ if (colon == line.end())
+ return false;
+
+ *key = line.xislice_h(colon).strip();
+ // move past the colon and any spaces
+ ++colon;
+ *value = line.xislice_t(colon).lstrip();
+ return true;
+}
+
+// eventually this should go away
+bool config_split(ZString line, XString *key, ZString *value)
+{
+ return config_split_impl(line, key, value);
+}
+// and use this instead
+bool config_split(XString line, XString *key, XString *value)
+{
+ return config_split_impl(line, key, value);
+}
+
+/// Master config parser. This handles 'import' and 'version-ge' etc.
+/// Then it defers to the inferior parser for a line it does not understand.
+bool load_config_file(ZString filename, ConfigItemParser slave)
+{
+ io::LineReader in(filename);
+ if (!in.is_open())
+ {
+ PRINTF("Unable to open file: %s\n", filename);
+ return false;
+ }
+ io::Line line;
+ bool rv = true;
+ while (in.read_line(line))
+ {
+ if (is_comment(line.text))
+ continue;
+ XString key;
+ ZString value;
+ if (!config_split(line.text, &key, &value))
+ {
+ line.error("Bad config line");
+ rv = false;
+ continue;
+ }
+ if (key == "import")
+ {
+ rv &= load_config_file(value, slave);
+ continue;
+ }
+ else if (key == "version-lt")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION < vers)
+ continue;
+ break;
+ }
+ else if (key == "version-le")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION <= vers)
+ continue;
+ break;
+ }
+ else if (key == "version-gt")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION > vers)
+ continue;
+ break;
+ }
+ else if (key == "version-ge")
+ {
+ Version vers;
+ if (!extract(value, &vers))
+ {
+ rv = false;
+ continue;
+ }
+ if (CURRENT_VERSION >= vers)
+ continue;
+ break;
+ }
+ else if (!slave(key, value))
+ {
+ line.error("Bad config key or value");
+ rv = false;
+ continue;
+ }
+ // nothing to see here, move along
+ }
+ return rv;
+}
diff --git a/src/common/config_parse.hpp b/src/common/config_parse.hpp
new file mode 100644
index 0000000..6a55174
--- /dev/null
+++ b/src/common/config_parse.hpp
@@ -0,0 +1,36 @@
+#ifndef TMWA_COMMON_CONFIG_PARSE_HPP
+#define TMWA_COMMON_CONFIG_PARSE_HPP
+// config_parse.hpp - Framework for per-server config parsers.
+//
+// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# include "../sanity.hpp"
+
+# include "../strings/fwd.hpp"
+
+typedef bool (*ConfigItemParser)(XString key, ZString value);
+
+bool is_comment(XString line);
+bool config_split(ZString line, XString *key, ZString *value);
+bool config_split(XString line, XString *key, XString *value);
+
+/// Master config parser. This handles 'import' and 'version-ge' etc.
+/// Then it defers to the inferior parser for a line it does not understand.
+bool load_config_file(ZString filename, ConfigItemParser slave);
+
+#endif // TMWA_COMMON_CONFIG_PARSE_HPP
diff --git a/src/common/core.cpp b/src/common/core.cpp
index 727babd..fe2f660 100644
--- a/src/common/core.cpp
+++ b/src/common/core.cpp
@@ -10,6 +10,8 @@
#include "../strings/zstring.hpp"
+#include "../io/cxxstdio.hpp"
+
#include "random.hpp"
#include "socket.hpp"
#include "timer.hpp"
@@ -46,12 +48,15 @@ sigfunc compat_signal(int signo, sigfunc func)
return oact.sa_handler;
}
+volatile
+bool runflag = true;
+
static
void chld_proc(int)
{
wait(NULL);
}
-static __attribute__((noreturn))
+static
void sig_proc(int)
{
for (int i = 1; i < 31; ++i)
@@ -59,12 +64,9 @@ void sig_proc(int)
#pragma GCC diagnostic ignored "-Wold-style-cast"
compat_signal(i, SIG_IGN);
#pragma GCC diagnostic pop
- term_func();
- _exit(0);
+ runflag = false;
}
-bool runflag = true;
-
/*
Note about fatal signals:
@@ -83,6 +85,12 @@ int main(int argc, char **argv)
for (int i = 0; i < argc; ++i)
args[i] = ZString(strings::really_construct_from_a_pointer, argv[i], nullptr);
do_init(argc, args);
+
+ if (!runflag)
+ {
+ PRINTF("Fatal error during startup; exiting\n");
+ return 1;
+ }
// set up exit handlers *after* the initialization has happened.
// This is because term_func is likely to depend on successful init.
diff --git a/src/common/core.hpp b/src/common/core.hpp
index f93f5a1..8141e9c 100644
--- a/src/common/core.hpp
+++ b/src/common/core.hpp
@@ -8,9 +8,8 @@
/// core.c contains a server-independent main() function
/// and then runs a do_sendrecv loop
-/// When this is cleared, the server exits gracefully
-/// only used by map server's GM command: @mapexit
-extern bool runflag;
+/// When this is cleared, the server exits gracefully.
+extern volatile bool runflag;
/// This is an external function defined by each server
/// This function must register stuff for the parse loop
diff --git a/src/common/utils.cpp b/src/common/utils.cpp
index 7f9a7ee..3a26e6d 100644
--- a/src/common/utils.cpp
+++ b/src/common/utils.cpp
@@ -65,28 +65,6 @@ int config_switch(ZString str)
abort();
}
-bool split_key_value(ZString line, XString *w1, ZString *w2)
-{
- if (line.startswith("//"))
- return false;
- if (!line)
- return false;
-
- if (std::find_if(line.begin(), line.end(),
- [](unsigned char c) { return c < ' '; }
- ) != line.end())
- return false;
- ZString::iterator colon = std::find(line.begin(), line.end(), ':');
- if (colon == line.end())
- return false;
- *w1 = line.xislice_h(colon);
- ++colon;
- while (std::isspace(*colon))
- ++colon;
- *w2 = line.xislice_t(colon);
- return true;
-}
-
static_assert(sizeof(timestamp_seconds_buffer) == 20, "seconds buffer");
static_assert(sizeof(timestamp_milliseconds_buffer) == 24, "millis buffer");
diff --git a/src/common/utils.hpp b/src/common/utils.hpp
index f975e34..161cbd4 100644
--- a/src/common/utils.hpp
+++ b/src/common/utils.hpp
@@ -29,8 +29,6 @@ struct is_trivially_copyable
bool e_mail_check(XString email);
int config_switch (ZString str);
-bool split_key_value(ZString line, XString *w1, ZString *w2);
-
inline
void really_memcpy(uint8_t *dest, const uint8_t *src, size_t n)
{
diff --git a/src/common/version.cpp b/src/common/version.cpp
index 1ee4071..811ffdf 100644
--- a/src/common/version.cpp
+++ b/src/common/version.cpp
@@ -2,6 +2,18 @@
#include "../conf/version.hpp"
+#include "../strings/xstring.hpp"
+
+#include "extract.hpp"
+
+Version CURRENT_VERSION =
+{
+ VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH,
+ VERSION_DEVEL,
+
+ 0, 0,
+ VENDOR_VERSION,
+};
Version CURRENT_LOGIN_SERVER_VERSION =
{
VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH,
@@ -33,3 +45,9 @@ Version CURRENT_MAP_SERVER_VERSION =
const char CURRENT_VERSION_STRING[] = "TMWA "
S(VERSION_MAJOR) "." S(VERSION_MINOR) "." S(VERSION_PATCH)
" dev" S(VERSION_DEVEL) " (" VENDOR " " S(VENDOR_VERSION) ")";
+
+bool extract(XString str, Version *vers)
+{
+ *vers = {};
+ return extract(str, record<'.'>(&vers->major, &vers->minor, &vers->patch));
+}
diff --git a/src/common/version.hpp b/src/common/version.hpp
index 677806b..a2c4e05 100644
--- a/src/common/version.hpp
+++ b/src/common/version.hpp
@@ -3,6 +3,8 @@
# include <cstdint>
+# include "../strings/fwd.hpp"
+
// TODO make these bitwise enums
# define TMWA_FLAG_REGISTRATION 0x01
@@ -25,10 +27,43 @@ struct Version
};
static_assert(sizeof(Version) == 8, "this is sent over the network, can't change");
+extern Version CURRENT_VERSION;
+
extern Version CURRENT_LOGIN_SERVER_VERSION;
extern Version CURRENT_CHAR_SERVER_VERSION;
extern Version CURRENT_MAP_SERVER_VERSION;
extern const char CURRENT_VERSION_STRING[];
+bool extract(XString str, Version *vers);
+
+constexpr
+bool operator < (Version l, Version r)
+{
+ return (l.major < r.major
+ || (l.major == r.major
+ && (l.minor < r.minor
+ || (l.minor == r.minor
+ && (l.patch < r.patch
+ || (l.patch == r.patch
+ && (l.devel < r.devel
+ || (l.devel == r.devel
+ && l.vend < r.vend))))))));
+}
+constexpr
+bool operator > (Version l, Version r)
+{
+ return r < l;
+}
+constexpr
+bool operator <= (Version l, Version r)
+{
+ return !(r < l);
+}
+constexpr
+bool operator >= (Version l, Version r)
+{
+ return !(l < r);
+}
+
#endif // TMWA_COMMON_VERSION_HPP