From 4c65e455980be5066c4e4fef42da71dc10a1a0e2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 10 Nov 2012 16:31:05 -0700 Subject: [PATCH] Correct signing and sizing of integer literals #77 --- CMakeLists.txt | 4 + .../chaiscript/language/chaiscript_eval.hpp | 4 +- .../chaiscript/language/chaiscript_parser.hpp | 53 +++++++++++ unittests/integer_literal_test.cpp | 90 +++++++++++++++++++ 4 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 unittests/integer_literal_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 69aa2d0..11960e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,6 +208,10 @@ if(BUILD_TESTING) target_link_libraries(c_linkage_test ${LIBS}) add_test(NAME C_Linkage_Test COMMAND c_linkage_test) + add_executable(integer_literal_test unittests/integer_literal_test.cpp) + target_link_libraries(integer_literal_test ${LIBS}) + add_test(NAME Integer_Literal_Test COMMAND integer_literal_test) + if (MULTITHREAD_SUPPORT_ENABLED) add_executable(multithreaded_test unittests/multithreaded_test.cpp) target_link_libraries(multithreaded_test ${LIBS}) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index c11b708..b2c684a 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -103,7 +103,7 @@ namespace chaiscript Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(int(atoi(t_ast_node_text.c_str())))) { } - Int_AST_Node(const std::string &t_ast_node_text = "", const Boxed_Value &t_bv = const_var(0), int t_id = AST_Node_Type::Int, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + Int_AST_Node(const std::string &t_ast_node_text, const Boxed_Value &t_bv, int t_id = AST_Node_Type::Int, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(t_bv) { } virtual ~Int_AST_Node() {} @@ -121,7 +121,7 @@ namespace chaiscript Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(double(atof(t_ast_node_text.c_str())))) { } - Float_AST_Node(const std::string &t_ast_node_text = "", const Boxed_Value &t_bv = const_var(0), int t_id = AST_Node_Type::Float, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + Float_AST_Node(const std::string &t_ast_node_text, const Boxed_Value &t_bv, int t_id = AST_Node_Type::Float, const boost::shared_ptr &t_fname=boost::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(t_bv) { } virtual ~Float_AST_Node() {} diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index fee0717..0c7e882 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -490,6 +490,8 @@ namespace chaiscript } } + + template Boxed_Value buildInt(const IntType &t_type, const std::string &t_val) { @@ -521,6 +523,57 @@ namespace chaiscript std::stringstream ss(t_val.substr(0, i)); ss >> t_type; + std::stringstream testu(t_val.substr(0, i)); + boost::uint64_t u; + testu >> t_type >> u; + + bool unsignedrequired = false; + size_t size = sizeof(int) * 8; + + if ((u >> (sizeof(int) * 8)) > 0) + { + //requires something bigger than int + long_ = true; + } + + BOOST_ASSERT(sizeof(long) == sizeof(boost::uint64_t) || sizeof(long) * 2 == sizeof(boost::uint64_t)); + + if ((sizeof(long) < sizeof(boost::uint64_t)) + && (u >> ((sizeof(uint64_t) - sizeof(long)) * 8)) > 0) + { + //requires something bigger than long + longlong_ = true; + } + + if (longlong_) + { + size = sizeof(boost::int64_t) * 8; + } else if (long_) { + size = sizeof(long) * 8; + } + + if ( (u >> (size - 1)) > 0) + { + unsignedrequired = true; + } + + if (unsignedrequired && !unsigned_) + { + if (t_type == std::hex || t_type == std::oct) + { + // with hex and octal we are happy to just make it unsigned + unsigned_ = true; + } else { + // with decimal we must bump it up to the next size + if (long_) + { + longlong_ = true; + } else if (!long_ && !longlong_) { + long_ = true; + } + } + } + if (unsigned_) { if (longlong_) diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp new file mode 100644 index 0000000..85efe06 --- /dev/null +++ b/unittests/integer_literal_test.cpp @@ -0,0 +1,90 @@ +// Tests to make sure that the order in which function dispatches occur is correct + +#include + +#define TEST_LITERAL(v) test_literal(v, #v) + +template +bool test_literal(T val, const std::string &str) +{ + chaiscript::ChaiScript chai; + T val2 = chai.eval(str); + std::cout << "Comparing : " << val << " " << val2 << std::endl; + return val == val2; +} + +int main() +{ + if( TEST_LITERAL(0xF) + && TEST_LITERAL(0xFF) + && TEST_LITERAL(0xFFF) + && TEST_LITERAL(0xFFFF) + && TEST_LITERAL(0xFFFFF) + && TEST_LITERAL(0xFFFFFF) + && TEST_LITERAL(0xFFFFFFF) + && TEST_LITERAL(0xFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFFFFF) + + + && TEST_LITERAL(01) + && TEST_LITERAL(017) + && TEST_LITERAL(0177) + && TEST_LITERAL(01777) + && TEST_LITERAL(017777) + && TEST_LITERAL(0177777) + && TEST_LITERAL(01777777) + && TEST_LITERAL(017777777) + && TEST_LITERAL(0177777777) + && TEST_LITERAL(01777777777) + && TEST_LITERAL(017777777777) + && TEST_LITERAL(0177777777777) + && TEST_LITERAL(01777777777777) + && TEST_LITERAL(017777777777777) + && TEST_LITERAL(0177777777777777) + && TEST_LITERAL(01777777777777777) + && TEST_LITERAL(017777777777777777) + && TEST_LITERAL(0177777777777777777) + && TEST_LITERAL(01777777777777777777) + && TEST_LITERAL(017777777777777777777) + && TEST_LITERAL(0177777777777777777777) + && TEST_LITERAL(01777777777777777777777) + + && TEST_LITERAL(1) + && TEST_LITERAL(17) + && TEST_LITERAL(177) + && TEST_LITERAL(1777) + && TEST_LITERAL(17777) + && TEST_LITERAL(177777) + && TEST_LITERAL(1777777) + && TEST_LITERAL(17777777) + && TEST_LITERAL(177777777) + && TEST_LITERAL(1777777777) + && TEST_LITERAL(17777777777) + && TEST_LITERAL(177777777777) + && TEST_LITERAL(1777777777777) + && TEST_LITERAL(17777777777777) + && TEST_LITERAL(177777777777777) + && TEST_LITERAL(1777777777777777) + && TEST_LITERAL(17777777777777777) + && TEST_LITERAL(177777777777777777) + && TEST_LITERAL(1777777777777777777) + +) + { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } + + + + + +}