Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/config/tools/generate.cpp @ 25

Last change on this file since 25 was 12, checked in by landauf, 18 years ago

added boost

File size: 8.4 KB
RevLine 
[12]1//  (C) Copyright John Maddock 2004.
2//  Use, modification and distribution are subject to the
3//  Boost Software License, Version 1.0. (See accompanying file
4//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6//
7// This progam scans for *.ipp files in the libs/config/test
8// directory and then generates the *.cpp test files from them
9// along with config_test.cpp and a Jamfile.
10//
11
12#include <boost/regex.hpp>
13#include <boost/filesystem/path.hpp>
14#include <boost/filesystem/operations.hpp>
15#include <boost/filesystem/fstream.hpp>
16#include <boost/test/included/prg_exec_monitor.hpp>
17#include <iostream>
18#include <sstream>
19#include <string>
20#include <ctime>
21
22namespace fs = boost::filesystem;
23
24fs::path config_path;
25
26std::string copyright(
27"//  Copyright John Maddock 2002-4.\n"
28"//  Use, modification and distribution are subject to the \n"
29"//  Boost Software License, Version 1.0. (See accompanying file \n"
30"//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
31"\n"
32"//  See http://www.boost.org/libs/config for the most recent version.");
33
34std::stringstream config_test1;
35std::stringstream config_test1a;
36std::stringstream config_test2;
37std::stringstream jamfile;
38
39void write_config_test()
40{
41   fs::ofstream ofs(config_path / "config_test.cpp");
42   time_t t = std::time(0);
43   ofs << "//  This file was automatically generated on " << std::ctime(&t);
44   ofs << "//  by libs/config/tools/generate.cpp\n" << copyright << std::endl;
45   ofs << "// Test file for config setup\n"
46      "// This file should compile, if it does not then\n"
47      "// one or more macros need to be defined.\n"
48      "// see boost_*.ipp for more details\n\n"
49      "// Do not edit this file, it was generated automatically by\n\n"
50      "#include <boost/config.hpp>\n#include <iostream>\n#include \"test.hpp\"\n\n"
51      "int error_count = 0;\n\n";
52   ofs << config_test1.str() << std::endl;
53   ofs << config_test1a.str() << std::endl;
54   ofs << "int main( int, char *[] )\n{\n" << config_test2.str() << "   return error_count;\n}\n\n";
55}
56
57void write_jamfile()
58{
59   fs::ofstream ofs(config_path / "Jamfile");
60   time_t t = std::time(0);
61   ofs << "#\n# Regression test Jamfile for boost configuration setup.\n# *** DO NOT EDIT THIS FILE BY HAND ***\n"
62      "# This file was automatically generated on " << std::ctime(&t);
63   ofs << "#  by libs/config/tools/generate.cpp\n"
64      "# Copyright John Maddock.\n"
65      "#\n# If you need to alter build preferences then set them in\n"
66      "# the template defined in options.jam.\n#\n"
67      "subproject libs/config/test ;\n"
68      "# bring in the rules for testing\n"
69      "import testing ./options ;\n\n"
70      "run config_info.cpp <template>config_options ;\n"
71      "run config_test.cpp <template>config_options ;\n"
72      "run limits_test.cpp <template>config_test_options ;\n"
73      "run abi/abi_test.cpp abi/main.cpp <template>config_options ;\n\n";
74   ofs << jamfile.str() << std::endl;
75}
76
77void write_test_file(const fs::path& file, 
78                     const std::string& macro_name, 
79                     const std::string& namespace_name, 
80                     const std::string& header_file,
81                     bool positive_test, 
82                     bool expect_success)
83{
84   if(!fs::exists(file))
85   {
86      std::cout << "Writing test file " << file.native_directory_string() << std::endl;
87
88      fs::ofstream ofs(file);
89      std::time_t t = std::time(0);
90      ofs << "//  This file was automatically generated on " << std::ctime(&t);
91      ofs << "//  by libs/config/tools/generate.cpp\n" << copyright << std::endl;
92      ofs << "\n// Test file for macro " << macro_name << std::endl;
93
94      if(expect_success)
95      {
96         ofs << "// This file should compile, if it does not then\n"
97            "// " << macro_name << " should ";
98         if(positive_test)
99            ofs << "not ";
100         ofs << "be defined.\n";
101      }
102      else
103      {
104         ofs << "// This file should not compile, if it does then\n"
105            "// " << macro_name << " should ";
106         if(!positive_test)
107            ofs << "not ";
108         ofs << "be defined.\n";
109      }
110      ofs << "// See file " << header_file << " for details\n\n";
111
112      ofs << "// Must not have BOOST_ASSERT_CONFIG set; it defeats\n"
113         "// the objective of this file:\n"
114         "#ifdef BOOST_ASSERT_CONFIG\n"
115         "#  undef BOOST_ASSERT_CONFIG\n"
116         "#endif\n\n";
117
118      ofs << "#include <boost/config.hpp>\n"
119         "#include \"test.hpp\"\n\n"
120         "#if";
121      if(positive_test != expect_success)
122         ofs << "n";
123      ofs << "def " << macro_name << 
124         "\n#include \"" << header_file << 
125         "\"\n#else\n";
126      if(expect_success)
127         ofs << "namespace " << namespace_name << " = empty_boost;\n";
128      else
129         ofs << "#error \"this file should not compile\"\n";
130      ofs << "#endif\n\n";
131
132      ofs << "int main( int, char *[] )\n{\n   return " << namespace_name << "::test();\n}\n\n"; 
133   }
134   else
135   {
136      std::cout << "Skipping existing test file " << file.native_directory_string() << std::endl;
137   }
138}
139
140void process_ipp_file(const fs::path& file, bool positive_test)
141{
142   std::cout << "Info: Scanning file: " << file.native_directory_string() << std::endl;
143
144   // our variables:
145   std::string file_text;
146   std::string macro_name;
147   std::string namespace_name;
148   fs::path positive_file;
149   fs::path negative_file;
150
151   // load the file into memory so we can scan it:
152   fs::ifstream ifs(file);
153   std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(), std::back_inserter(file_text));
154   ifs.close();
155   // scan for the macro name:
156   boost::regex macro_regex("//\\s*MACRO\\s*:\\s*(\\w+)");
157   boost::smatch macro_match;
158   if(boost::regex_search(file_text, macro_match, macro_regex))
159   {
160      macro_name = macro_match[1];
161      namespace_name = boost::regex_replace(file_text, macro_regex, "\\L$1", boost::format_first_only | boost::format_no_copy);
162   }
163   if(macro_name.empty())
164   {
165      std::cout << "Error: no macro definition found in " << file.native_directory_string();
166   }
167   else
168   {
169      std::cout << "Info: Macroname: " << macro_name << std::endl;
170   }
171
172   // get the output filesnames:
173   boost::regex file_regex("boost_([^.]+)\\.ipp");
174   positive_file = file.branch_path() / boost::regex_replace(file.leaf(), file_regex, "$1_pass.cpp");
175   negative_file = file.branch_path() / boost::regex_replace(file.leaf(), file_regex, "$1_fail.cpp");
176   write_test_file(positive_file, macro_name, namespace_name, file.leaf(), positive_test, true);
177   write_test_file(negative_file, macro_name, namespace_name, file.leaf(), positive_test, false);
178   
179   // always create config_test data,
180   // positive and negative tests go to separate streams, because for some
181   // reason some compilers choke unless we put them in a particular order...
182   std::ostream* pout = positive_test ? &config_test1a : &config_test1;
183   *pout << "#if";
184   if(!positive_test)
185      *pout << "n";
186   *pout << "def " << macro_name
187      << "\n#include \"" << file.leaf() << "\"\n#else\nnamespace "
188      << namespace_name << " = empty_boost;\n#endif\n";
189
190   config_test2 << "   if(0 != " << namespace_name << "::test())\n"
191      "   {\n"
192      "      std::cerr << \"Failed test for " << macro_name << " at: \" << __FILE__ << \":\" << __LINE__ << std::endl;\n"
193      "      ++error_count;\n"
194      "   }\n";
195
196   // always generate the jamfile data:
197   jamfile << "test-suite \"" << macro_name << "\" : \n"
198      "[ run " << positive_file.leaf() << " <template>config_options ]\n"
199      "[ compile-fail " << negative_file.leaf() << " <template>config_options ] ;\n";
200
201}
202
203int cpp_main(int argc, char* argv[])
204{
205   //
206   // get the boost path to begin with:
207   //
208   if(argc > 1)
209   {
210      fs::path p(argv[1], fs::native);
211      config_path = p / "libs" / "config" / "test" ;
212   }
213   else
214   {
215      // try __FILE__:
216      fs::path p(__FILE__, fs::native);
217      config_path = p.branch_path().branch_path() / "test";
218   }
219   std::cout << "Info: Boost.Config test path set as: " << config_path.native_directory_string() << std::endl;
220
221   // enumerate *.ipp files:
222   boost::regex ipp_mask("boost_(?:(has)|no).*\\.ipp");
223   boost::smatch ipp_match;
224   fs::directory_iterator i(config_path), j;
225   while(i != j)
226   {
227      if(boost::regex_match(i->leaf(), ipp_match, ipp_mask))
228      {
229         process_ipp_file(*i, ipp_match[1].matched);
230      }
231      ++i;
232   }
233   write_config_test();
234   write_jamfile();
235   return 0;
236}
Note: See TracBrowser for help on using the repository browser.