FST  openfst-1.8.3
OpenFst Library
flags.cc
Go to the documentation of this file.
1 // Copyright 2005-2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the 'License');
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an 'AS IS' BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Google-style flag handling definitions.
16 
17 #include <fst/flags.h>
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstdlib>
22 #include <iostream>
23 #include <ostream>
24 #include <set>
25 #include <string>
26 #include <string_view>
27 #include <utility>
28 
29 #include <fst/log.h>
30 
31 static const char *private_tmpdir = getenv("TMPDIR");
32 
33 DEFINE_int32(v, 0, "verbosity level");
34 DEFINE_bool(help, false, "show usage information");
35 DEFINE_bool(helpshort, false, "show brief usage information");
36 DEFINE_string(tmpdir, private_tmpdir ? private_tmpdir : "/tmp",
37  "temporary directory");
38 
39 static std::string flag_usage;
40 static std::string prog_src;
41 
42 // Sets prog_src to src.
43 static void SetProgSrc(const char *src) {
44  prog_src = src;
45  // Remove "-main" in src filename. Flags are defined in fstx.cc but SetFlags()
46  // is called in fstx-main.cc, which results in a filename mismatch in
47  // ShowUsageRestrict() below.
48  static constexpr std::string_view kMainSuffix = "-main.cc";
49  const int prefix_length = prog_src.size() - kMainSuffix.size();
50  if (prefix_length > 0 &&
51  std::string_view(prog_src).substr(prefix_length) == kMainSuffix) {
52  static constexpr size_t kDashMainSize = std::string_view("-main").size();
53  prog_src.erase(prefix_length, kDashMainSize);
54  }
55 }
56 
57 void SetFlags(const char *usage, int *argc, char ***argv,
58  bool remove_flags, const char *src) {
59  flag_usage = usage;
60  SetProgSrc(src);
61 
62  int index = 1;
63  for (; index < *argc; ++index) {
64  std::string_view argval = (*argv)[index];
65  if (argval[0] != '-' || argval == "-") break;
66  while (argval[0] == '-') argval.remove_prefix(1); // Removes initial '-'.
67  std::string arg(argval);
68  std::string val("");
69  // Splits argval (arg=val) into arg and val.
70  auto pos = argval.find('=');
71  if (pos != std::string::npos) {
72  arg = argval.substr(0, pos);
73  val = argval.substr(pos + 1);
74  }
75  auto bool_register = FlagRegister<bool>::GetRegister();
76  if (bool_register->SetFlag(arg, val))
77  continue;
78  auto string_register = FlagRegister<std::string>::GetRegister();
79  if (string_register->SetFlag(arg, val)) continue;
80  auto int32_register = FlagRegister<int32_t>::GetRegister();
81  if (int32_register->SetFlag(arg, val)) continue;
82  auto int64_register = FlagRegister<int64_t>::GetRegister();
83  if (int64_register->SetFlag(arg, val)) continue;
84  auto uint64_register = FlagRegister<uint64_t>::GetRegister();
85  if (uint64_register->SetFlag(arg, val)) continue;
86  auto double_register = FlagRegister<double>::GetRegister();
87  if (double_register->SetFlag(arg, val)) continue;
88  LOG(FATAL) << "SetFlags: Bad option: " << (*argv)[index];
89  }
90  if (remove_flags) {
91  for (auto i = 0; i < *argc - index; ++i) {
92  (*argv)[i + 1] = (*argv)[i + index];
93  }
94  *argc -= index - 1;
95  }
96  if (FST_FLAGS_help) {
97  ShowUsage(true);
98  exit(1);
99  }
100  if (FST_FLAGS_helpshort) {
101  ShowUsage(false);
102  exit(1);
103  }
104 }
105 
106 // If flag is defined in file 'src' and 'in_src' true or is not
107 // defined in file 'src' and 'in_src' is false, then print usage.
108 static void ShowUsageRestrict(
109  const std::set<std::pair<std::string, std::string>> &usage_set,
110  const std::string &src, bool in_src, bool show_file) {
111  std::string old_file;
112  bool file_out = false;
113  bool usage_out = false;
114  for (const auto &pair : usage_set) {
115  const auto &file = pair.first;
116  const auto &usage = pair.second;
117  bool match = file == src;
118  if ((match && !in_src) || (!match && in_src)) continue;
119  if (file != old_file) {
120  if (show_file) {
121  if (file_out) std::cout << std::endl;
122  std::cout << "Flags from: " << file << std::endl;
123  file_out = true;
124  }
125  old_file = file;
126  }
127  std::cout << usage << std::endl;
128  usage_out = true;
129  }
130  if (usage_out) std::cout << std::endl;
131 }
132 
134  std::cerr << "Memory allocation failed" << std::endl;
135  std::exit(1);
136 }
137 
138 void ShowUsage(bool long_usage) {
139  std::set<std::pair<std::string, std::string>> usage_set;
140  std::cout << flag_usage << std::endl;
141  auto bool_register = FlagRegister<bool>::GetRegister();
142  bool_register->GetUsage(&usage_set);
143  auto string_register = FlagRegister<std::string>::GetRegister();
144  string_register->GetUsage(&usage_set);
145  auto int32_register = FlagRegister<int32_t>::GetRegister();
146  int32_register->GetUsage(&usage_set);
147  auto int64_register = FlagRegister<int64_t>::GetRegister();
148  int64_register->GetUsage(&usage_set);
149  auto uint64_register = FlagRegister<uint64_t>::GetRegister();
150  uint64_register->GetUsage(&usage_set);
151  auto double_register = FlagRegister<double>::GetRegister();
152  double_register->GetUsage(&usage_set);
153  if (!prog_src.empty()) {
154  std::cout << "PROGRAM FLAGS:" << std::endl << std::endl;
155  ShowUsageRestrict(usage_set, prog_src, true, false);
156  }
157  if (!long_usage) return;
158  if (!prog_src.empty()) {
159  std::cout << "LIBRARY FLAGS:" << std::endl << std::endl;
160  }
161  ShowUsageRestrict(usage_set, prog_src, false, true);
162 }
void FailedNewHandler()
Definition: flags.cc:133
#define LOG(type)
Definition: log.h:53
static FlagRegister< T > * GetRegister()
Definition: flags.h:79
DEFINE_bool(help, false,"show usage information")
void SetFlags(const char *usage, int *argc, char ***argv, bool remove_flags, const char *src)
Definition: flags.cc:57
DEFINE_int32(v, 0,"verbosity level")
DEFINE_string(tmpdir, private_tmpdir?private_tmpdir:"/tmp","temporary directory")
void ShowUsage(bool long_usage)
Definition: flags.cc:138