CommandLine.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 #include "squid.h"
10 
11 #include "CommandLine.h"
12 #include "sbuf/SBuf.h"
13 
14 static void
15 ResetGetopt(const bool allowStderrWarnings)
16 {
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
21  optind = 0;
22 }
23 
24 CommandLine::CommandLine(int argC, char *argV[], const char *shortRules, const RawLongOption *longRules):
25  argv_(),
26  shortOptions_(shortRules ? xstrdup(shortRules) : ""),
27  longOptions_()
28 {
29  assert(argC > 0); // C++ main() requirement that makes our arg0() safe
30  assert(shortRules);
31 
32  /* copy argV items */
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"
37 
38  /* copy grammar rules for the long options */
39  if (longRules) {
40  for (auto longOption = longRules; longOption->name; ++longOption)
41  longOptions_.emplace_back(*longOption);
42  longOptions_.emplace_back();
43  }
44 }
45 
47  CommandLine(them.argc(), them.argv(), them.shortOptions_, them.longOptions())
48 {
49 }
50 
53 {
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_);
59  return *this;
60 }
61 
63 {
64  for (auto arg: argv_)
65  xfree(arg);
66 
68 }
69 
70 bool
71 CommandLine::hasOption(const int optIdToFind, const char **optValue) const
72 {
73  ResetGetopt(false); // avoid duped warnings; forEachOption() will complain
74  int optId = 0;
75  while (nextOption(optId)) {
76  if (optId == optIdToFind) {
77  if (optValue) {
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)
80  *optValue = optarg;
81  }
82  return true;
83  }
84  }
85  return false;
86 }
87 
88 void
89 CommandLine::forEachOption(Visitor visitor) const
90 {
91  ResetGetopt(true);
92  int optId = 0;
93  while (nextOption(optId))
94  visitor(optId, optarg);
95 }
96 
100 bool
101 CommandLine::nextOption(int &optId) const
102 {
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());
106  SBuf errMsg;
107  errMsg.Printf("'%s': %s", argv_[optind - 1], optId == '?' ?
108  "unrecognized option or missing required argument" : "missing required argument");
109  throw TexcHere(errMsg);
110  }
111  return optId != -1;
112 }
113 
114 void
115 CommandLine::resetArg0(const char *programName)
116 {
117  assert(programName);
118  xfree(argv_[0]);
119  argv_[0] = xstrdup(programName);
120 }
121 
122 void
123 CommandLine::pushFrontOption(const char *name, const char *value)
124 {
125  assert(name);
126  argv_.insert(argv_.begin() + 1, xstrdup(name));
127  if (value)
128  argv_.insert(argv_.begin() + 2, xstrdup(value));
129 }
130 
132  option({nullptr, 0, nullptr, 0})
133 {
134 }
135 
137  option({nullptr, 0, nullptr, 0})
138 {
139  copy(opt);
140 }
141 
143  LongOption(static_cast<const RawLongOption &>(opt))
144 {
145 }
146 
148 {
149  xfree(name);
150 }
151 
152 LongOption &
154 {
155  if (this != &opt)
156  copy(static_cast<const RawLongOption &>(opt));
157  return *this;
158 }
159 
160 void
162 {
163  xfree(name);
164  name = opt.name ? xstrdup(opt.name) : nullptr;
165  has_arg = opt.has_arg;
166  flag = opt.flag;
167  val = opt.val;
168 }
169 
static void ResetGetopt(const bool allowStderrWarnings)
Definition: CommandLine.cc:15
int opterr
Definition: getopt.c:47
Definition: SBuf.h:93
bool hasOption(const int optId, const char **optValue=nullptr) const
Definition: CommandLine.cc:71
#define xstrdup
char * optarg
Definition: getopt.c:51
void forEachOption(Visitor) const
calls Visitor for each of the configured command line option
Definition: CommandLine.cc:89
const char * shortOptions_
single-dash, single-letter (-x) option rules
Definition: CommandLine.h:80
void pushFrontOption(const char *name, const char *value=nullptr)
inserts a (possibly duplicated) option at the beginning of options (just after argv[0])
Definition: CommandLine.cc:123
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
Definition: TextException.h:63
void resetArg0(const char *programName)
replaces argv[0] with the new value
Definition: CommandLine.cc:115
Manages arguments passed to a program (i.e., main(argc, argv) parameters).
Definition: CommandLine.h:34
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition: SBuf.cc:214
std::vector< char * > argv_
raw main() parameters, including argv[0] and a nil argv[argc]
Definition: CommandLine.h:77
#define assert(EX)
Definition: assert.h:17
A struct option C++ wrapper, helps with option::name copying/freeing.
Definition: CommandLine.h:20
CommandLine & operator=(const CommandLine &)
Definition: CommandLine.cc:52
#define xfree
const RawLongOption * longOptions() const
Definition: CommandLine.h:73
void copy(const RawLongOption &)
Definition: CommandLine.cc:161
bool nextOption(int &optId) const
Definition: CommandLine.cc:101
int optind
Definition: getopt.c:48
LongOption & operator=(const LongOption &)
Definition: CommandLine.cc:153
CommandLine(int argc, char *argv[], const char *shortRules, const RawLongOption *longRules)
expects main() input plus getopt_long(3) grammar rules for parsing argv
Definition: CommandLine.cc:24
int argc() const
Definition: CommandLine.h:61
char ** argv() const
Definition: CommandLine.h:64
std::vector< LongOption > longOptions_
long –option rules
Definition: CommandLine.h:81

 

Introduction

Documentation

Support

Miscellaneous