WML preprocessor: implement #ifver, #ifnver MACRO <op> <version>
Currently, the specified MACRO is not expanded further, so if it contains code inclusions with {} those will not be resolved. Furthermore, MACRO should not take arguments. The whole idea is that it should be defined to simple text such as "1.7.5" like Wesnoth does for WESNOTH_VERSION since 2011-03-22T06:40:15Z!shadowm@wesnoth.org.
This commit is contained in:
parent
5341c62319
commit
e0b0a18104
3 changed files with 87 additions and 2 deletions
|
@ -65,6 +65,8 @@ Version 1.9.4+svn:
|
|||
* Added TAKE_IT_STRING and LEAVE_IT_STRING arguments to PICKUPPABLE_ITEM
|
||||
* Added an engine-defined WESNOTH_VERSION macro that expands to the Wesnoth engine
|
||||
version string.
|
||||
* New #ifver/#ifnver preprocessor macro to compare Wesnoth or UMC-defined version
|
||||
numbers as in '#ifver WESNOTH_VERSION >= 1.9.5'.
|
||||
* The tags [remove_shroud] and [place_shroud] now take comma-separated lists of sides.
|
||||
They default to affecting all sides now if no side is set.
|
||||
* The [gold] tag now takes a comma-separated list of sides, and defaults to
|
||||
|
|
|
@ -1020,10 +1020,10 @@ def global_sanity_check(filename, lines):
|
|||
recruitment_pattern = {}
|
||||
ifdef_stack = [None]
|
||||
for i in range(len(lines)):
|
||||
if lines[i].startswith("#ifdef") or lines[i].startswith("#ifhave"):
|
||||
if lines[i].startswith("#ifdef") or lines[i].startswith("#ifhave") or lines[i].startswith("#ifver"):
|
||||
ifdef_stack.append(lines[i].strip().split()[1])
|
||||
continue
|
||||
if lines[i].startswith("#ifndef") or lines[i].startswith("#ifnhave"):
|
||||
if lines[i].startswith("#ifndef") or lines[i].startswith("#ifnhave") or lines[i].startswith("#ifnver"):
|
||||
ifdef_stack.append("!" + lines[i].strip().split()[1])
|
||||
continue
|
||||
if lines[i].startswith("#else"):
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "config.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "foreach.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "log.hpp"
|
||||
#include "wesconfig.h"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
|
@ -31,6 +32,7 @@
|
|||
#include "serialization/parser.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "util.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
@ -52,6 +54,16 @@ static t_file_number_map file_number_map;
|
|||
|
||||
static bool encode_filename = true;
|
||||
|
||||
enum PREPROCESSOR_VERSION_OP {
|
||||
OP_INVALID,
|
||||
OP_EQUAL,
|
||||
OP_NOT_EQUAL,
|
||||
OP_LESS,
|
||||
OP_LESS_OR_EQUAL,
|
||||
OP_GREATER,
|
||||
OP_GREATER_OR_EQUAL,
|
||||
};
|
||||
|
||||
// get filename associated to this code
|
||||
static std::string get_filename(const std::string& file_code){
|
||||
if(!encode_filename)
|
||||
|
@ -105,6 +117,47 @@ static std::string get_location(const std::string& loc)
|
|||
return res;
|
||||
}
|
||||
|
||||
static PREPROCESSOR_VERSION_OP parse_version_op(const std::string& op_str)
|
||||
{
|
||||
if(op_str == "==") {
|
||||
return OP_EQUAL;
|
||||
} else if(op_str == "!=") {
|
||||
return OP_NOT_EQUAL;
|
||||
} else if(op_str == "<") {
|
||||
return OP_LESS;
|
||||
} else if(op_str == "<=") {
|
||||
return OP_LESS_OR_EQUAL;
|
||||
} else if(op_str == ">") {
|
||||
return OP_GREATER;
|
||||
} else if(op_str == ">=") {
|
||||
return OP_GREATER_OR_EQUAL;
|
||||
}
|
||||
|
||||
return OP_INVALID;
|
||||
}
|
||||
|
||||
static bool do_version_check(const version_info& a, PREPROCESSOR_VERSION_OP op, const version_info& b)
|
||||
{
|
||||
switch(op) {
|
||||
case OP_EQUAL:
|
||||
return a == b;
|
||||
case OP_NOT_EQUAL:
|
||||
return a != b;
|
||||
case OP_LESS:
|
||||
return a < b;
|
||||
case OP_LESS_OR_EQUAL:
|
||||
return a <= b;
|
||||
case OP_GREATER:
|
||||
return a > b;
|
||||
case OP_GREATER_OR_EQUAL:
|
||||
return a >= b;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool preproc_define::operator==(preproc_define const &v) const {
|
||||
return value == v.value && arguments == v.arguments;
|
||||
}
|
||||
|
@ -872,6 +925,36 @@ bool preprocessor_data::get_chunk()
|
|||
DBG_CF << "testing for file or directory " << symbol << ": "
|
||||
<< (found ? "found" : "not found") << '\n';
|
||||
conditional_skip(found);
|
||||
} else if (command == "ifver" || command == "ifnver") {
|
||||
skip_spaces();
|
||||
std::string const& vsymstr = read_word();
|
||||
skip_spaces();
|
||||
std::string const& vopstr = read_word();
|
||||
skip_spaces();
|
||||
std::string const& vverstr = read_word();
|
||||
|
||||
const PREPROCESSOR_VERSION_OP vop = parse_version_op(vopstr);
|
||||
|
||||
if(vop == OP_INVALID) {
|
||||
target_.error("Invalid #ifver/#ifnver operator", linenum_);
|
||||
} else if(target_.defines_->count(vsymstr) != 0) {
|
||||
preproc_define const& sym = (*target_.defines_)[vsymstr];
|
||||
|
||||
if(!sym.arguments.empty()) {
|
||||
target_.error("First argument macro in #ifver/#ifnver should not require arguments", linenum_);
|
||||
}
|
||||
|
||||
version_info const version1(sym.value);
|
||||
version_info const version2(vverstr);
|
||||
|
||||
const bool found = do_version_check(version1, vop, version2);
|
||||
DBG_CF << "testing version '" << version1.str() << "' against '" << version2.str() << "' (" << vopstr << "): "
|
||||
<< (found ? "match" : "no match") << '\n';
|
||||
|
||||
conditional_skip(command == "ifver" ? !found : found);
|
||||
} else {
|
||||
target_.error("Undefined macro in #ifver/#ifnver first argument", linenum_);
|
||||
}
|
||||
} else if (command == "else") {
|
||||
if (token.type == token_desc::SKIP_ELSE) {
|
||||
pop_token();
|
||||
|
|
Loading…
Add table
Reference in a new issue