Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/config/tools/generate.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 11.1 KB
Line 
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 <set>
21#include <ctime>
22
23namespace fs = boost::filesystem;
24
25fs::path config_path;
26
27std::string copyright(
28"//  Copyright John Maddock 2002-4.\n"
29"//  Use, modification and distribution are subject to the \n"
30"//  Boost Software License, Version 1.0. (See accompanying file \n"
31"//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
32"\n"
33"//  See http://www.boost.org/libs/config for the most recent version.");
34
35std::stringstream config_test1;
36std::stringstream config_test1a;
37std::stringstream config_test2;
38std::stringstream jamfile;
39std::stringstream jamfile_v2;
40std::set<std::string> macro_list;
41
42
43void write_config_info()
44{
45   // load the file into memory so we can scan it:
46   fs::ifstream ifs(config_path / "config_info.cpp");
47   std::string file_text;
48   std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(), std::back_inserter(file_text));
49   ifs.close();
50   // create macro list:
51   std::stringstream ss;
52   for(std::set<std::string>::const_iterator i(macro_list.begin()), j(macro_list.end());
53      i != j;
54      ++i)
55   {
56      ss << "   PRINT_MACRO(" << *i << ");\n";
57   }
58   std::string macros = ss.str();
59   // scan for Boost macro block:
60   boost::regex re("BEGIN\\s+GENERATED\\s+BLOCK\\s+DO\\s+NOT\\s+EDIT\\s+THIS[^\\n]+\\n(.*?)\\n\\s+//\\s*END\\s+GENERATED\\s+BLOCK");
61   boost::smatch what;
62   if(boost::regex_search(file_text, what, re))
63   {
64      std::string new_text;
65      new_text.append(what.prefix().first, what[1].first);
66      new_text.append(macros);
67      new_text.append(what[1].second, what.suffix().second);
68      fs::ofstream ofs(config_path / "config_info.cpp");
69      ofs << new_text;
70   }
71}
72
73void write_config_test()
74{
75   fs::ofstream ofs(config_path / "config_test.cpp");
76   time_t t = std::time(0);
77   ofs << "//  This file was automatically generated on " << std::ctime(&t);
78   ofs << "//  by libs/config/tools/generate.cpp\n" << copyright << std::endl;
79   ofs << "// Test file for config setup\n"
80      "// This file should compile, if it does not then\n"
81      "// one or more macros need to be defined.\n"
82      "// see boost_*.ipp for more details\n\n"
83      "// Do not edit this file, it was generated automatically by\n\n"
84      "#include <boost/config.hpp>\n#include <iostream>\n#include \"test.hpp\"\n\n"
85      "int error_count = 0;\n\n";
86   ofs << config_test1.str() << std::endl;
87   ofs << config_test1a.str() << std::endl;
88   ofs << "int main( int, char *[] )\n{\n" << config_test2.str() << "   return error_count;\n}\n\n";
89}
90
91void write_jamfile()
92{
93   fs::ofstream ofs(config_path / "Jamfile");
94   time_t t = std::time(0);
95   ofs << "#\n# Regression test Jamfile for boost configuration setup.\n# *** DO NOT EDIT THIS FILE BY HAND ***\n"
96      "# This file was automatically generated on " << std::ctime(&t);
97   ofs << "#  by libs/config/tools/generate.cpp\n"
98      "# Copyright John Maddock.\n"
99      "# Use, modification and distribution are subject to the \n"
100      "# Boost Software License, Version 1.0. (See accompanying file \n"
101      "# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
102      "#\n# If you need to alter build preferences then set them in\n"
103      "# the template defined in options.jam.\n#\n"
104      "subproject libs/config/test ;\n"
105      "# bring in the rules for testing\n"
106      "import testing ./options ;\n\n"
107      "run config_info.cpp <template>config_options ;\n"
108      "run math_info.cpp <template>config_options : : : <borland><*><runtime-link>static ;\n"
109      "run config_test.cpp <template>config_options ;\n"
110      "run limits_test.cpp <template>config_test_options ;\n"
111      "run abi/abi_test.cpp abi/main.cpp <template>config_options ;\n\n";
112   ofs << jamfile.str() << std::endl;
113}
114
115void write_jamfile_v2() 
116{
117   fs::ofstream ofs(config_path / "Jamfile.v2");
118   time_t t = std::time(0);
119   ofs << "#\n# Regression test Jamfile for boost configuration setup.\n# *** DO NOT EDIT THIS FILE BY HAND ***\n"
120      "# This file was automatically generated on " << std::ctime(&t);
121   ofs << "#  by libs/config/tools/generate.cpp\n"
122      "# Copyright John Maddock.\n"
123      "# Use, modification and distribution are subject to the \n"
124      "# Boost Software License, Version 1.0. (See accompanying file \n"
125      "# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
126      "#\n# If you need to alter build preferences then set them in\n"
127      "# the template defined in options_v2.jam.\n#\n"
128      "path-constant DOT : . ;\n"
129      "include $(DOT)/options_v2.jam ;\n\n"
130      "run config_info.cpp ;\n"
131      "run math_info.cpp : : : <toolset>borland:<runtime-link>static ;\n"
132      "run config_test.cpp ;\n"
133      "run limits_test.cpp ;\n"
134      "run abi/abi_test.cpp abi/main.cpp  ;\n\n";
135   ofs << jamfile_v2.str() << std::endl;
136
137}
138
139void write_test_file(const fs::path& file, 
140                     const std::string& macro_name, 
141                     const std::string& namespace_name, 
142                     const std::string& header_file,
143                     bool positive_test, 
144                     bool expect_success)
145{
146   if(!fs::exists(file))
147   {
148      std::cout << "Writing test file " << file.native_directory_string() << std::endl;
149
150      fs::ofstream ofs(file);
151      std::time_t t = std::time(0);
152      ofs << "//  This file was automatically generated on " << std::ctime(&t);
153      ofs << "//  by libs/config/tools/generate.cpp\n" << copyright << std::endl;
154      ofs << "\n// Test file for macro " << macro_name << std::endl;
155
156      if(expect_success)
157      {
158         ofs << "// This file should compile, if it does not then\n"
159            "// " << macro_name << " should ";
160         if(positive_test)
161            ofs << "not ";
162         ofs << "be defined.\n";
163      }
164      else
165      {
166         ofs << "// This file should not compile, if it does then\n"
167            "// " << macro_name << " should ";
168         if(!positive_test)
169            ofs << "not ";
170         ofs << "be defined.\n";
171      }
172      ofs << "// See file " << header_file << " for details\n\n";
173
174      ofs << "// Must not have BOOST_ASSERT_CONFIG set; it defeats\n"
175         "// the objective of this file:\n"
176         "#ifdef BOOST_ASSERT_CONFIG\n"
177         "#  undef BOOST_ASSERT_CONFIG\n"
178         "#endif\n\n";
179
180      ofs << "#include <boost/config.hpp>\n"
181         "#include \"test.hpp\"\n\n"
182         "#if";
183      if(positive_test != expect_success)
184         ofs << "n";
185      ofs << "def " << macro_name << 
186         "\n#include \"" << header_file << 
187         "\"\n#else\n";
188      if(expect_success)
189         ofs << "namespace " << namespace_name << " = empty_boost;\n";
190      else
191         ofs << "#error \"this file should not compile\"\n";
192      ofs << "#endif\n\n";
193
194      ofs << "int main( int, char *[] )\n{\n   return " << namespace_name << "::test();\n}\n\n"; 
195   }
196   else
197   {
198      std::cout << "Skipping existing test file " << file.native_directory_string() << std::endl;
199   }
200}
201
202void process_ipp_file(const fs::path& file, bool positive_test)
203{
204   std::cout << "Info: Scanning file: " << file.native_directory_string() << std::endl;
205
206   // our variables:
207   std::string file_text;
208   std::string macro_name;
209   std::string namespace_name;
210   fs::path positive_file;
211   fs::path negative_file;
212
213   // load the file into memory so we can scan it:
214   fs::ifstream ifs(file);
215   std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(), std::back_inserter(file_text));
216   ifs.close();
217   // scan for the macro name:
218   boost::regex macro_regex("//\\s*MACRO\\s*:\\s*(\\w+)");
219   boost::smatch macro_match;
220   if(boost::regex_search(file_text, macro_match, macro_regex))
221   {
222      macro_name = macro_match[1];
223      macro_list.insert(macro_name);
224      namespace_name = boost::regex_replace(file_text, macro_regex, "\\L$1", boost::format_first_only | boost::format_no_copy);
225   }
226   if(macro_name.empty())
227   {
228      std::cout << "Error: no macro definition found in " << file.native_directory_string();
229   }
230   else
231   {
232      std::cout << "Info: Macroname: " << macro_name << std::endl;
233   }
234
235   // get the output filesnames:
236   boost::regex file_regex("boost_([^.]+)\\.ipp");
237   positive_file = file.branch_path() / boost::regex_replace(file.leaf(), file_regex, "$1_pass.cpp");
238   negative_file = file.branch_path() / boost::regex_replace(file.leaf(), file_regex, "$1_fail.cpp");
239   write_test_file(positive_file, macro_name, namespace_name, file.leaf(), positive_test, true);
240   write_test_file(negative_file, macro_name, namespace_name, file.leaf(), positive_test, false);
241   
242   // always create config_test data,
243   // positive and negative tests go to separate streams, because for some
244   // reason some compilers choke unless we put them in a particular order...
245   std::ostream* pout = positive_test ? &config_test1a : &config_test1;
246   *pout << "#if";
247   if(!positive_test)
248      *pout << "n";
249   *pout << "def " << macro_name
250      << "\n#include \"" << file.leaf() << "\"\n#else\nnamespace "
251      << namespace_name << " = empty_boost;\n#endif\n";
252
253   config_test2 << "   if(0 != " << namespace_name << "::test())\n"
254      "   {\n"
255      "      std::cerr << \"Failed test for " << macro_name << " at: \" << __FILE__ << \":\" << __LINE__ << std::endl;\n"
256      "      ++error_count;\n"
257      "   }\n";
258
259   // always generate the jamfile data:
260   jamfile << "test-suite \"" << macro_name << "\" : \n"
261      "[ run " << positive_file.leaf() << " <template>config_options ]\n"
262      "[ compile-fail " << negative_file.leaf() << " <template>config_options ] ;\n";
263
264   jamfile_v2 << "test-suite \"" << macro_name << "\" : \n"
265      "[ run " << positive_file.leaf() << " ]\n"
266      "[ compile-fail " << negative_file.leaf() << " ] ;\n";
267
268}
269
270int cpp_main(int argc, char* argv[])
271{
272   //
273   // get the boost path to begin with:
274   //
275   if(argc > 1)
276   {
277      fs::path p(argv[1], fs::native);
278      config_path = p / "libs" / "config" / "test" ;
279   }
280   else
281   {
282      // try __FILE__:
283      fs::path p(__FILE__, fs::native);
284      config_path = p.branch_path().branch_path() / "test";
285   }
286   std::cout << "Info: Boost.Config test path set as: " << config_path.native_directory_string() << std::endl;
287
288   // enumerate *.ipp files:
289   boost::regex ipp_mask("boost_(?:(has)|no).*\\.ipp");
290   boost::smatch ipp_match;
291   fs::directory_iterator i(config_path), j;
292   while(i != j)
293   {
294      if(boost::regex_match(i->leaf(), ipp_match, ipp_mask))
295      {
296         process_ipp_file(*i, ipp_match[1].matched);
297      }
298      ++i;
299   }
300   write_config_test();
301   write_jamfile();
302   write_jamfile_v2();
303   write_config_info();
304   return 0;
305}
306
Note: See TracBrowser for help on using the repository browser.