Author: shadowmaster
Date: Wed Mar 23 04:20:39 2011
New Revision: 48984

URL: http://svn.gna.org/viewcvs/wesnoth?rev=48984&view=rev
Log:
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 r48971.

Modified:
    trunk/changelog
    trunk/data/tools/wmllint
    trunk/src/serialization/preprocessor.cpp

Modified: trunk/changelog
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/changelog?rev=48984&r1=48983&r2=48984&view=diff
==============================================================================
--- trunk/changelog (original)
+++ trunk/changelog Wed Mar 23 04:20:39 2011
@@ -65,6 +65,8 @@
    * 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

Modified: trunk/data/tools/wmllint
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/data/tools/wmllint?rev=48984&r1=48983&r2=48984&view=diff
==============================================================================
--- trunk/data/tools/wmllint (original)
+++ trunk/data/tools/wmllint Wed Mar 23 04:20:39 2011
@@ -1020,10 +1020,10 @@
     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"):

Modified: trunk/src/serialization/preprocessor.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/serialization/preprocessor.cpp?rev=48984&r1=48983&r2=48984&view=diff
==============================================================================
--- trunk/src/serialization/preprocessor.cpp (original)
+++ trunk/src/serialization/preprocessor.cpp Wed Mar 23 04:20:39 2011
@@ -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>
 
@@ -51,6 +53,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){
@@ -103,6 +115,47 @@
                res += ' ';
        }
        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 {
@@ -872,6 +925,36 @@
                        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();


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to