sbuild
1.5.4
|
00001 /* Copyright © 2005-2009 Roger Leigh <rleigh@debian.org> 00002 * 00003 * schroot is free software: you can redistribute it and/or modify it 00004 * under the terms of the GNU General Public License as published by 00005 * the Free Software Foundation, either version 3 of the License, or 00006 * (at your option) any later version. 00007 * 00008 * schroot is distributed in the hope that it will be useful, but 00009 * WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program. If not, see 00015 * <http://www.gnu.org/licenses/>. 00016 * 00017 *********************************************************************/ 00018 00019 #ifndef SBUILD_BASIC_KEYFILE_H 00020 #define SBUILD_BASIC_KEYFILE_H 00021 00022 #include <sbuild/sbuild-i18n.h> 00023 #include <sbuild/sbuild-log.h> 00024 #include <sbuild/sbuild-keyfile-base.h> 00025 #include <sbuild/sbuild-parse-error.h> 00026 #include <sbuild/sbuild-parse-value.h> 00027 #include <sbuild/sbuild-types.h> 00028 #include <sbuild/sbuild-tr1types.h> 00029 #include <sbuild/sbuild-util.h> 00030 00031 #include <cassert> 00032 #include <map> 00033 #include <string> 00034 #include <sstream> 00035 00036 #include <boost/format.hpp> 00037 00038 namespace sbuild 00039 { 00043 template <typename K> 00044 class basic_keyfile_parser 00045 { 00046 public: 00048 typedef keyfile_base::error error; 00049 00051 basic_keyfile_parser (): 00052 group(), 00053 group_set(false), 00054 key(), 00055 key_set(false), 00056 value(), 00057 value_set(false), 00058 comment(), 00059 comment_set(false), 00060 line_number(0) 00061 { 00062 } 00063 00065 virtual ~basic_keyfile_parser () 00066 { 00067 } 00068 00070 typename K::group_name_type group; 00071 00073 bool group_set; 00074 00076 typename K::key_type key; 00077 00079 bool key_set; 00080 00082 typename K::value_type value; 00083 00085 bool value_set; 00086 00088 typename K::comment_type comment; 00089 00091 bool comment_set; 00092 00094 typename K::size_type line_number; 00095 00100 virtual void 00101 begin () 00102 { 00103 line_number = 0; 00104 } 00105 00116 virtual void 00117 parse_line (std::string const& line) 00118 { 00119 ++line_number; 00120 } 00121 00126 virtual void 00127 end() 00128 { 00129 } 00130 }; 00131 00137 template <typename K, typename P = basic_keyfile_parser<K> > 00138 class basic_keyfile : public keyfile_base 00139 { 00140 public: 00142 typedef typename K::group_name_type group_name_type; 00143 00145 typedef typename K::key_type key_type; 00146 00148 typedef typename K::value_type value_type; 00149 00151 typedef typename K::comment_type comment_type; 00152 00154 typedef typename K::size_type size_type; 00155 00157 typedef std::vector<group_name_type> group_list; 00158 00160 typedef std::vector<value_type> value_list; 00161 00162 private: 00164 typedef P parse_type; 00165 00167 typedef std::tuple<key_type,value_type,comment_type,size_type> 00168 item_type; 00169 00171 typedef std::map<key_type,item_type> item_map_type; 00172 00174 typedef std::tuple<group_name_type,item_map_type,comment_type,size_type> group_type; 00175 00177 typedef std::map<group_name_type,group_type> group_map_type; 00178 00180 typedef std::vector<key_type> key_list; 00181 00182 public: 00184 basic_keyfile (); 00185 00191 basic_keyfile (std::string const& file); 00192 00198 basic_keyfile (std::istream& stream); 00199 00201 virtual ~basic_keyfile (); 00202 00209 group_list 00210 get_groups () const; 00211 00219 key_list 00220 get_keys (group_name_type const& group) const; 00221 00230 void 00231 check_keys (group_name_type const& group, 00232 key_list const& keys) const; 00233 00240 bool 00241 has_group (group_name_type const& group) const; 00242 00250 bool 00251 has_key (group_name_type const& group, 00252 key_type const& key) const; 00253 00261 void 00262 set_group (group_name_type const& group, 00263 comment_type const& comment); 00264 00273 void 00274 set_group (group_name_type const& group, 00275 comment_type const& comment, 00276 size_type line); 00277 00284 comment_type 00285 get_comment (group_name_type const& group) const; 00286 00294 comment_type 00295 get_comment (group_name_type const& group, 00296 key_type const& key) const; 00297 00304 size_type 00305 get_line (group_name_type const& group) const; 00306 00314 size_type 00315 get_line (group_name_type const& group, 00316 key_type const& key) const; 00317 00328 template <typename T> 00329 bool 00330 get_value (group_name_type const& group, 00331 key_type const& key, 00332 T& value) const 00333 { 00334 log_debug(DEBUG_INFO) << "Getting keyfile group=" << group 00335 << ", key=" << key << std::endl; 00336 const item_type *found_item = find_item(group, key); 00337 if (found_item) 00338 { 00339 value_type const& strval(std::get<1>(*found_item)); 00340 try 00341 { 00342 parse_value(strval, value); 00343 return true; 00344 } 00345 catch (parse_value_error const& e) 00346 { 00347 size_type line = get_line(group, key); 00348 if (line) 00349 { 00350 error ep(line, group, key, PASSTHROUGH_LGK, e); 00351 log_exception_warning(ep); 00352 } 00353 else 00354 { 00355 error ep(group, key, PASSTHROUGH_GK, e); 00356 log_exception_warning(ep); 00357 } 00358 return false; 00359 } 00360 } 00361 log_debug(DEBUG_NOTICE) << "key not found" << std::endl; 00362 return false; 00363 } 00364 00377 template <typename T> 00378 bool 00379 get_value (group_name_type const& group, 00380 key_type const& key, 00381 priority priority, 00382 T& value) const 00383 { 00384 bool status = get_value(group, key, value); 00385 check_priority(group, key, priority, status); 00386 return status; 00387 } 00388 00398 bool 00399 get_locale_string (group_name_type const& group, 00400 key_type const& key, 00401 value_type& value) const; 00402 00414 bool 00415 get_locale_string (group_name_type const& group, 00416 key_type const& key, 00417 priority priority, 00418 value_type& value) const; 00419 00430 bool 00431 get_locale_string (group_name_type const& group, 00432 key_type const& key, 00433 std::string const& locale, 00434 value_type& value) const; 00435 00449 bool 00450 get_locale_string (group_name_type const& group, 00451 key_type const& key, 00452 std::string const& locale, 00453 priority priority, 00454 value_type& value) const; 00455 00468 template <typename C> 00469 bool 00470 get_list_value (group_name_type const& group, 00471 key_type const& key, 00472 C& container) const 00473 { 00474 value_type item_value; 00475 if (get_value(group, key, item_value)) 00476 { 00477 value_list items = split_string(item_value, 00478 this->separator); 00479 for (typename value_list::const_iterator pos = items.begin(); 00480 pos != items.end(); 00481 ++pos 00482 ) 00483 { 00484 typename C::value_type tmp; 00485 00486 try 00487 { 00488 parse_value(*pos, tmp); 00489 } 00490 catch (parse_value_error const& e) 00491 { 00492 size_type line = get_line(group, key); 00493 if (line) 00494 { 00495 error ep(line, group, key, PASSTHROUGH_LGK, e); 00496 log_exception_warning(ep); 00497 } 00498 else 00499 { 00500 error ep(group, key, PASSTHROUGH_GK, e); 00501 log_exception_warning(ep); 00502 } 00503 return false; 00504 } 00505 00506 container.push_back(tmp); 00507 } 00508 return true; 00509 } 00510 return false; 00511 } 00512 00527 template <typename C> 00528 bool 00529 get_list_value (group_name_type const& group, 00530 key_type const& key, 00531 priority priority, 00532 C& container) const 00533 { 00534 bool status = get_list_value(group, key, container); 00535 check_priority(group, key, priority, status); 00536 return status; 00537 } 00538 00551 template <typename C> 00552 bool 00553 get_set_value (group_name_type const& group, 00554 key_type const& key, 00555 C& container) const 00556 { 00557 value_type item_value; 00558 if (get_value(group, key, item_value)) 00559 { 00560 value_list items = split_string(item_value, 00561 this->separator); 00562 for (typename value_list::const_iterator pos = items.begin(); 00563 pos != items.end(); 00564 ++pos 00565 ) 00566 { 00567 typename C::value_type tmp; 00568 00569 try 00570 { 00571 parse_value(*pos, tmp); 00572 } 00573 catch (parse_value_error const& e) 00574 { 00575 size_type line = get_line(group, key); 00576 if (line) 00577 { 00578 error ep(line, group, key, PASSTHROUGH_LGK, e); 00579 log_exception_warning(ep); 00580 } 00581 else 00582 { 00583 error ep(group, key, PASSTHROUGH_GK, e); 00584 log_exception_warning(ep); 00585 } 00586 return false; 00587 } 00588 00589 container.insert(tmp); 00590 } 00591 return true; 00592 } 00593 return false; 00594 } 00595 00610 template <typename C> 00611 bool 00612 get_set_value (group_name_type const& group, 00613 key_type const& key, 00614 priority priority, 00615 C& container) const 00616 { 00617 bool status = get_set_value(group, key, container); 00618 check_priority(group, key, priority, status); 00619 return status; 00620 } 00621 00630 template <typename T> 00631 void 00632 set_value (group_name_type const& group, 00633 key_type const& key, 00634 T const& value) 00635 { 00636 set_value(group, key, value, comment_type()); 00637 } 00638 00648 template <typename T> 00649 void 00650 set_value (group_name_type const& group, 00651 key_type const& key, 00652 T const& value, 00653 comment_type const& comment) 00654 { 00655 set_value(group, key, value, comment, 0); 00656 } 00657 00668 template <typename T> 00669 void 00670 set_value (group_name_type const& group, 00671 key_type const& key, 00672 T const& value, 00673 comment_type const& comment, 00674 size_type line) 00675 { 00676 std::ostringstream os; 00677 os.imbue(std::locale::classic()); 00678 os << std::boolalpha << value; 00679 00680 set_group(group, ""); 00681 group_type *found_group = find_group(group); 00682 assert (found_group != 0); // should not fail 00683 00684 item_map_type& items = std::get<1>(*found_group); 00685 00686 typename item_map_type::iterator pos = items.find(key); 00687 if (pos != items.end()) 00688 items.erase(pos); 00689 items.insert 00690 (typename item_map_type::value_type(key, 00691 item_type(key, os.str(), 00692 comment, line))); 00693 } 00694 00704 template <typename I> 00705 void 00706 set_list_value (group_name_type const& group, 00707 key_type const& key, 00708 I begin, 00709 I end) 00710 { 00711 set_list_value(group, key, begin, end, comment_type()); 00712 } 00713 00724 template <typename I> 00725 void 00726 set_list_value (group_name_type const& group, 00727 key_type const& key, 00728 I begin, 00729 I end, 00730 comment_type const& comment) 00731 { 00732 set_list_value (group, key, begin, end, comment, 0); 00733 } 00734 00746 template <typename I> 00747 void 00748 set_list_value (group_name_type const& group, 00749 key_type const& key, 00750 I begin, 00751 I end, 00752 comment_type const& comment, 00753 size_type line) 00754 { 00755 value_type strval; 00756 00757 for (I pos = begin; pos != end;) 00758 { 00759 std::ostringstream os; 00760 os.imbue(std::locale::classic()); 00761 os << std::boolalpha << *pos; 00762 if (os) 00763 { 00764 strval += os.str(); 00765 if (++pos != end) 00766 strval += this->separator; 00767 } 00768 } 00769 00770 set_value (group, key, strval, comment, line); 00771 } 00772 00782 template <typename I> 00783 void 00784 set_set_value (group_name_type const& group, 00785 key_type const& key, 00786 I begin, 00787 I end) 00788 { 00789 std::vector<typename std::iterator_traits<I>::value_type> l(begin, end); 00790 std::sort(l.begin(), l.end()); 00791 set_list_value(group, key, l.begin(), l.end()); 00792 } 00793 00804 template <typename I> 00805 void 00806 set_set_value (group_name_type const& group, 00807 key_type const& key, 00808 I begin, 00809 I end, 00810 comment_type const& comment) 00811 { 00812 std::vector<typename std::iterator_traits<I>::value_type> l(begin, end); 00813 std::sort(l.begin(), l.end()); 00814 set_list_value(group, key, l.begin(), l.end(), comment); 00815 } 00816 00828 template <typename I> 00829 void 00830 set_set_value (group_name_type const& group, 00831 key_type const& key, 00832 I begin, 00833 I end, 00834 comment_type const& comment, 00835 size_type line) 00836 { 00837 std::vector<typename std::iterator_traits<I>::value_type> l(begin, end); 00838 std::sort(l.begin(), l.end()); 00839 set_list_value(group, key, l.begin(), l.end(), comment, line); 00840 } 00841 00847 void 00848 remove_group (group_name_type const& group); 00849 00856 void 00857 remove_key (group_name_type const& group, 00858 key_type const& key); 00859 00866 basic_keyfile& 00867 operator += (basic_keyfile const& rhs); 00868 00876 template <typename _K, typename _P> 00877 friend basic_keyfile<_K, _P> 00878 operator + (basic_keyfile<_K, _P> const& lhs, 00879 basic_keyfile<_K, _P> const& rhs); 00880 00888 template <class charT, class traits> 00889 friend 00890 std::basic_istream<charT,traits>& 00891 operator >> (std::basic_istream<charT,traits>& stream, 00892 basic_keyfile& kf) 00893 { 00894 basic_keyfile tmp; 00895 parse_type state; 00896 std::string line; 00897 00898 state.begin(); 00899 00900 while (std::getline(stream, line)) 00901 { 00902 state.parse_line(line); 00903 00904 // Insert group 00905 if (state.group_set) 00906 { 00907 if (tmp.has_group(state.group)) 00908 throw error(state.line_number, DUPLICATE_GROUP, state.group); 00909 else 00910 tmp.set_group(state.group, state.comment, state.line_number); 00911 } 00912 00913 // Insert item 00914 if (state.key_set && state.value_set) 00915 { 00916 if (tmp.has_key(state.group, state.key)) 00917 throw error(state.line_number, state.group, DUPLICATE_KEY, state.key); 00918 else 00919 tmp.set_value(state.group, state.key, state.value, state.comment, state.line_number); 00920 } 00921 } 00922 00923 state.end(); 00924 // TODO: do inserts here as well. 00925 00926 kf += tmp; 00927 00928 return stream; 00929 } 00930 00938 template <class charT, class traits> 00939 friend 00940 std::basic_ostream<charT,traits>& 00941 operator << (std::basic_ostream<charT,traits>& stream, 00942 basic_keyfile const& kf) 00943 { 00944 size_type group_count = 0; 00945 00946 for (typename group_map_type::const_iterator gp = kf.groups.begin(); 00947 gp != kf.groups.end(); 00948 ++gp, ++group_count) 00949 { 00950 if (group_count > 0) 00951 stream << '\n'; 00952 00953 group_type const& group = gp->second; 00954 group_name_type const& groupname = std::get<0>(group); 00955 comment_type const& comment = std::get<2>(group); 00956 00957 if (comment.length() > 0) 00958 print_comment(comment, stream); 00959 00960 stream << '[' << groupname << ']' << '\n'; 00961 00962 item_map_type const& items(std::get<1>(group)); 00963 for (typename item_map_type::const_iterator it = items.begin(); 00964 it != items.end(); 00965 ++it) 00966 { 00967 item_type const& item = it->second; 00968 key_type const& key(std::get<0>(item)); 00969 value_type const& value(std::get<1>(item)); 00970 comment_type const& comment(std::get<2>(item)); 00971 00972 if (comment.length() > 0) 00973 print_comment(comment, stream); 00974 00975 stream << key << '=' << value << '\n'; 00976 } 00977 } 00978 00979 return stream; 00980 } 00981 00982 private: 00989 const group_type * 00990 find_group (group_name_type const& group) const; 00991 00998 group_type * 00999 find_group (group_name_type const& group); 01000 01008 const item_type * 01009 find_item (group_name_type const& group, 01010 key_type const& key) const; 01011 01019 item_type * 01020 find_item (group_name_type const& group, 01021 key_type const& key); 01022 01031 void 01032 check_priority (group_name_type const& group, 01033 key_type const& key, 01034 priority priority, 01035 bool valid) const; 01036 01048 static void 01049 print_comment (comment_type const& comment, 01050 std::ostream& stream); 01051 01053 group_map_type groups; 01055 value_type separator; 01056 01057 public: 01070 template<class C, typename T> 01071 static void 01072 set_object_value (C const& object, 01073 T (C::* method)() const, 01074 basic_keyfile& basic_keyfile, 01075 group_name_type const& group, 01076 key_type const& key) 01077 { 01078 try 01079 { 01080 if (method) 01081 basic_keyfile.set_value(group, key, (object.*method)()); 01082 } 01083 catch (std::runtime_error const& e) 01084 { 01085 throw error(group, key, PASSTHROUGH_GK, e); 01086 } 01087 } 01088 01101 template<class C, typename T> 01102 static void 01103 set_object_value (C const& object, 01104 T const& (C::* method)() const, 01105 basic_keyfile& basic_keyfile, 01106 group_name_type const& group, 01107 key_type const& key) 01108 { 01109 try 01110 { 01111 if (method) 01112 basic_keyfile.set_value(group, key, (object.*method)()); 01113 } 01114 catch (std::runtime_error const& e) 01115 { 01116 throw error(group, key, PASSTHROUGH_GK, e); 01117 } 01118 } 01119 01133 template<class C, typename T> 01134 static void 01135 set_object_list_value (C const& object, 01136 T (C::* method)() const, 01137 basic_keyfile& basic_keyfile, 01138 group_name_type const& group, 01139 key_type const& key) 01140 { 01141 try 01142 { 01143 if (method) 01144 basic_keyfile.set_list_value(group, key, 01145 (object.*method)().begin(), 01146 (object.*method)().end()); 01147 } 01148 catch (std::runtime_error const& e) 01149 { 01150 throw error(group, key, PASSTHROUGH_GK, e); 01151 } 01152 } 01153 01168 template<class C, typename T> 01169 static void 01170 set_object_list_value (C const& object, 01171 T const& (C::* method)() const, 01172 basic_keyfile& basic_keyfile, 01173 group_name_type const& group, 01174 key_type const& key) 01175 { 01176 try 01177 { 01178 if (method) 01179 basic_keyfile.set_list_value(group, key, 01180 (object.*method)().begin(), 01181 (object.*method)().end()); 01182 } 01183 catch (std::runtime_error const& e) 01184 { 01185 throw error(group, key, PASSTHROUGH_GK, e); 01186 } 01187 } 01188 01202 template<class C, typename T> 01203 static void 01204 set_object_set_value (C const& object, 01205 T (C::* method)() const, 01206 basic_keyfile& basic_keyfile, 01207 group_name_type const& group, 01208 key_type const& key) 01209 { 01210 try 01211 { 01212 if (method) 01213 basic_keyfile.set_set_value(group, key, 01214 (object.*method)().begin(), 01215 (object.*method)().end()); 01216 } 01217 catch (std::runtime_error const& e) 01218 { 01219 throw error(group, key, PASSTHROUGH_GK, e); 01220 } 01221 } 01222 01237 template<class C, typename T> 01238 static void 01239 set_object_set_value (C const& object, 01240 T const& (C::* method)() const, 01241 basic_keyfile& basic_keyfile, 01242 group_name_type const& group, 01243 key_type const& key) 01244 { 01245 try 01246 { 01247 if (method) 01248 basic_keyfile.set_set_value(group, key, 01249 (object.*method)().begin(), 01250 (object.*method)().end()); 01251 } 01252 catch (std::runtime_error const& e) 01253 { 01254 throw error(group, key, PASSTHROUGH_GK, e); 01255 } 01256 } 01257 01272 template<class C, typename T> 01273 static void 01274 get_object_value (C& object, 01275 void (C::* method)(T param), 01276 basic_keyfile const& basic_keyfile, 01277 group_name_type const& group, 01278 key_type const& key, 01279 basic_keyfile::priority priority) 01280 { 01281 try 01282 { 01283 T value; 01284 if (basic_keyfile.get_value(group, key, priority, value) 01285 && method) 01286 (object.*method)(value); 01287 } 01288 catch (std::runtime_error const& e) 01289 { 01290 size_type line = basic_keyfile.get_line(group, key); 01291 if (line) 01292 throw error(line, group, key, PASSTHROUGH_LGK, e); 01293 else 01294 throw error(group, key, PASSTHROUGH_GK, e); 01295 } 01296 } 01297 01312 template<class C, typename T> 01313 static void 01314 get_object_value (C& object, 01315 void (C::* method)(T const& param), 01316 basic_keyfile const& basic_keyfile, 01317 group_name_type const& group, 01318 key_type const& key, 01319 basic_keyfile::priority priority) 01320 { 01321 try 01322 { 01323 T value; 01324 if (basic_keyfile.get_value(group, key, priority, value) 01325 && method) 01326 (object.*method)(value); 01327 } 01328 catch (std::runtime_error const& e) 01329 { 01330 size_type line = basic_keyfile.get_line(group, key); 01331 if (line) 01332 throw error(line, group, key, PASSTHROUGH_LGK, e); 01333 else 01334 throw error(group, key, PASSTHROUGH_GK, e); 01335 } 01336 } 01337 01352 template<class C, typename T> 01353 static void 01354 get_object_list_value (C& object, 01355 void (C::* method)(T param), 01356 basic_keyfile const& basic_keyfile, 01357 group_name_type const& group, 01358 key_type const& key, 01359 basic_keyfile::priority priority) 01360 { 01361 try 01362 { 01363 T value; 01364 if (basic_keyfile.get_list_value(group, key, priority, value) 01365 && method) 01366 (object.*method)(value); 01367 } 01368 catch (std::runtime_error const& e) 01369 { 01370 size_type line = basic_keyfile.get_line(group, key); 01371 if (line) 01372 throw error(line, group, key, PASSTHROUGH_LGK, e); 01373 else 01374 throw error(group, key, PASSTHROUGH_GK, e); 01375 throw error(basic_keyfile.get_line(group, key), 01376 group, key, e); 01377 } 01378 } 01379 01395 template<class C, typename T> 01396 static void 01397 get_object_list_value (C& object, 01398 void (C::* method)(T const& param), 01399 basic_keyfile const& basic_keyfile, 01400 group_name_type const& group, 01401 key_type const& key, 01402 basic_keyfile::priority priority) 01403 { 01404 try 01405 { 01406 T value; 01407 if (basic_keyfile.get_list_value(group, key, priority, value) 01408 && method) 01409 (object.*method)(value); 01410 } 01411 catch (std::runtime_error const& e) 01412 { 01413 size_type line = basic_keyfile.get_line(group, key); 01414 if (line) 01415 throw error(line, group, key, PASSTHROUGH_LGK, e); 01416 else 01417 throw error(group, key, PASSTHROUGH_GK, e); 01418 throw error(basic_keyfile.get_line(group, key), 01419 group, key, e); 01420 } 01421 } 01422 01437 template<class C, typename T> 01438 static void 01439 get_object_set_value (C& object, 01440 void (C::* method)(T param), 01441 basic_keyfile const& basic_keyfile, 01442 group_name_type const& group, 01443 key_type const& key, 01444 basic_keyfile::priority priority) 01445 { 01446 try 01447 { 01448 T value; 01449 if (basic_keyfile.get_set_value(group, key, priority, value) 01450 && method) 01451 (object.*method)(value); 01452 } 01453 catch (std::runtime_error const& e) 01454 { 01455 size_type line = basic_keyfile.get_line(group, key); 01456 if (line) 01457 throw error(line, group, key, PASSTHROUGH_LGK, e); 01458 else 01459 throw error(group, key, PASSTHROUGH_GK, e); 01460 throw error(basic_keyfile.get_line(group, key), 01461 group, key, e); 01462 } 01463 } 01464 01480 template<class C, typename T> 01481 static void 01482 get_object_set_value (C& object, 01483 void (C::* method)(T const& param), 01484 basic_keyfile const& basic_keyfile, 01485 group_name_type const& group, 01486 key_type const& key, 01487 basic_keyfile::priority priority) 01488 { 01489 try 01490 { 01491 T value; 01492 if (basic_keyfile.get_set_value(group, key, priority, value) 01493 && method) 01494 (object.*method)(value); 01495 } 01496 catch (std::runtime_error const& e) 01497 { 01498 size_type line = basic_keyfile.get_line(group, key); 01499 if (line) 01500 throw error(line, group, key, PASSTHROUGH_LGK, e); 01501 else 01502 throw error(group, key, PASSTHROUGH_GK, e); 01503 throw error(basic_keyfile.get_line(group, key), 01504 group, key, e); 01505 } 01506 } 01507 }; 01508 01509 } 01510 01511 #include <sbuild/sbuild-basic-keyfile.tcc> 01512 01513 #endif /* SBUILD_BASIC_KEYFILE_H */ 01514 01515 /* 01516 * Local Variables: 01517 * mode:C++ 01518 * End: 01519 */