Line data Source code
1 : /*
2 : * License:
3 : * Copyright (c) 2006-2019 Made to Order Software Corp. All Rights Reserved
4 : *
5 : * https://snapwebsites.org/
6 : * contact@m2osw.com
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 2 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License along
19 : * with this program; if not, write to the Free Software Foundation, Inc.,
20 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 : *
22 : * Authors:
23 : * Alexis Wilke alexis@m2osw.com
24 : * Doug Barbieri doug@m2osw.com
25 : */
26 :
27 : /** \file
28 : * \brief Advanced getopt data access implementation.
29 : *
30 : * The advgetopt class has many function used to access the data in the
31 : * class. These functions are gathered here.
32 : */
33 :
34 : // self
35 : //
36 : #include "advgetopt/advgetopt.h"
37 :
38 : // advgetopt lib
39 : //
40 : #include "advgetopt/exception.h"
41 :
42 :
43 : // last include
44 : //
45 : #include <snapdev/poison.h>
46 :
47 :
48 :
49 : namespace advgetopt
50 : {
51 :
52 :
53 : /** \brief Transform the argv[0] parameter in the program name.
54 : *
55 : * This function is transforms the first command line argument in a program
56 : * name. It will define two versions, the basename and the fullname which
57 : * you can access with the get_program_name() and get_program_fullname()
58 : * functions.
59 : *
60 : * \note
61 : * The %p and %*p options of the process_help_string() function make use
62 : * of this parameter. If you never call this function, they both use an
63 : * empty string as the program name.
64 : *
65 : * \exception getopt_exception_logic
66 : * If you call this function with a null pointer, then it raises this
67 : * exception.
68 : *
69 : * \param[in] argv The arguments vector.
70 : *
71 : * \sa get_program_name()
72 : * \sa get_program_fullname()
73 : * \sa process_help_string()
74 : */
75 258 : void getopt::parse_program_name(char * argv[])
76 : {
77 258 : if(argv == nullptr)
78 : {
79 1 : throw getopt_exception_logic("argv pointer cannot be nullptr");
80 : }
81 257 : if(argv[0] != nullptr)
82 : {
83 256 : f_program_fullname = argv[0];
84 : }
85 :
86 257 : std::string::size_type p(f_program_fullname.find_last_of('/'));
87 257 : if(p == std::string::npos)
88 : {
89 : // MS-Windows path uses \ instead of /
90 : //
91 6 : p = f_program_fullname.find_last_of('\\');
92 : }
93 257 : if(p != std::string::npos)
94 : {
95 : // remove the path
96 : //
97 253 : f_program_name = f_program_fullname.substr(p + 1);
98 : }
99 : else
100 : {
101 4 : f_program_name = f_program_fullname;
102 : }
103 257 : }
104 :
105 :
106 : /** \brief Get the full name of the program.
107 : *
108 : * This function return the name of the program exactly as it was passed to
109 : * the program via argv[0].
110 : *
111 : * The reset() function will reset this parameter. If you are creating
112 : * internal lists of parameters that you want to parse with the same
113 : * getopt object and your main getopt object, then you may want to
114 : * consider using this function to define argv[0] of your new list:
115 : *
116 : * \code
117 : * std::vector<std::string> args;
118 : * args.push_back(my_opts.get_program_fullname());
119 : * args.push_back("--test");
120 : * [...]
121 : * // the following probably require some const_cast<>(), but that's the idea
122 : * my_opts.reset(args.size(), &args[0], ...);
123 : * \endcode
124 : *
125 : * \return The contents of the argv[0] parameter as defined on construction.
126 : *
127 : * \sa parse_program_name()
128 : */
129 167 : std::string getopt::get_program_fullname() const
130 : {
131 167 : return f_program_fullname;
132 : }
133 :
134 :
135 : /** \brief Get the basename of the program.
136 : *
137 : * This function retrieves the basename, the name of the program with its
138 : * path trimmed, from this getopt object.
139 : *
140 : * This is defined from the argv[0] parameter passed to the constructor or
141 : * the last reset() call.
142 : *
143 : * \return The basename of the program.
144 : *
145 : * \sa parse_program_name()
146 : */
147 167 : std::string getopt::get_program_name() const
148 : {
149 167 : return f_program_name;
150 : }
151 :
152 :
153 : /** \brief Retrieve the project name if one is defined.
154 : *
155 : * This function returns the name of the project as defined in the
156 : * options_environment structure passed to the constructor.
157 : *
158 : * For example, the snapwebsites project makes use of "snapwebsites"
159 : * name as its common project name. Many of the configuration files are
160 : * found under that sub-folder. This ensures that the configuration files
161 : * are searched for under the indicated folders and again under:
162 : *
163 : * \code
164 : * <existing path>/<project name>.d/<basename>
165 : * \endcode
166 : *
167 : * So if you have a configuration file named "snapserver.conf" with
168 : * a path such as "/etc/snapwebsites", you end up with:
169 : *
170 : * \code
171 : * "/etc/snapwebsites/snapserver.conf"
172 : * "/etc/snapwebsites/snapwebsites.d/snapserver.conf"
173 : * \endcode
174 : *
175 : * Notice that the loader adds a ".d" at the end of the project name.
176 : * Also, if the user were to specify a different filename with the
177 : * --config command line option, it could end up like this:
178 : *
179 : * \code
180 : * ... --config /home/alexis/.config/iplock/iplock.conf ...
181 : *
182 : * # First we read this file:
183 : * "/home/alexis/.config/iplock/iplock.conf"
184 : *
185 : * # Second we read this file (assuming the same project name
186 : * # of "snapwebsites"):
187 : * "/home/alexis/.config/iplock/snapwebsites.d/iplock.conf"
188 : * \endcode
189 : *
190 : * The order is important as well. We first load the direct path, then
191 : * the path with the sub-folder. Finally, we move forward to the next
192 : * configuration file. We ignore errors when a file can't be loaded or
193 : * is missing.
194 : *
195 : * \return The name of the project, maybe empty if undefined.
196 : */
197 2 : std::string getopt::get_project_name() const
198 : {
199 2 : if(f_options_environment.f_project_name == nullptr)
200 : {
201 1 : return std::string();
202 : }
203 1 : return f_options_environment.f_project_name;
204 : }
205 :
206 :
207 :
208 :
209 : } // namespace advgetopt
210 : // vim: ts=4 sw=4 et
|