FST  openfst-1.8.2
OpenFst Library
flags.cc
Go to the documentation of this file.
1 // Copyright 2005-2020 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 <cstdint>
20 #include <cstring>
21 #include <iostream>
22 #include <ostream>
23 #include <set>
24 #include <string>
25 #include <string_view>
26 #include <utility>
27 
28 #include <fst/log.h>
29 
30 static const char *private_tmpdir = getenv("TMPDIR");
31 
32 DEFINE_int32(v, 0, "verbosity level");
33 DEFINE_bool(help, false, "show usage information");
34 DEFINE_bool(helpshort, false, "show brief usage information");
35 DEFINE_string(tmpdir, private_tmpdir ? private_tmpdir : "/tmp",
36  "temporary directory");
37 
38 static std::string flag_usage;
39 static std::string prog_src;
40 
41 // Sets prog_src to src.
42 static void SetProgSrc(const char *src) {
43  prog_src = src;
44  // Remove "-main" in src filename. Flags are defined in fstx.cc but SetFlags()
45  // is called in fstx-main.cc, which results in a filename mismatch in
46  // ShowUsageRestrict() below.
47  static constexpr std::string_view kMainSuffix = "-main.cc";
48  const int prefix_length = prog_src.size() - kMainSuffix.size();
49  if (prefix_length > 0 &&
50  std::string_view(prog_src).substr(prefix_length) == kMainSuffix) {
51  static constexpr size_t kDashMainSize = std::string_view("-main").size();
52  prog_src.erase(prefix_length, kDashMainSize);
53  }
54 }
55 
56 void SetFlags(const char *usage, int *argc, char ***argv,
57  bool remove_flags, const char *src) {
58  flag_usage = usage;
59  SetProgSrc(src);
60 
61  int index = 1;
62  for (; index < *argc; ++index) {
63  std::string_view argval = (*argv)[index];
64  if (argval[0] != '-' || argval == "-") break;
65  while (argval[0] == '-') argval.remove_prefix(1); // Removes initial '-'.
66  std::string arg(argval);
67  std::string val("");
68  // Splits argval (arg=val) into arg and val.
69  auto pos = argval.find('=');
70  if (pos != std::string::npos) {
71  arg = argval.substr(0, pos);
72  val = argval.substr(pos + 1);
73  }
74  auto bool_register = FlagRegister<bool>::GetRegister();
75  if (bool_register->SetFlag(arg, val))
76  continue;
77  auto string_register = FlagRegister<std::string>::GetRegister();
78  if (string_register->SetFlag(arg, val)) continue;
79  auto int32_register = FlagRegister<int32_t>::GetRegister();
80  if (int32_register->SetFlag(arg, val)) continue;
81  auto int64_register = FlagRegister<int64_t>::GetRegister();
82  if (int64_register->SetFlag(arg, val)) continue;
83  auto uint64_register = FlagRegister<uint64_t>::GetRegister();
84  if (uint64_register->SetFlag(arg, val)) continue;
85  auto double_register = FlagRegister<double>::GetRegister();
86  if (double_register->SetFlag(arg, val)) continue;
87  LOG(FATAL) << "SetFlags: Bad option: " << (*argv)[index];
88  }
89  if (remove_flags) {
90  for (auto i = 0; i < *argc - index; ++i) {
91  (*argv)[i + 1] = (*argv)[i + index];
92  }
93  *argc -= index - 1;
94  }
95  if (FST_FLAGS_help) {
96  ShowUsage(true);
97  exit(1);
98  }
99  if (FST_FLAGS_helpshort) {
100  ShowUsage(false);
101  exit(1);
102  }
103 }
104 
105 // If flag is defined in file 'src' and 'in_src' true or is not
106 // defined in file 'src' and 'in_src' is false, then print usage.
107 static void ShowUsageRestrict(
108  const std::set<std::pair<std::string, std::string>> &usage_set,
109  const std::string &src, bool in_src, bool show_file) {
110  std::string old_file;
111  bool file_out = false;
112  bool usage_out = false;
113  for (const auto &pair : usage_set) {
114  const auto &file = pair.first;
115  const auto &usage = pair.second;
116  bool match = file == src;
117  if ((match && !in_src) || (!match && in_src)) continue;
118  if (file != old_file) {
119  if (show_file) {
120  if (file_out) std::cout << std::endl;
121  std::cout << "Flags from: " << file << std::endl;
122  file_out = true;
123  }
124  old_file = file;
125  }
126  std::cout << usage << std::endl;
127  usage_out = true;
128  }
129  if (usage_out) std::cout << std::endl;
130 }
131 
132 void ShowUsage(bool long_usage) {
133  std::set<std::pair<std::string, std::string>> usage_set;
134  std::cout << flag_usage << std::endl;
135  auto bool_register = FlagRegister<bool>::GetRegister();
136  bool_register->GetUsage(&usage_set);
137  auto string_register = FlagRegister<std::string>::GetRegister();
138  string_register->GetUsage(&usage_set);
139  auto int32_register = FlagRegister<int32_t>::GetRegister();
140  int32_register->GetUsage(&usage_set);
141  auto int64_register = FlagRegister<int64_t>::GetRegister();
142  int64_register->GetUsage(&usage_set);
143  auto uint64_register = FlagRegister<uint64_t>::GetRegister();
144  uint64_register->GetUsage(&usage_set);
145  auto double_register = FlagRegister<double>::GetRegister();
146  double_register->GetUsage(&usage_set);
147  if (!prog_src.empty()) {
148  std::cout << "PROGRAM FLAGS:" << std::endl << std::endl;
149  ShowUsageRestrict(usage_set, prog_src, true, false);
150  }
151  if (!long_usage) return;
152  if (!prog_src.empty()) {
153  std::cout << "LIBRARY FLAGS:" << std::endl << std::endl;
154  }
155  ShowUsageRestrict(usage_set, prog_src, false, true);
156 }
#define LOG(type)
Definition: log.h:49
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:56
DEFINE_int32(v, 0,"verbosity level")
DEFINE_string(tmpdir, private_tmpdir?private_tmpdir:"/tmp","temporary directory")
void ShowUsage(bool long_usage)
Definition: flags.cc:132