1 // Copyright Vladimir Prus 2002-2004.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
7 #include <boost/config.hpp>
9 #define BOOST_PROGRAM_OPTIONS_SOURCE
10 #include <boost/program_options/config.hpp>
11 #include <boost/program_options/parsers.hpp>
12 #include <boost/program_options/options_description.hpp>
13 #include <boost/program_options/positional_options.hpp>
14 #include <boost/program_options/detail/cmdline.hpp>
15 #include <boost/program_options/detail/config_file.hpp>
16 #include <boost/program_options/environment_iterator.hpp>
17 #include <boost/program_options/detail/convert.hpp>
19 #include <boost/bind.hpp>
20 #include <boost/throw_exception.hpp>
25 #if !defined(__GNUC__) || __GNUC__ < 3
37 // The 'environ' should be declared in some cases. E.g. Linux man page says:
38 // (This variable must be declared in the user program, but is declared in
39 // the header file unistd.h in case the header files came from libc4 or libc5,
40 // and in case they came from glibc and _GNU_SOURCE was defined.)
41 // To be safe, declare it here.
43 // It appears that on Mac OS X the 'environ' variable is not
44 // available to dynamically linked libraries.
45 // See: http://article.gmane.org/gmane.comp.lib.boost.devel/103843
46 // See: http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html
47 #if defined(__APPLE__) && defined(__DYNAMIC__)
48 // The proper include for this is crt_externs.h, however it's not
49 // available on iOS. The right replacement is not known. See
50 // https://svn.boost.org/trac/boost/ticket/5053
51 extern "C" { extern char ***_NSGetEnviron(void); }
52 #define environ (*_NSGetEnviron())
54 #if defined(__MWERKS__)
57 #if !defined(_WIN32) || defined(__COMO_VERSION__)
58 extern char** environ
;
65 namespace boost
{ namespace program_options
{
67 #ifndef BOOST_NO_STD_WSTRING
69 woption
woption_from_option(const option
& opt
)
72 result
.string_key
= opt
.string_key
;
73 result
.position_key
= opt
.position_key
;
74 result
.unregistered
= opt
.unregistered
;
76 std::transform(opt
.value
.begin(), opt
.value
.end(),
77 back_inserter(result
.value
),
78 boost::bind(from_utf8
, _1
));
80 std::transform(opt
.original_tokens
.begin(),
81 opt
.original_tokens
.end(),
82 back_inserter(result
.original_tokens
),
83 boost::bind(from_utf8
, _1
));
88 basic_parsed_options
<wchar_t>
89 ::basic_parsed_options(const parsed_options
& po
)
90 : description(po
.description
),
91 utf8_encoded_options(po
),
92 m_options_prefix(po
.m_options_prefix
)
94 for (unsigned i
= 0; i
< po
.options
.size(); ++i
)
95 options
.push_back(woption_from_option(po
.options
[i
]));
100 basic_parsed_options
<charT
>
101 parse_config_file(std::basic_istream
<charT
>& is
,
102 const options_description
& desc
,
103 bool allow_unregistered
)
105 set
<string
> allowed_options
;
107 const vector
<shared_ptr
<option_description
> >& options
= desc
.options();
108 for (unsigned i
= 0; i
< options
.size(); ++i
)
110 const option_description
& d
= *options
[i
];
112 if (d
.long_name().empty())
113 boost::throw_exception(
114 error("abbreviated option names are not permitted in options configuration files"));
116 allowed_options
.insert(d
.long_name());
119 // Parser return char strings
120 parsed_options
result(&desc
);
121 copy(detail::basic_config_file_iterator
<charT
>(
122 is
, allowed_options
, allow_unregistered
),
123 detail::basic_config_file_iterator
<charT
>(),
124 back_inserter(result
.options
));
125 // Convert char strings into desired type.
126 return basic_parsed_options
<charT
>(result
);
130 BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options
<char>
131 parse_config_file(std::basic_istream
<char>& is
,
132 const options_description
& desc
,
133 bool allow_unregistered
);
135 #ifndef BOOST_NO_STD_WSTRING
137 BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options
<wchar_t>
138 parse_config_file(std::basic_istream
<wchar_t>& is
,
139 const options_description
& desc
,
140 bool allow_unregistered
);
143 template<class charT
>
144 basic_parsed_options
<charT
>
145 parse_config_file(const char* filename
,
146 const options_description
& desc
,
147 bool allow_unregistered
)
149 // Parser return char strings
150 std::basic_ifstream
< charT
> strm(filename
);
153 boost::throw_exception(reading_file(filename
));
155 return parse_config_file(strm
, desc
, allow_unregistered
);
159 BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options
<char>
160 parse_config_file(const char* filename
,
161 const options_description
& desc
,
162 bool allow_unregistered
);
164 #ifndef BOOST_NO_STD_WSTRING
166 BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options
<wchar_t>
167 parse_config_file(const char* filename
,
168 const options_description
& desc
,
169 bool allow_unregistered
);
173 // This versio, which accepts any options without validation, is disabled,
174 // in the hope that nobody will need it and we cant drop it altogether.
175 // Besides, probably the right way to handle all options is the '*' name.
177 BOOST_PROGRAM_OPTIONS_DECL parsed_options
178 parse_config_file(std::istream
& is
)
180 detail::config_file_iterator
cf(is
, false);
181 parsed_options
result(0);
182 copy(cf
, detail::config_file_iterator(),
183 back_inserter(result
.options
));
188 BOOST_PROGRAM_OPTIONS_DECL parsed_options
189 parse_environment(const options_description
& desc
,
190 const function1
<std::string
, std::string
>& name_mapper
)
192 parsed_options
result(&desc
);
194 for(environment_iterator
i(environ
), e
; i
!= e
; ++i
) {
195 string option_name
= name_mapper(i
->first
);
197 if (!option_name
.empty()) {
199 n
.string_key
= option_name
;
200 n
.value
.push_back(i
->second
);
201 result
.options
.push_back(n
);
209 class prefix_name_mapper
{
211 prefix_name_mapper(const std::string
& prefix
)
215 std::string
operator()(const std::string
& s
)
218 if (s
.find(prefix
) == 0) {
219 for(string::size_type n
= prefix
.size(); n
< s
.size(); ++n
)
221 // Intel-Win-7.1 does not understand
222 // push_back on string.
223 result
+= static_cast<char>(tolower(s
[n
]));
233 BOOST_PROGRAM_OPTIONS_DECL parsed_options
234 parse_environment(const options_description
& desc
,
235 const std::string
& prefix
)
237 return parse_environment(desc
, detail::prefix_name_mapper(prefix
));
240 BOOST_PROGRAM_OPTIONS_DECL parsed_options
241 parse_environment(const options_description
& desc
, const char* prefix
)
243 return parse_environment(desc
, string(prefix
));