added some builtin rules
-FILE_OPEN
-HDRMACRO
-IMPORTED_MODULES
-MD5
-NEAREST_USER_LOCATION
-PAD
-PRECIOUS
-SEARCH_FOR_TARGET
-SELF_PATH
-UPDATE_NOW
-USER_MODULE
-W32_GETREGNAMES
@@ -16,6 +16,11 @@ | ||
16 | 16 | #include <boost/none.hpp> |
17 | 17 | #include <cstdlib> |
18 | 18 | |
19 | +#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__) | |
20 | + #include <io.h> | |
21 | +#endif | |
22 | +#include <fcntl.h> | |
23 | + | |
19 | 24 | namespace bjam = hamigaki::bjam; |
20 | 25 | namespace ut = boost::unit_test; |
21 | 26 |
@@ -366,10 +371,13 @@ | ||
366 | 371 | ("EXIT") |
367 | 372 | ("EXPORT") |
368 | 373 | ("FAIL_EXPECTED") |
374 | + ("FILE_OPEN") | |
369 | 375 | ("GLOB") |
370 | 376 | ("GLOB-RECURSIVELY") |
371 | 377 | ("HAS_NATIVE_RULE") |
378 | + ("HDRMACRO") | |
372 | 379 | ("IMPORT") |
380 | + ("IMPORTED_MODULES") | |
373 | 381 | ("IMPORT_MODULE") |
374 | 382 | ("INCLUDES") |
375 | 383 | ("INSTANCE") |
@@ -376,23 +384,32 @@ | ||
376 | 384 | ("ISFILE") |
377 | 385 | ("LEAVES") |
378 | 386 | ("MATCH") |
387 | + ("MD5") | |
379 | 388 | ("NATIVE_RULE") |
389 | + ("NEAREST_USER_LOCATION") | |
380 | 390 | ("NOCARE") |
381 | 391 | ("NORMALIZE_PATH") |
382 | 392 | ("NOTFILE") |
383 | 393 | ("NOUPDATE") |
394 | + ("PAD") | |
395 | + ("PRECIOUS") | |
384 | 396 | ("PWD") |
385 | 397 | ("REBUILDS") |
386 | 398 | ("RMOLD") |
387 | 399 | ("RULENAMES") |
400 | + ("SEARCH_FOR_TARGET") | |
401 | + ("SELF_PATH") | |
388 | 402 | ("SHELL") |
389 | 403 | ("SORT") |
390 | 404 | ("SUBST") |
391 | 405 | ("TEMPORARY") |
392 | 406 | ("UPDATE") |
407 | + ("UPDATE_NOW") | |
408 | + ("USER_MODULE") | |
393 | 409 | ("VARNAMES") |
394 | 410 | #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) |
395 | 411 | ("W32_GETREG") |
412 | + ("W32_GETREGNAMES") | |
396 | 413 | #endif |
397 | 414 | ; |
398 | 415 | result = ctx.invoke_rule("RULENAMES", args); |
@@ -569,6 +586,25 @@ | ||
569 | 586 | result.begin(), result.end(), expect.begin(), expect.end()); |
570 | 587 | } |
571 | 588 | |
589 | +void imported_modules_test() | |
590 | +{ | |
591 | + bjam::context ctx; | |
592 | + bjam::list_of_list args; | |
593 | + | |
594 | + args.push_back(boost::assign::list_of("m1")("m2")); | |
595 | + args.push_back(boost::assign::list_of("m3")); | |
596 | + ctx.invoke_rule("IMPORT_MODULE", args); | |
597 | + | |
598 | + args.clear(); | |
599 | + args.push_back(boost::assign::list_of("m3")); | |
600 | + | |
601 | + bjam::string_list expect = boost::assign::list_of("m1")("m2"); | |
602 | + const bjam::string_list& result = ctx.invoke_rule("IMPORTED_MODULES", args); | |
603 | + | |
604 | + BOOST_CHECK_EQUAL_COLLECTIONS( | |
605 | + result.begin(), result.end(), expect.begin(), expect.end()); | |
606 | +} | |
607 | + | |
572 | 608 | void instance_test() |
573 | 609 | { |
574 | 610 | bjam::context ctx; |
@@ -657,6 +693,21 @@ | ||
657 | 693 | // TODO: add the positive tests |
658 | 694 | } |
659 | 695 | |
696 | +void user_module_test() | |
697 | +{ | |
698 | + bjam::context ctx; | |
699 | + bjam::list_of_list args; | |
700 | + | |
701 | + const std::string m1("m1"); | |
702 | + | |
703 | + BOOST_CHECK(!ctx.get_module(m1).user_module); | |
704 | + | |
705 | + args.push_back(boost::assign::list_of(m1)); | |
706 | + BOOST_CHECK(ctx.invoke_rule("USER_MODULE", args).empty()); | |
707 | + | |
708 | + BOOST_CHECK(ctx.get_module(m1).user_module); | |
709 | +} | |
710 | + | |
660 | 711 | void check_if_file_test() |
661 | 712 | { |
662 | 713 | bjam::context ctx; |
@@ -698,8 +749,10 @@ | ||
698 | 749 | // should use SHGetSpecialFolderPath() |
699 | 750 | std::string prog_dir(win_dir, 0, 3); |
700 | 751 | prog_dir += "Program Files"; |
752 | +#if !defined(_WIN64) | |
701 | 753 | if (get_native_system_arch() != 0) |
702 | 754 | prog_dir += " (x86)"; |
755 | +#endif | |
703 | 756 | |
704 | 757 | ::OSVERSIONINFOA info; |
705 | 758 | std::memset(&info, 0, sizeof(info)); |
@@ -714,8 +767,8 @@ | ||
714 | 767 | |
715 | 768 | args.push_back(boost::assign::list_of |
716 | 769 | ("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion") |
717 | - ("ProgramFilesDir") | |
718 | 770 | ); |
771 | + args.push_back(boost::assign::list_of("ProgramFilesDir")); | |
719 | 772 | result = ctx.invoke_rule("W32_GETREG", args); |
720 | 773 | BOOST_CHECK_EQUAL(result.size(), 1u); |
721 | 774 | if (!result.empty()) |
@@ -729,8 +782,8 @@ | ||
729 | 782 | args.clear(); |
730 | 783 | args.push_back(boost::assign::list_of |
731 | 784 | ("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion") |
732 | - ("ProgramFilesPath") | |
733 | 785 | ); |
786 | + args.push_back(boost::assign::list_of("ProgramFilesPath")); | |
734 | 787 | result = ctx.invoke_rule("W32_GETREG", args); |
735 | 788 | BOOST_CHECK_EQUAL(result.size(), 1u); |
736 | 789 | if (!result.empty()) |
@@ -751,8 +804,8 @@ | ||
751 | 804 | args.clear(); |
752 | 805 | args.push_back(boost::assign::list_of |
753 | 806 | ("HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon") |
754 | - ("BuildNumber") | |
755 | 807 | ); |
808 | + args.push_back(boost::assign::list_of("BuildNumber")); | |
756 | 809 | result = ctx.invoke_rule("W32_GETREG", args); |
757 | 810 | BOOST_CHECK_EQUAL(result.size(), 1u); |
758 | 811 | if (!result.empty()) |
@@ -762,11 +815,37 @@ | ||
762 | 815 | args.clear(); |
763 | 816 | args.push_back(boost::assign::list_of |
764 | 817 | ("HKLM\\HARDWARE\\DESCRIPTION\\System") |
765 | - ("SystemBiosVersion") | |
766 | 818 | ); |
819 | + args.push_back(boost::assign::list_of("SystemBiosVersion")); | |
767 | 820 | result = ctx.invoke_rule("W32_GETREG", args); |
768 | 821 | BOOST_CHECK(result.size() >= 1); |
769 | 822 | } |
823 | + | |
824 | +void w32_getregnames_test() | |
825 | +{ | |
826 | + bjam::context ctx; | |
827 | + bjam::list_of_list args; | |
828 | + bjam::string_list result; | |
829 | + | |
830 | + args.push_back(boost::assign::list_of | |
831 | + ("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion") | |
832 | + ); | |
833 | + args.push_back(boost::assign::list_of("subkeys")); | |
834 | + result = ctx.invoke_rule("W32_GETREGNAMES", args); | |
835 | + BOOST_CHECK( | |
836 | + std::find(result.begin(), result.end(), "Control Panel") != result.end() | |
837 | + ); | |
838 | + | |
839 | + args.clear(); | |
840 | + args.push_back(boost::assign::list_of | |
841 | + ("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion") | |
842 | + ); | |
843 | + args.push_back(boost::assign::list_of("values")); | |
844 | + result = ctx.invoke_rule("W32_GETREGNAMES", args); | |
845 | + BOOST_CHECK( | |
846 | + std::find(result.begin(), result.end(), "DevicePath") != result.end() | |
847 | + ); | |
848 | +} | |
770 | 849 | #endif |
771 | 850 | |
772 | 851 | void shell_test() |
@@ -788,6 +867,84 @@ | ||
788 | 867 | } |
789 | 868 | } |
790 | 869 | |
870 | +void md5_test() | |
871 | +{ | |
872 | + bjam::context ctx; | |
873 | + bjam::list_of_list args; | |
874 | + bjam::string_list result; | |
875 | + | |
876 | + args.push_back(boost::assign::list_of("abc")); | |
877 | + result = ctx.invoke_rule("MD5", args); | |
878 | + BOOST_CHECK_EQUAL(result.size(), 1u); | |
879 | + if (!result.empty()) | |
880 | + BOOST_CHECK_EQUAL(result[0], "900150983cd24fb0d6963f7d28e17f72"); | |
881 | +} | |
882 | + | |
883 | +void file_open_test() | |
884 | +{ | |
885 | + bjam::context ctx; | |
886 | + bjam::list_of_list args; | |
887 | + bjam::string_list result; | |
888 | + | |
889 | + args.push_back(boost::assign::list_of("file_open.txt")); | |
890 | + args.push_back(boost::assign::list_of("w")); | |
891 | + result = ctx.invoke_rule("FILE_OPEN", args); | |
892 | + BOOST_REQUIRE_EQUAL(result.size(), 1u); | |
893 | + | |
894 | + int fd = std::atoi(result[0].c_str()); | |
895 | + BOOST_REQUIRE_NE(fd, -1); | |
896 | + | |
897 | + static const char msg[] = "file_open_test\n"; | |
898 | + int n = ::write(fd, msg, sizeof(msg)-1); | |
899 | + BOOST_CHECK_EQUAL(n, static_cast<int>(sizeof(msg)-1)); | |
900 | + | |
901 | + ::close(fd); | |
902 | + | |
903 | + | |
904 | + args.clear(); | |
905 | + args.push_back(boost::assign::list_of("file_open.txt")); | |
906 | + args.push_back(boost::assign::list_of("r")); | |
907 | + result = ctx.invoke_rule("FILE_OPEN", args); | |
908 | + BOOST_REQUIRE_EQUAL(result.size(), 1u); | |
909 | + | |
910 | + fd = std::atoi(result[0].c_str()); | |
911 | + BOOST_REQUIRE_NE(fd, -1); | |
912 | + | |
913 | + char buf[64]; | |
914 | + n = ::read(fd, buf, sizeof(buf)); | |
915 | + | |
916 | + BOOST_CHECK_EQUAL(n, static_cast<int>(sizeof(msg)-1)); | |
917 | + if (n != -1) | |
918 | + BOOST_CHECK_EQUAL(std::string(buf, n), std::string(msg)); | |
919 | + | |
920 | + ::close(fd); | |
921 | + std::remove("file_open.txt"); | |
922 | +} | |
923 | + | |
924 | +void pad_test() | |
925 | +{ | |
926 | + bjam::context ctx; | |
927 | + bjam::list_of_list args; | |
928 | + bjam::string_list result; | |
929 | + | |
930 | + args.push_back(boost::assign::list_of("abc")); | |
931 | + args.push_back(boost::assign::list_of("8")); | |
932 | + result = ctx.invoke_rule("PAD", args); | |
933 | + BOOST_CHECK_EQUAL(result.size(), 1u); | |
934 | + if (!result.empty()) | |
935 | + BOOST_CHECK_EQUAL(result[0], "abc "); | |
936 | +} | |
937 | + | |
938 | +void precious_test() | |
939 | +{ | |
940 | + bjam::context ctx; | |
941 | + bjam::list_of_list args; | |
942 | + | |
943 | + args.push_back(boost::assign::list_of("t1")); | |
944 | + BOOST_CHECK(ctx.invoke_rule("PRECIOUS", args).empty()); | |
945 | + BOOST_CHECK(ctx.get_target("t1").flags & bjam::target::precious); | |
946 | +} | |
947 | + | |
791 | 948 | ut::test_suite* init_unit_test_suite(int, char* []) |
792 | 949 | { |
793 | 950 | ut::test_suite* test = BOOST_TEST_SUITE("builtin rules test"); |
@@ -819,6 +976,7 @@ | ||
819 | 976 | test->add(BOOST_TEST_CASE(&back_trace_test)); |
820 | 977 | test->add(BOOST_TEST_CASE(&pwd_test)); |
821 | 978 | test->add(BOOST_TEST_CASE(&import_module_test)); |
979 | + test->add(BOOST_TEST_CASE(&imported_modules_test)); | |
822 | 980 | test->add(BOOST_TEST_CASE(&instance_test)); |
823 | 981 | test->add(BOOST_TEST_CASE(&sort_test)); |
824 | 982 | test->add(BOOST_TEST_CASE(&normalize_path_test)); |
@@ -825,10 +983,16 @@ | ||
825 | 983 | test->add(BOOST_TEST_CASE(&calc_test)); |
826 | 984 | test->add(BOOST_TEST_CASE(&native_rule_test)); |
827 | 985 | test->add(BOOST_TEST_CASE(&has_native_rule_test)); |
986 | + test->add(BOOST_TEST_CASE(&user_module_test)); | |
828 | 987 | test->add(BOOST_TEST_CASE(&check_if_file_test)); |
829 | 988 | #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) |
830 | 989 | test->add(BOOST_TEST_CASE(&w32_getreg_test)); |
990 | + test->add(BOOST_TEST_CASE(&w32_getregnames_test)); | |
831 | 991 | #endif |
832 | 992 | test->add(BOOST_TEST_CASE(&shell_test)); |
993 | + test->add(BOOST_TEST_CASE(&md5_test)); | |
994 | + test->add(BOOST_TEST_CASE(&file_open_test)); | |
995 | + test->add(BOOST_TEST_CASE(&pad_test)); | |
996 | + test->add(BOOST_TEST_CASE(&precious_test)); | |
833 | 997 | return test; |
834 | 998 | } |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // registry.cpp: Win32 registry utilities |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -154,6 +154,68 @@ | ||
154 | 154 | return string_list(); |
155 | 155 | } |
156 | 156 | |
157 | + std::string get_subkey_name(std::size_t i) const | |
158 | + { | |
159 | + char name[256]; | |
160 | + DWORD name_size = sizeof(name); | |
161 | + | |
162 | + int err = ::RegEnumKeyExA( | |
163 | + handle_, static_cast<DWORD>(i), name, &name_size, 0, 0, 0, 0); | |
164 | + | |
165 | + if (err == ERROR_SUCCESS) | |
166 | + return std::string(name); | |
167 | + else | |
168 | + return std::string(); | |
169 | + } | |
170 | + | |
171 | + string_list get_subkey_names() const | |
172 | + { | |
173 | + if (handle_ == 0) | |
174 | + return string_list(); | |
175 | + | |
176 | + string_list result; | |
177 | + for (std::size_t i = 0; ; ++i) | |
178 | + { | |
179 | + const std::string& name = get_subkey_name(i); | |
180 | + if (name.empty()) | |
181 | + break; | |
182 | + result.push_back(name); | |
183 | + } | |
184 | + | |
185 | + return result; | |
186 | + } | |
187 | + | |
188 | + std::string get_value_name(std::size_t i) const | |
189 | + { | |
190 | + char name[16384]; | |
191 | + DWORD name_size = sizeof(name); | |
192 | + | |
193 | + int err = ::RegEnumValueA( | |
194 | + handle_, static_cast<DWORD>(i), name, &name_size, 0, 0, 0, 0); | |
195 | + | |
196 | + if (err == ERROR_SUCCESS) | |
197 | + return std::string(name); | |
198 | + else | |
199 | + return std::string(); | |
200 | + } | |
201 | + | |
202 | + string_list get_value_names() const | |
203 | + { | |
204 | + if (handle_ == 0) | |
205 | + return string_list(); | |
206 | + | |
207 | + string_list result; | |
208 | + for (std::size_t i = 0; ; ++i) | |
209 | + { | |
210 | + const std::string& name = get_value_name(i); | |
211 | + if (name.empty()) | |
212 | + break; | |
213 | + result.push_back(name); | |
214 | + } | |
215 | + | |
216 | + return result; | |
217 | + } | |
218 | + | |
157 | 219 | private: |
158 | 220 | ::HKEY handle_; |
159 | 221 | }; |
@@ -178,4 +240,38 @@ | ||
178 | 240 | return reg.get_values(name); |
179 | 241 | } |
180 | 242 | |
243 | +HAMIGAKI_BJAM_DECL | |
244 | +string_list registry_subkey_names(const std::string& key) | |
245 | +{ | |
246 | + std::string::size_type delim = key.find("\\"); | |
247 | + | |
248 | + ::HKEY parent = root_key(key.substr(0, delim)); | |
249 | + if (parent == 0) | |
250 | + return string_list(); | |
251 | + | |
252 | + std::string::size_type start = delim; | |
253 | + if (start != std::string::npos) | |
254 | + ++start; | |
255 | + | |
256 | + registry_key reg(parent, key.substr(start), KEY_ENUMERATE_SUB_KEYS); | |
257 | + return reg.get_subkey_names(); | |
258 | +} | |
259 | + | |
260 | +HAMIGAKI_BJAM_DECL | |
261 | +string_list registry_value_names(const std::string& key) | |
262 | +{ | |
263 | + std::string::size_type delim = key.find("\\"); | |
264 | + | |
265 | + ::HKEY parent = root_key(key.substr(0, delim)); | |
266 | + if (parent == 0) | |
267 | + return string_list(); | |
268 | + | |
269 | + std::string::size_type start = delim; | |
270 | + if (start != std::string::npos) | |
271 | + ++start; | |
272 | + | |
273 | + registry_key reg(parent, key.substr(start), KEY_QUERY_VALUE); | |
274 | + return reg.get_value_names(); | |
275 | +} | |
276 | + | |
181 | 277 | } } } // End namespaces win32, bjam, hamigaki. |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // bjam_context.cpp: the context information for bjam |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007, 2008. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -316,6 +316,7 @@ | ||
316 | 316 | f.arguments() = args; |
317 | 317 | f.filename(rule.filename); |
318 | 318 | f.line(rule.line); |
319 | + f.prev_user_frame(old.prev_user_frame()); | |
319 | 320 | |
320 | 321 | scoped_push_frame guard(*this, f); |
321 | 322 | this->change_module(rule.module_name); |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // builtin_rules.cpp: bjam builtin rules |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007, 2008. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -12,10 +12,12 @@ | ||
12 | 12 | #include <hamigaki/bjam/util/glob.hpp> |
13 | 13 | #include <hamigaki/bjam/util/path.hpp> |
14 | 14 | #include <hamigaki/bjam/util/regex.hpp> |
15 | +#include <hamigaki/bjam/util/search.hpp> | |
15 | 16 | #include <hamigaki/bjam/util/shell.hpp> |
16 | 17 | #include <hamigaki/bjam/bjam_context.hpp> |
17 | 18 | #include <hamigaki/bjam/builtin_rules.hpp> |
18 | 19 | #include <hamigaki/bjam/bjam_exceptions.hpp> |
20 | +#include <hamigaki/checksum/md5.hpp> | |
19 | 21 | #include <hamigaki/iterator/first_iterator.hpp> |
20 | 22 | #include <hamigaki/iterator/ostream_iterator.hpp> |
21 | 23 | #include <boost/assign/list_of.hpp> |
@@ -26,6 +28,7 @@ | ||
26 | 28 | #include <boost/next_prior.hpp> |
27 | 29 | #include <boost/regex.hpp> |
28 | 30 | #include <cstdlib> |
31 | +#include <iomanip> | |
29 | 32 | #include <locale> |
30 | 33 | #include <sstream> |
31 | 34 |
@@ -33,6 +36,11 @@ | ||
33 | 36 | #include <hamigaki/bjam/util/win32/registry.hpp> |
34 | 37 | #endif |
35 | 38 | |
39 | +#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__) | |
40 | + #include <io.h> | |
41 | +#endif | |
42 | +#include <fcntl.h> | |
43 | + | |
36 | 44 | namespace fs = boost::filesystem; |
37 | 45 | |
38 | 46 | namespace hamigaki { namespace bjam { |
@@ -268,6 +276,12 @@ | ||
268 | 276 | return string_list(); |
269 | 277 | } |
270 | 278 | |
279 | +HAMIGAKI_BJAM_DECL string_list hdr_macro(context& ctx) | |
280 | +{ | |
281 | + // TODO: not implemented | |
282 | + return string_list(); | |
283 | +} | |
284 | + | |
271 | 285 | HAMIGAKI_BJAM_DECL string_list fail_expected(context& ctx) |
272 | 286 | { |
273 | 287 | set_target_flags(ctx, target::fail_expected); |
@@ -290,6 +304,22 @@ | ||
290 | 304 | return old; |
291 | 305 | } |
292 | 306 | |
307 | +HAMIGAKI_BJAM_DECL string_list update_now(context& ctx) | |
308 | +{ | |
309 | + frame& f = ctx.current_frame(); | |
310 | + const list_of_list& args = f.arguments(); | |
311 | + const string_list& arg2 = args[1]; | |
312 | + const string_list& arg3 = args[2]; | |
313 | + | |
314 | + const string_list& targets = args[0]; | |
315 | + const boost::optional<std::string>& log = arg2.try_front(); | |
316 | + const boost::optional<std::string>& force = arg3.try_front(); | |
317 | + | |
318 | + // TODO: not implemented | |
319 | + | |
320 | + return string_list(std::string("ok")); | |
321 | +} | |
322 | + | |
293 | 323 | HAMIGAKI_BJAM_DECL string_list subst(context& ctx) |
294 | 324 | { |
295 | 325 | frame& f = ctx.current_frame(); |
@@ -463,6 +493,49 @@ | ||
463 | 493 | return string_list(ctx.working_directory()); |
464 | 494 | } |
465 | 495 | |
496 | +HAMIGAKI_BJAM_DECL string_list search_for_target(context& ctx) | |
497 | +{ | |
498 | + frame& f = ctx.current_frame(); | |
499 | + const list_of_list& args = f.arguments(); | |
500 | + | |
501 | + const string_list& targets = args[0]; | |
502 | + const string_list& path = args[1]; | |
503 | + | |
504 | + const std::string& name = targets[0]; | |
505 | + | |
506 | + path_components compo; | |
507 | + split_path(compo, name); | |
508 | + compo.grist.clear(); | |
509 | + compo.member.clear(); | |
510 | + | |
511 | + bool found = false; | |
512 | + std::string filename; | |
513 | + | |
514 | + for (std::size_t i = 0, size = path.size(); i < size; ++i) | |
515 | + { | |
516 | + compo.root = path[i]; | |
517 | + filename = make_path(compo); | |
518 | + | |
519 | + if (fs::exists(fs::path(filename))) | |
520 | + { | |
521 | + found = true; | |
522 | + break; | |
523 | + } | |
524 | + } | |
525 | + | |
526 | + if (!found) | |
527 | + { | |
528 | + compo.root.clear(); | |
529 | + fs::path ph(make_path(compo)); | |
530 | + fs::path work(ctx.working_directory()); | |
531 | + filename = fs::complete(ph, work).file_string(); | |
532 | + } | |
533 | + | |
534 | + call_bind_rule(ctx, name, filename); | |
535 | + | |
536 | + return string_list(name); | |
537 | +} | |
538 | + | |
466 | 539 | HAMIGAKI_BJAM_DECL string_list import_module(context& ctx) |
467 | 540 | { |
468 | 541 | frame& f = ctx.current_frame(); |
@@ -476,6 +549,19 @@ | ||
476 | 549 | return string_list(); |
477 | 550 | } |
478 | 551 | |
552 | +HAMIGAKI_BJAM_DECL string_list imported_modules(context& ctx) | |
553 | +{ | |
554 | + frame& f = ctx.current_frame(); | |
555 | + const list_of_list& args = f.arguments(); | |
556 | + | |
557 | + module& m = ctx.get_module(args[0].try_front()); | |
558 | + | |
559 | + return string_list( | |
560 | + m.imported_modules.begin(), | |
561 | + m.imported_modules.end() | |
562 | + ); | |
563 | +} | |
564 | + | |
479 | 565 | HAMIGAKI_BJAM_DECL string_list instance(context& ctx) |
480 | 566 | { |
481 | 567 | frame& f = ctx.current_frame(); |
@@ -583,6 +669,44 @@ | ||
583 | 669 | return string_list(); |
584 | 670 | } |
585 | 671 | |
672 | +HAMIGAKI_BJAM_DECL string_list user_module(context& ctx) | |
673 | +{ | |
674 | + frame& f = ctx.current_frame(); | |
675 | + const list_of_list& args = f.arguments(); | |
676 | + | |
677 | + const string_list& modules = args[0]; | |
678 | + module& m = ctx.get_module(args[0].try_front()); | |
679 | + | |
680 | + for (std::size_t i = 0, size = modules.size(); i < size; ++i) | |
681 | + { | |
682 | + module& m = ctx.get_module(modules[i]); | |
683 | + m.user_module = true; | |
684 | + } | |
685 | + | |
686 | + return string_list(); | |
687 | +} | |
688 | + | |
689 | +HAMIGAKI_BJAM_DECL string_list nearest_user_location(context& ctx) | |
690 | +{ | |
691 | + frame& f = ctx.current_frame(); | |
692 | + | |
693 | + frame* user_frame = | |
694 | + f.current_module().user_module ? &f : f.prev_user_frame(); | |
695 | + if (!user_frame) | |
696 | + return string_list(); | |
697 | + | |
698 | + string_list result; | |
699 | + result.push_back(user_frame->filename()); | |
700 | + { | |
701 | + std::ostringstream os; | |
702 | + os.imbue(std::locale::classic()); | |
703 | + os << user_frame->line(); | |
704 | + result.push_back(os.str()); | |
705 | + } | |
706 | + | |
707 | + return result; | |
708 | +} | |
709 | + | |
586 | 710 | HAMIGAKI_BJAM_DECL string_list check_if_file(context& ctx) |
587 | 711 | { |
588 | 712 | frame& f = ctx.current_frame(); |
@@ -606,13 +730,32 @@ | ||
606 | 730 | const list_of_list& args = f.arguments(); |
607 | 731 | |
608 | 732 | const string_list& arg1 = args[0]; |
733 | + const string_list& arg2 = args[1]; | |
609 | 734 | |
610 | - boost::optional<std::string> name; | |
611 | - if (arg1.size() >= 2) | |
612 | - name = arg1[1]; | |
735 | + const std::string& path = arg1[0]; | |
736 | + boost::optional<std::string> name = arg2.try_front(); | |
613 | 737 | |
614 | - return win32::registry_values(arg1[0], name); | |
738 | + return win32::registry_values(path, name); | |
615 | 739 | } |
740 | + | |
741 | +HAMIGAKI_BJAM_DECL string_list w32_getregnames(context& ctx) | |
742 | +{ | |
743 | + frame& f = ctx.current_frame(); | |
744 | + const list_of_list& args = f.arguments(); | |
745 | + | |
746 | + const string_list& arg1 = args[0]; | |
747 | + const string_list& arg2 = args[1]; | |
748 | + | |
749 | + const std::string& path = arg1[0]; | |
750 | + const std::string& result_type = arg2[0]; | |
751 | + | |
752 | + if (result_type == "subkeys") | |
753 | + return win32::registry_subkey_names(path); | |
754 | + else if (result_type == "values") | |
755 | + return win32::registry_value_names(path); | |
756 | + else | |
757 | + return string_list(); | |
758 | +} | |
616 | 759 | #endif |
617 | 760 | |
618 | 761 | HAMIGAKI_BJAM_DECL string_list shell(context& ctx) |
@@ -636,6 +779,77 @@ | ||
636 | 779 | return bjam::shell(cmd, need_status, need_capture); |
637 | 780 | } |
638 | 781 | |
782 | +HAMIGAKI_BJAM_DECL string_list md5(context& ctx) | |
783 | +{ | |
784 | + frame& f = ctx.current_frame(); | |
785 | + const list_of_list& args = f.arguments(); | |
786 | + | |
787 | + const std::string& s = args[0][0]; | |
788 | + | |
789 | + checksum::md5 md5; | |
790 | + md5.process_bytes(s.c_str(), s.size()); | |
791 | + | |
792 | + typedef checksum::md5::value_type value_type; | |
793 | + const value_type& v = md5.checksum(); | |
794 | + | |
795 | + std::ostringstream os; | |
796 | + os.imbue(std::locale::classic()); | |
797 | + os << std::hex << std::setfill('0'); | |
798 | + for (std::size_t i = 0; i < value_type::static_size; ++i) | |
799 | + os << std::setw(2) << static_cast<unsigned>(v[i]); | |
800 | + | |
801 | + return string_list(os.str()); | |
802 | +} | |
803 | + | |
804 | +HAMIGAKI_BJAM_DECL string_list file_open(context& ctx) | |
805 | +{ | |
806 | + frame& f = ctx.current_frame(); | |
807 | + const list_of_list& args = f.arguments(); | |
808 | + | |
809 | + const std::string& name = args[0][0]; | |
810 | + const std::string& mode = args[1][0]; | |
811 | + | |
812 | + int fd; | |
813 | + if (mode == "w") | |
814 | + fd = ::open(name.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
815 | + else | |
816 | + fd = ::open(name.c_str(), O_RDONLY); | |
817 | + | |
818 | + if (fd == -1) | |
819 | + return string_list(); | |
820 | + | |
821 | + std::ostringstream os; | |
822 | + os.imbue(std::locale::classic()); | |
823 | + os << fd; | |
824 | + return string_list(os.str()); | |
825 | +} | |
826 | + | |
827 | +HAMIGAKI_BJAM_DECL string_list pad(context& ctx) | |
828 | +{ | |
829 | + frame& f = ctx.current_frame(); | |
830 | + const list_of_list& args = f.arguments(); | |
831 | + | |
832 | + std::string str = args[0][0]; | |
833 | + std::size_t width = static_cast<std::size_t>(std::atoi(args[1][0].c_str())); | |
834 | + | |
835 | + if (str.size() < width) | |
836 | + str.resize(width, ' '); | |
837 | + | |
838 | + return string_list(str); | |
839 | +} | |
840 | + | |
841 | +HAMIGAKI_BJAM_DECL string_list precious(context& ctx) | |
842 | +{ | |
843 | + set_target_flags(ctx, target::precious); | |
844 | + return string_list(); | |
845 | +} | |
846 | + | |
847 | +HAMIGAKI_BJAM_DECL string_list self_path(context& ctx) | |
848 | +{ | |
849 | + // FIXME | |
850 | + return string_list("bjam"); | |
851 | +} | |
852 | + | |
639 | 853 | } // namespace builtins |
640 | 854 | |
641 | 855 | HAMIGAKI_BJAM_DECL void set_builtin_rules(context& ctx) |
@@ -711,6 +925,10 @@ | ||
711 | 925 | ctx.set_builtin_rule("ISFILE", params, &builtins::is_file); |
712 | 926 | |
713 | 927 | params.clear(); |
928 | + ctx.set_builtin_rule("HDRMACRO", params, &builtins::hdr_macro); | |
929 | + ctx.set_builtin_rule("HdrMacro", params, &builtins::hdr_macro, false); | |
930 | + | |
931 | + params.clear(); | |
714 | 932 | ctx.set_builtin_rule("FAIL_EXPECTED", params, &builtins::fail_expected); |
715 | 933 | |
716 | 934 | params.clear(); |
@@ -722,6 +940,12 @@ | ||
722 | 940 | ctx.set_builtin_rule("UPDATE", params, &builtins::update); |
723 | 941 | |
724 | 942 | params.clear(); |
943 | + params.push_back(boost::assign::list_of("targets")("*")); | |
944 | + params.push_back(boost::assign::list_of("log")("?")); | |
945 | + params.push_back(boost::assign::list_of("ignore-minus-n")("?")); | |
946 | + ctx.set_builtin_rule("UPDATE_NOW", params, &builtins::update_now); | |
947 | + | |
948 | + params.clear(); | |
725 | 949 | params.push_back( |
726 | 950 | boost::assign::list_of("string")("pattern")("replacements")("+")); |
727 | 951 | ctx.set_builtin_rule("SUBST", params, &builtins::subst); |
@@ -755,11 +979,22 @@ | ||
755 | 979 | ctx.set_builtin_rule("PWD", params, &builtins::pwd); |
756 | 980 | |
757 | 981 | params.clear(); |
982 | + params.push_back(boost::assign::list_of("target")("*")); | |
983 | + params.push_back(boost::assign::list_of("path")("*")); | |
984 | + ctx.set_builtin_rule( | |
985 | + "SEARCH_FOR_TARGET", params, &builtins::search_for_target); | |
986 | + | |
987 | + params.clear(); | |
758 | 988 | params.push_back(boost::assign::list_of("modules_to_import")("+")); |
759 | 989 | params.push_back(boost::assign::list_of("target_module")("?")); |
760 | 990 | ctx.set_builtin_rule("IMPORT_MODULE", params, &builtins::import_module); |
761 | 991 | |
762 | 992 | params.clear(); |
993 | + params.push_back(boost::assign::list_of("module")("?")); | |
994 | + ctx.set_builtin_rule( | |
995 | + "IMPORTED_MODULES", params, &builtins::imported_modules); | |
996 | + | |
997 | + params.clear(); | |
763 | 998 | params.push_back(boost::assign::list_of("instance_module")); |
764 | 999 | params.push_back(boost::assign::list_of("class_module")); |
765 | 1000 | ctx.set_builtin_rule("INSTANCE", params, &builtins::instance); |
@@ -784,13 +1019,27 @@ | ||
784 | 1019 | ctx.set_builtin_rule("HAS_NATIVE_RULE", params, &builtins::has_native_rule); |
785 | 1020 | |
786 | 1021 | params.clear(); |
1022 | + params.push_back(boost::assign::list_of("module")("*")); | |
1023 | + ctx.set_builtin_rule("USER_MODULE", params, &builtins::user_module); | |
1024 | + | |
1025 | + params.clear(); | |
1026 | + ctx.set_builtin_rule( | |
1027 | + "NEAREST_USER_LOCATION", params, &builtins::nearest_user_location); | |
1028 | + | |
1029 | + params.clear(); | |
787 | 1030 | params.push_back(boost::assign::list_of("file")); |
788 | 1031 | ctx.set_builtin_rule("CHECK_IF_FILE", params, &builtins::check_if_file); |
789 | 1032 | |
790 | 1033 | #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) |
791 | 1034 | params.clear(); |
792 | - params.push_back(boost::assign::list_of("key_path")("data")("?")); | |
1035 | + params.push_back(boost::assign::list_of("key_path")); | |
1036 | + params.push_back(boost::assign::list_of("data")("?")); | |
793 | 1037 | ctx.set_builtin_rule("W32_GETREG", params, &builtins::w32_getreg); |
1038 | + | |
1039 | + params.clear(); | |
1040 | + params.push_back(boost::assign::list_of("key_path")); | |
1041 | + params.push_back(boost::assign::list_of("result-type")); | |
1042 | + ctx.set_builtin_rule("W32_GETREGNAMES", params, &builtins::w32_getregnames); | |
794 | 1043 | #endif |
795 | 1044 | |
796 | 1045 | params.clear(); |
@@ -798,6 +1047,27 @@ | ||
798 | 1047 | params.push_back(boost::assign::list_of("*")); |
799 | 1048 | ctx.set_builtin_rule("SHELL", params, &builtins::shell); |
800 | 1049 | ctx.set_builtin_rule("COMMAND", params, &builtins::shell); |
1050 | + | |
1051 | + params.clear(); | |
1052 | + params.push_back(boost::assign::list_of("string")); | |
1053 | + ctx.set_builtin_rule("MD5", params, &builtins::md5); | |
1054 | + | |
1055 | + params.clear(); | |
1056 | + params.push_back(boost::assign::list_of("name")); | |
1057 | + params.push_back(boost::assign::list_of("mode")); | |
1058 | + ctx.set_builtin_rule("FILE_OPEN", params, &builtins::file_open); | |
1059 | + | |
1060 | + params.clear(); | |
1061 | + params.push_back(boost::assign::list_of("string")); | |
1062 | + params.push_back(boost::assign::list_of("width")); | |
1063 | + ctx.set_builtin_rule("PAD", params, &builtins::pad); | |
1064 | + | |
1065 | + params.clear(); | |
1066 | + params.push_back(boost::assign::list_of("targets")("*")); | |
1067 | + ctx.set_builtin_rule("PRECIOUS", params, &builtins::precious); | |
1068 | + | |
1069 | + params.clear(); | |
1070 | + ctx.set_builtin_rule("SELF_PATH", params, &builtins::self_path); | |
801 | 1071 | } |
802 | 1072 | |
803 | 1073 | } } // End namespaces bjam, hamigaki. |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // order.cpp: bjam order module |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -34,7 +34,7 @@ | ||
34 | 34 | typedef string_list::const_iterator iter_type; |
35 | 35 | iter_type it = std::find(objects.begin(), objects.end(), name); |
36 | 36 | if (it != objects.end()) |
37 | - return std::distance(objects.begin(), it); | |
37 | + return static_cast<int>(std::distance(objects.begin(), it)); | |
38 | 38 | else |
39 | 39 | return -1; |
40 | 40 | } |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // builtin_rules.hpp: bjam builtin rules |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -39,10 +39,11 @@ | ||
39 | 39 | HAMIGAKI_BJAM_DECL string_list no_update(context& ctx); |
40 | 40 | HAMIGAKI_BJAM_DECL string_list temporary(context& ctx); |
41 | 41 | HAMIGAKI_BJAM_DECL string_list is_file(context& ctx); |
42 | - | |
42 | +HAMIGAKI_BJAM_DECL string_list hdr_macro(context& ctx); | |
43 | 43 | HAMIGAKI_BJAM_DECL string_list fail_expected(context& ctx); |
44 | 44 | HAMIGAKI_BJAM_DECL string_list rm_old(context& ctx); |
45 | 45 | HAMIGAKI_BJAM_DECL string_list update(context& ctx); |
46 | +HAMIGAKI_BJAM_DECL string_list update_now(context& ctx); | |
46 | 47 | HAMIGAKI_BJAM_DECL string_list subst(context& ctx); |
47 | 48 | HAMIGAKI_BJAM_DECL string_list rule_names(context& ctx); |
48 | 49 | HAMIGAKI_BJAM_DECL string_list var_names(context& ctx); |
@@ -52,9 +53,9 @@ | ||
52 | 53 | HAMIGAKI_BJAM_DECL string_list caller_module(context& ctx); |
53 | 54 | HAMIGAKI_BJAM_DECL string_list back_trace(context& ctx); |
54 | 55 | HAMIGAKI_BJAM_DECL string_list pwd(context& ctx); |
55 | - | |
56 | +HAMIGAKI_BJAM_DECL string_list search_for_target(context& ctx); | |
56 | 57 | HAMIGAKI_BJAM_DECL string_list import_module(context& ctx); |
57 | - | |
58 | +HAMIGAKI_BJAM_DECL string_list imported_modules(context& ctx); | |
58 | 59 | HAMIGAKI_BJAM_DECL string_list instance(context& ctx); |
59 | 60 | HAMIGAKI_BJAM_DECL string_list sort(context& ctx); |
60 | 61 | HAMIGAKI_BJAM_DECL string_list normalize_path(context& ctx); |
@@ -61,13 +62,22 @@ | ||
61 | 62 | HAMIGAKI_BJAM_DECL string_list calc(context& ctx); |
62 | 63 | HAMIGAKI_BJAM_DECL string_list native_rule(context& ctx); |
63 | 64 | HAMIGAKI_BJAM_DECL string_list has_native_rule(context& ctx); |
64 | - | |
65 | +HAMIGAKI_BJAM_DECL string_list user_module(context& ctx); | |
66 | +HAMIGAKI_BJAM_DECL string_list nearest_user_location(context& ctx); | |
65 | 67 | HAMIGAKI_BJAM_DECL string_list check_if_file(context& ctx); |
66 | 68 | |
67 | 69 | #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) |
68 | 70 | HAMIGAKI_BJAM_DECL string_list w32_getreg(context& ctx); |
71 | +HAMIGAKI_BJAM_DECL string_list w32_getregnames(context& ctx); | |
69 | 72 | #endif |
70 | 73 | |
74 | +HAMIGAKI_BJAM_DECL string_list shell(context& ctx); | |
75 | +HAMIGAKI_BJAM_DECL string_list md5(context& ctx); | |
76 | +HAMIGAKI_BJAM_DECL string_list file_open(context& ctx); | |
77 | +HAMIGAKI_BJAM_DECL string_list pad(context& ctx); | |
78 | +HAMIGAKI_BJAM_DECL string_list precious(context& ctx); | |
79 | +HAMIGAKI_BJAM_DECL string_list self_path(context& ctx); | |
80 | + | |
71 | 81 | } // namespace builtins |
72 | 82 | |
73 | 83 | } } // End namespaces bjam, hamigaki. |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // frame.hpp: bjam frame |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -18,12 +18,12 @@ | ||
18 | 18 | struct frame |
19 | 19 | { |
20 | 20 | public: |
21 | - explicit frame(module& m) : module_(&m), line_(1) | |
21 | + explicit frame(module& m) : module_(&m), line_(1), prev_user_(0) | |
22 | 22 | { |
23 | 23 | } |
24 | 24 | |
25 | 25 | frame(module& m, const boost::optional<std::string>& name) |
26 | - : module_(&m), module_name_(name) | |
26 | + : module_(&m), module_name_(name), prev_user_(0) | |
27 | 27 | { |
28 | 28 | } |
29 | 29 |
@@ -88,6 +88,21 @@ | ||
88 | 88 | line_ = n; |
89 | 89 | } |
90 | 90 | |
91 | + frame* prev_user_frame() | |
92 | + { | |
93 | + return prev_user_; | |
94 | + } | |
95 | + | |
96 | + const frame* prev_user_frame() const | |
97 | + { | |
98 | + return prev_user_; | |
99 | + } | |
100 | + | |
101 | + void prev_user_frame(frame* f) | |
102 | + { | |
103 | + prev_user_ = f; | |
104 | + } | |
105 | + | |
91 | 106 | private: |
92 | 107 | module* module_; |
93 | 108 | boost::optional<std::string> module_name_; |
@@ -95,6 +110,7 @@ | ||
95 | 110 | list_of_list arguments_; |
96 | 111 | std::string filename_; |
97 | 112 | int line_; |
113 | + frame* prev_user_; | |
98 | 114 | }; |
99 | 115 | |
100 | 116 | class scoped_change_filename : private boost::noncopyable |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // registry.hpp: Win32 registry utility |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -24,6 +24,12 @@ | ||
24 | 24 | string_list registry_values( |
25 | 25 | const std::string& key, const boost::optional<std::string>& name); |
26 | 26 | |
27 | +HAMIGAKI_BJAM_DECL | |
28 | +string_list registry_subkey_names(const std::string& key); | |
29 | + | |
30 | +HAMIGAKI_BJAM_DECL | |
31 | +string_list registry_value_names(const std::string& key); | |
32 | + | |
27 | 33 | } } } // End namespaces win32, bjam, hamigaki. |
28 | 34 | |
29 | 35 | #ifdef BOOST_HAS_ABI_HEADERS |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // module.hpp: bjam module |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -25,6 +25,11 @@ | ||
25 | 25 | boost::optional<std::string> class_module; |
26 | 26 | std::set<std::string> imported_modules; |
27 | 27 | std::map<std::string,native_rule> native_rules; |
28 | + bool user_module; | |
29 | + | |
30 | + module() : user_module(false) | |
31 | + { | |
32 | + } | |
28 | 33 | }; |
29 | 34 | |
30 | 35 | } } // End namespaces bjam, hamigaki. |
@@ -1,6 +1,6 @@ | ||
1 | 1 | // target.hpp: bjam target |
2 | 2 | |
3 | -// Copyright Takeshi Mouri 2007. | |
3 | +// Copyright Takeshi Mouri 2007-2010. | |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. |
5 | 5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | 6 | // http://www.boost.org/LICENSE_1_0.txt) |
@@ -26,6 +26,7 @@ | ||
26 | 26 | static const unsigned rm_old = 0x0040; |
27 | 27 | static const unsigned fail_expected = 0x0080; |
28 | 28 | static const unsigned is_file = 0x0100; |
29 | + static const unsigned precious = 0x0200; | |
29 | 30 | |
30 | 31 | variable_table variables; |
31 | 32 | std::set<std::string> depended_targets; |