Squashed 'third_party/boostorg/predef/' content from commit 560ff52

Change-Id: Ib7804ff2c768e0d597993b019146292dfb41e9dc
git-subtree-dir: third_party/boostorg/predef
git-subtree-split: 560ff5298ead78276872604f1ee6523e63a4fa90
diff --git a/tools/check/build.jam b/tools/check/build.jam
new file mode 100644
index 0000000..1ce4f11
--- /dev/null
+++ b/tools/check/build.jam
@@ -0,0 +1,9 @@
+# Copyright Rene Rivera 2015
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+exe predef_check_as_c : predef_check_as_c.c : <include>../include ;
+exe predef_check_as_cpp : predef_check_as_cpp.cpp : <include>../include ;
+exe predef_check_as_objc : predef_check_as_objc.m : <include>../include ;
+exe predef_check_as_objcpp : predef_check_as_objcpp.mm : <include>../include ;
diff --git a/tools/check/predef.jam b/tools/check/predef.jam
new file mode 100644
index 0000000..c037fb4
--- /dev/null
+++ b/tools/check/predef.jam
@@ -0,0 +1,202 @@
+# Copyright Rene Rivera 2015
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Defines rules that provide requirements based on checking
+# conditions using Boost Predef definitions and version numbers.
+
+import modules ;
+import project ;
+import feature ;
+import string ;
+import toolset ;
+import modules ;
+import path ;
+import "class" : new ;
+import regex ;
+
+# Create a project for our targets.
+project.extension predef check ;
+
+# Feature to pass check expressions to check programs.
+feature.feature predef-expression : : free ;
+
+# Checks the expressions and when used evaluates to the true-properties
+# if the expressions are all true. Otherwise evaluates to the
+# false-properties.
+rule check ( expressions + : language ? : true-properties * : false-properties * )
+{
+    # Default to C++ on the check context.
+    language ?= cpp ;
+    
+    local project_target = [ project.target $(__name__) ] ;
+	project.push-current $(project_target) ;
+    local terms ;
+    local result ;
+    for expression in $(expressions)
+    {
+        if $(expression:L) in "and" "or"
+        {
+            terms += $(expression:L) ;
+        }
+        else
+        {
+            # Create the check run if we don't have one yet.
+            local key = [ MD5 "$(language)::$(expression)" ] ;
+            if ! ( $(key) in $(_checks_) )
+            {
+                _checks_ += $(key) ;
+                _message_(/check/predef//predef_check_cc_$(key)) = $(expression) ;
+                check_target $(language) $(key) : [ change_term_to_def $(expression) ] ;
+            }
+            
+            terms += /check/predef//predef_check_cc_$(key) ;
+        }
+    }
+    local instance = [ new check-expression-evaluator
+        $(terms) : $(true-properties) : $(false-properties) ] ;
+    result = <conditional>@$(instance).check ;
+    project.pop-current ;
+    return $(result) ;
+}
+
+# Checks the expressions and when used evaluates to <build>no
+# if the expressions are all false. Otherwise evaluates to the
+# nothing.
+rule require ( expressions + : language ? )
+{
+    return [ check $(expressions) : $(language) : : <build>no ] ;
+}
+
+#############################################################################
+
+.c.ext = c ;
+.cpp.ext = cpp ;
+.objc.ext = m ;
+.objcpp.ext = mm ;
+
+# Check targets. Each needs to be compiled for different languages
+# even though they are all the same source code.
+local rule check_target ( language key : requirements * )
+{
+    # Need to use absolute paths because we don't know the
+    # context of the invocation which affects where the paths
+    # originate from.
+    local predef_jam
+        = [ modules.binding $(__name__) ] ;
+    local source_path
+        = $(predef_jam:D)/predef_check_cc_as_$(language).$(.$(language).ext) ;
+    local include_path
+        = $(predef_jam:D)/../../include ;
+    obj predef_check_cc_$(key)
+        : $(source_path)
+        : <include>$(include_path) $(requirements) ;
+    explicit predef_check_cc_$(key) ;
+    return predef_check_cc_$(key) ;
+}
+
+local rule change_term_to_def ( term )
+{
+    local parts = [ regex.split $(term) " " ] ;
+    if $(parts[3])
+    {
+        local version_number = [ regex.split $(parts[3]) "[.]" ] ;
+        if ! $(version_number[3]) { version_number += "0" ; }
+        if ! $(version_number[2]) { version_number += "0" ; }
+        parts = $(parts[1-2]) BOOST_VERSION_NUMBER($(version_number:J=",")) ;
+    }
+    return <define>CHECK=\"$(parts:J=" ")\" ;
+}
+
+class check-expression-evaluator
+{
+    import configure ;
+    
+    rule __init__ ( expression + : true-properties * : false-properties * )
+    {
+        self.expression = $(expression) ;
+        self.true-properties = $(true-properties) ;
+        self.false-properties = $(false-properties) ;
+    }
+    
+    rule check ( properties * )
+    {
+        local to-eval ;
+        local tokens = "and" "or" ;
+        # Go through the expression and: eval the target values,
+        # and normalize to a full expression.
+        for local term in $(self.expression)
+        {
+            if ! ( $(term:L) in $(tokens) )
+            {
+                # A value is a target reference that will evan to "true"
+                # or "false".
+                if $(to-eval[-1]:L) && ! ( $(to-eval[-1]:L) in $(tokens) )
+                {
+                    # Default to "and" operation.
+                    to-eval += "and" ;
+                }
+                local message = [ modules.peek predef : _message_($(term)) ] ;
+                if [ configure.builds $(term) : $(properties) : $(message) ]
+                {
+                    to-eval += "true" ;
+                }
+                else
+                {
+                    to-eval += "false" ;
+                }
+            }
+            else
+            {
+                to-eval += $(term) ;
+            }
+        }
+        # Eval full the expression.
+        local eval-result = [ eval $(to-eval) ] ;
+        # And resolve true/false properties.
+        if $(eval-result) = "true"
+        {
+            return $(self.true-properties) ;
+        }
+        else
+        {
+            return $(self.false-properties) ;
+        }
+    }
+    
+    rule eval ( e * )
+    {
+        local r ;
+        if $(e[1]) && $(e[2]) && $(e[3])
+        {
+            if $(e[2]) = "and"
+            {
+                if $(e[1]) = "true" && $(e[3]) = "true"
+                {
+                    r = [ eval "true" $(e[4-]) ] ;
+                }
+                else
+                {
+                    r = [ eval "false" $(e[4-]) ] ;
+                }
+            }
+            else if $(e[2]) = "or"
+            {
+                if $(e[1]) = "true" || $(e[3]) = "true"
+                {
+                    r = [ eval "true" $(e[4-]) ] ;
+                }
+                else
+                {
+                    r = [ eval "false" $(e[4-]) ] ;
+                }
+            }
+        }
+        else
+        {
+            r = $(e[1]) ;
+        }
+        return $(r) ;
+    }
+}
diff --git a/tools/check/predef_check.h b/tools/check/predef_check.h
new file mode 100644
index 0000000..a6917c1
--- /dev/null
+++ b/tools/check/predef_check.h
@@ -0,0 +1,98 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/predef/detail/test_def.h>
+
+const char * str_token(const char ** str, const char * space)
+{
+    unsigned span;
+    char * token;
+    for (; **str != 0; *str += 1)
+    {
+        if (0 == strchr(space, **str))
+        {
+            break;
+        }
+    }
+    span = strcspn(*str, space);
+    token = (char *)malloc(span+1);
+    strncpy(token, *str, span);
+    token[span] = 0;
+    for (*str += span; **str != 0; *str += 1)
+    {
+        if (0 == strchr(space, **str))
+        {
+            break;
+        }
+    }
+    return token;
+}
+
+const char * whitespace = " ";
+const char * dot = ".";
+
+int main(int argc, const char ** argv)
+{
+    unsigned x = 0;
+    int argi = 1;
+    create_predef_entries();
+#if 0
+    qsort(generated_predef_info,generated_predef_info_count,
+        sizeof(predef_info),predef_info_compare);
+    for (x = 0; x < generated_predef_info_count; ++x)
+    {
+        printf("%s: %d\n", generated_predef_info[x].name, generated_predef_info[x].value);
+    }
+#endif
+    int result = -1;
+    for (argi = 1; argi < argc; ++argi)
+    {
+        const char * exp = argv[argi];
+        const char * exp_name = str_token(&exp, whitespace);
+        const char * exp_op = str_token(&exp, whitespace);
+        const char * exp_val = str_token(&exp, whitespace);
+        unsigned exp_version = 0;
+        if (*exp_val != 0)
+        {
+            exp = exp_val;
+            const char * exp_val_a = str_token(&exp, dot);
+            const char * exp_val_b = str_token(&exp, dot);
+            const char * exp_val_c = str_token(&exp, dot);
+            exp_version = BOOST_VERSION_NUMBER(atoi(exp_val_a), atoi(exp_val_b),atoi(exp_val_c));
+        }
+        for (x = 0; x < generated_predef_info_count; ++x)
+        {
+            if (*exp_op == 0 &&
+                generated_predef_info[x].value > 0 &&
+                strcmp(exp_name, generated_predef_info[x].name) == 0)
+            {
+                /* Expression of the form "BOOST_x_yy" is true. */
+                result = 0;
+                break;
+            }
+            else if (*exp_op == 0 &&
+                generated_predef_info[x].value == 0 &&
+                strcmp(exp_name, generated_predef_info[x].name) == 0)
+            {
+                /* Expression of the form "BOOST_x_yy" is false. */
+                return argi;
+            }
+            else if (*exp_op != 0 && *exp_val != 0 &&
+                strcmp(exp_name, generated_predef_info[x].name) == 0)
+            {
+                /* Expression of the form "BOOST_x_yy op val". */
+                result = 0;
+                if (0 == strcmp(">",exp_op) && !(generated_predef_info[x].value > exp_version)) return argi;
+                if (0 == strcmp("<",exp_op) && !(generated_predef_info[x].value < exp_version)) return argi;
+                if (0 == strcmp(">=",exp_op) && !(generated_predef_info[x].value >= exp_version)) return argi;
+                if (0 == strcmp("<=",exp_op) && !(generated_predef_info[x].value <= exp_version)) return argi;
+                if (0 == strcmp("==",exp_op) && !(generated_predef_info[x].value == exp_version)) return argi;
+                if (0 == strcmp("!=",exp_op) && !(generated_predef_info[x].value != exp_version)) return argi;
+            }
+        }
+    }
+    return result;
+}
diff --git a/tools/check/predef_check_as_c.c b/tools/check/predef_check_as_c.c
new file mode 100644
index 0000000..352c18b
--- /dev/null
+++ b/tools/check/predef_check_as_c.c
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check.h"
diff --git a/tools/check/predef_check_as_cpp.cpp b/tools/check/predef_check_as_cpp.cpp
new file mode 100644
index 0000000..352c18b
--- /dev/null
+++ b/tools/check/predef_check_as_cpp.cpp
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check.h"
diff --git a/tools/check/predef_check_as_objc.m b/tools/check/predef_check_as_objc.m
new file mode 100644
index 0000000..352c18b
--- /dev/null
+++ b/tools/check/predef_check_as_objc.m
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check.h"
diff --git a/tools/check/predef_check_as_objcpp.mm b/tools/check/predef_check_as_objcpp.mm
new file mode 100644
index 0000000..352c18b
--- /dev/null
+++ b/tools/check/predef_check_as_objcpp.mm
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check.h"
diff --git a/tools/check/predef_check_cc.h b/tools/check/predef_check_cc.h
new file mode 100644
index 0000000..da7609e
--- /dev/null
+++ b/tools/check/predef_check_cc.h
@@ -0,0 +1,19 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/predef.h>
+
+#ifdef CHECK
+#   if ((CHECK) == 0)
+#       error "FAILED"
+#   endif
+#endif
+
+int dummy()
+{
+	static int d = 0;
+	return d++;
+}
diff --git a/tools/check/predef_check_cc_as_c.c b/tools/check/predef_check_cc_as_c.c
new file mode 100644
index 0000000..24fab13
--- /dev/null
+++ b/tools/check/predef_check_cc_as_c.c
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check_cc.h"
diff --git a/tools/check/predef_check_cc_as_cpp.cpp b/tools/check/predef_check_cc_as_cpp.cpp
new file mode 100644
index 0000000..24fab13
--- /dev/null
+++ b/tools/check/predef_check_cc_as_cpp.cpp
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check_cc.h"
diff --git a/tools/check/predef_check_cc_as_objc.m b/tools/check/predef_check_cc_as_objc.m
new file mode 100644
index 0000000..24fab13
--- /dev/null
+++ b/tools/check/predef_check_cc_as_objc.m
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check_cc.h"
diff --git a/tools/check/predef_check_cc_as_objcpp.mm b/tools/check/predef_check_cc_as_objcpp.mm
new file mode 100644
index 0000000..24fab13
--- /dev/null
+++ b/tools/check/predef_check_cc_as_objcpp.mm
@@ -0,0 +1,7 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include "predef_check_cc.h"