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