2 // Automated Testing Framework (atf)
4 // Copyright (c) 2007 The NetBSD Foundation, Inc.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
10 // 1. Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #if defined(HAVE_CONFIG_H)
45 #include "atf-c/defs.h"
48 #include "application.hpp"
51 #if !defined(HAVE_VSNPRINTF_IN_STD)
55 #endif // !defined(HAVE_VSNPRINTF_IN_STD)
57 namespace impl
= atf::application
;
58 #define IMPL_NAME "atf::application"
60 // ------------------------------------------------------------------------
61 // The "usage_error" class.
62 // ------------------------------------------------------------------------
64 impl::usage_error::usage_error(const char *fmt
, ...)
66 std::runtime_error("usage_error; message unformatted")
71 std::vsnprintf(m_text
, sizeof(m_text
), fmt
, ap
);
75 impl::usage_error::~usage_error(void)
81 impl::usage_error::what(void)
87 // ------------------------------------------------------------------------
88 // The "application" class.
89 // ------------------------------------------------------------------------
91 impl::option::option(char ch
,
93 const std::string
& desc
) :
101 impl::option::operator<(const impl::option
& o
)
104 return m_character
< o
.m_character
;
107 impl::app::app(const std::string
& description
,
108 const std::string
& manpage
) :
112 m_description(description
),
117 impl::app::~app(void)
122 impl::app::inited(void)
127 impl::app::options_set
128 impl::app::options(void)
130 return specific_options();
134 impl::app::specific_args(void)
140 impl::app::options_set
141 impl::app::specific_options(void)
144 return options_set();
148 impl::app::process_option(int ch ATF_DEFS_ATTRIBUTE_UNUSED
,
149 const char* arg ATF_DEFS_ATTRIBUTE_UNUSED
)
154 impl::app::process_options(void)
159 #if defined(HAVE_GNU_GETOPT)
160 optstr
+= '+'; // Turn on POSIX behavior.
164 options_set opts
= options();
165 for (options_set::const_iterator iter
= opts
.begin();
166 iter
!= opts
.end(); iter
++) {
167 const option
& opt
= (*iter
);
169 optstr
+= opt
.m_character
;
170 if (!opt
.m_argument
.empty())
176 const int old_opterr
= ::opterr
;
178 while ((ch
= ::getopt(m_argc
, m_argv
, optstr
.c_str())) != -1) {
181 throw usage_error("Option -%c requires an argument.",
185 throw usage_error("Unknown option -%c.", ::optopt
);
188 process_option(ch
, ::optarg
);
194 // Clear getopt state just in case the test wants to use it.
197 #if defined(HAVE_OPTRESET)
203 impl::app::run(int argc
, char* const* argv
)
213 m_prog_name
= std::strrchr(m_argv
[0], '/');
214 if (m_prog_name
== NULL
)
215 m_prog_name
= m_argv
[0];
219 // Libtool workaround: if running from within the source tree (binaries
220 // that are not installed yet), skip the "lt-" prefix added to files in
221 // the ".libs" directory to show the real (not temporary) name.
222 if (std::strncmp(m_prog_name
, "lt-", 3) == 0)
225 const std::string bug
=
226 std::string("This is probably a bug in ") + m_prog_name
+
227 " or one of the libraries it uses. Please report this problem to "
228 PACKAGE_BUGREPORT
" and provide as many details as possible "
229 "describing how you got to this condition.";
235 } catch (const usage_error
& e
) {
236 std::cerr
<< m_prog_name
<< ": ERROR: " << e
.what() << "\n";
237 std::cerr
<< m_prog_name
<< ": See " << m_manpage
<< " for usage "
239 errcode
= EXIT_FAILURE
;
240 } catch (const std::runtime_error
& e
) {
241 std::cerr
<< m_prog_name
<< ": ERROR: " << e
.what() << "\n";
242 errcode
= EXIT_FAILURE
;
243 } catch (const std::exception
& e
) {
244 std::cerr
<< m_prog_name
<< ": ERROR: Caught unexpected error: "
246 errcode
= EXIT_FAILURE
;
248 std::cerr
<< m_prog_name
<< ": ERROR: Caught unknown error\n";
249 errcode
= EXIT_FAILURE
;