]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/CommandLine.cc
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
11 #include "CommandLine.h"
12 #include "sbuf/SBuf.h"
15 ResetGetopt(const bool allowStderrWarnings
)
17 opterr
= allowStderrWarnings
;
18 // Resetting optind to zero instead of conventional '1' has an
19 // advantage, since it also resets getopt(3) global state.
20 // getopt(3) always skips argv[0], even if optind is zero
24 CommandLine::CommandLine(int argC
, char *argV
[], const char *shortRules
, const RawLongOption
*longRules
):
26 shortOptions_(shortRules
? xstrdup(shortRules
) : ""),
29 assert(argC
> 0); // C++ main() requirement that makes our arg0() safe
33 argv_
.reserve(argC
+1);
34 for (int i
= 0; i
< argC
; ++i
)
35 argv_
.push_back(xstrdup(argV
[i
]));
36 argv_
.push_back(nullptr); // POSIX argv "must be terminated by a null pointer"
38 /* copy grammar rules for the long options */
40 for (auto longOption
= longRules
; longOption
->name
; ++longOption
)
41 longOptions_
.emplace_back(*longOption
);
42 longOptions_
.emplace_back();
46 CommandLine::CommandLine(const CommandLine
&them
):
47 CommandLine(them
.argc(), them
.argv(), them
.shortOptions_
, them
.longOptions())
52 CommandLine::operator =(const CommandLine
&them
)
54 // cannot just swap(*this, them): std::swap(T,T) may call this assignment op
55 CommandLine
tmp(them
);
56 std::swap(argv_
, tmp
.argv_
);
57 std::swap(shortOptions_
, tmp
.shortOptions_
);
58 std::swap(longOptions_
, tmp
.longOptions_
);
62 CommandLine::~CommandLine()
71 CommandLine::hasOption(const int optIdToFind
, const char **optValue
) const
73 ResetGetopt(false); // avoid duped warnings; forEachOption() will complain
75 while (nextOption(optId
)) {
76 if (optId
== optIdToFind
) {
78 // do not need to copy the optarg string because it is a pointer into the original
79 // argv array (https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html)
89 CommandLine::forEachOption(Visitor visitor
) const
93 while (nextOption(optId
))
94 visitor(optId
, optarg
);
97 /// extracts the next option (if any)
98 /// \returns whether the option was extracted
99 /// throws on unknown option or missing required argument
101 CommandLine::nextOption(int &optId
) const
103 optId
= getopt_long(argc(), argv(), shortOptions_
, longOptions(), nullptr);
104 if ((optId
== ':' && shortOptions_
[0] == ':') || optId
== '?') {
105 assert(optind
> 0 && static_cast<unsigned int>(optind
) < argv_
.size());
107 errMsg
.Printf("'%s': %s", argv_
[optind
- 1], optId
== '?' ?
108 "unrecognized option or missing required argument" : "missing required argument");
109 throw TexcHere(errMsg
);
115 CommandLine::resetArg0(const char *programName
)
119 argv_
[0] = xstrdup(programName
);
123 CommandLine::pushFrontOption(const char *name
, const char *value
)
126 argv_
.insert(argv_
.begin() + 1, xstrdup(name
));
128 argv_
.insert(argv_
.begin() + 2, xstrdup(value
));
131 LongOption::LongOption() :
132 option({nullptr, 0, nullptr, 0})
136 LongOption::LongOption(const RawLongOption
&opt
) :
137 option({nullptr, 0, nullptr, 0})
142 LongOption::LongOption(const LongOption
&opt
):
143 LongOption(static_cast<const RawLongOption
&>(opt
))
147 LongOption::~LongOption()
153 LongOption::operator =(const LongOption
&opt
)
156 copy(static_cast<const RawLongOption
&>(opt
));
161 LongOption::copy(const RawLongOption
&opt
)
164 name
= opt
.name
? xstrdup(opt
.name
) : nullptr;
165 has_arg
= opt
.has_arg
;