1 // flags.cc
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 // Author: riley@google.com (Michael Riley)
16 //
17 // \file
18 // Google-style flag handling definitions
19
20 #include <cstring>
21
22 #include <fst/compat.h>
23 #include <fst/flags.h>
24
25 DEFINE_int32(v, 0, "verbose level");
26 DEFINE_bool(help, false, "show usage information");
27 DEFINE_bool(helpshort, false, "show brief usage information");
28 DEFINE_string(tmpdir, "/tmp/", "temporary directory");
29
30 using namespace std;
31
32 static string flag_usage;
33 static string prog_src;
34
SetFlags(const char * usage,int * argc,char *** argv,bool remove_flags,const char * src)35 void SetFlags(const char *usage, int *argc, char ***argv,
36 bool remove_flags, const char *src) {
37 flag_usage = usage;
38 prog_src = src;
39 int index = 1;
40 for (; index < *argc; ++index) {
41 string argval = (*argv)[index];
42
43 if (argval[0] != '-' || argval == "-")
44 break;
45 while (argval[0] == '-')
46 argval = argval.substr(1); // remove initial '-'s
47
48 string arg = argval;
49 string val = "";
50
51 // split argval (arg=val) into arg and val
52 size_t pos = argval.find("=");
53 if (pos != string::npos) {
54 arg = argval.substr(0, pos);
55 val = argval.substr(pos + 1);
56 }
57
58 FlagRegister<bool> *bool_register =
59 FlagRegister<bool>::GetRegister();
60 if (bool_register->SetFlag(arg, val))
61 continue;
62 FlagRegister<string> *string_register =
63 FlagRegister<string>::GetRegister();
64 if (string_register->SetFlag(arg, val))
65 continue;
66 FlagRegister<int32> *int32_register =
67 FlagRegister<int32>::GetRegister();
68 if (int32_register->SetFlag(arg, val))
69 continue;
70 FlagRegister<int64> *int64_register =
71 FlagRegister<int64>::GetRegister();
72 if (int64_register->SetFlag(arg, val))
73 continue;
74 FlagRegister<double> *double_register =
75 FlagRegister<double>::GetRegister();
76 if (double_register->SetFlag(arg, val))
77 continue;
78
79 LOG(FATAL) << "SetFlags: Bad option: " << (*argv)[index];
80 }
81
82 if (remove_flags) {
83 for (int i = 0; i < *argc - index; ++i)
84 (*argv)[i + 1] = (*argv)[i + index];
85 *argc -= index - 1;
86 }
87
88 if (FLAGS_help) {
89 ShowUsage(true);
90 exit(1);
91 }
92
93 if (FLAGS_helpshort) {
94 ShowUsage(false);
95 exit(1);
96 }
97 }
98
99 // If flag is defined in file 'src' and 'in_src' true or is not
100 // defined in file 'src' and 'in_src' is false, then print usage.
101 static void
ShowUsageRestrict(const std::set<pair<string,string>> & usage_set,const string & src,bool in_src,bool show_file)102 ShowUsageRestrict(const std::set< pair<string, string> > &usage_set,
103 const string &src, bool in_src, bool show_file) {
104 string old_file;
105 bool file_out = false;
106 bool usage_out = false;
107 for (std::set< pair<string, string> >::const_iterator it =
108 usage_set.begin();
109 it != usage_set.end();
110 ++it) {
111 const string &file = it->first;
112 const string &usage = it->second;
113
114 bool match = file == src;
115 if ((match && !in_src) || (!match && in_src))
116 continue;
117
118 if (file != old_file) {
119 if (show_file) {
120 if (file_out) cout << "\n";
121 cout << "Flags from: " << file << "\n";
122 file_out = true;
123 }
124 old_file = file;
125 }
126 cout << usage << "\n";
127 usage_out = true;
128 }
129 if (usage_out) cout << "\n";
130 }
131
ShowUsage(bool long_usage)132 void ShowUsage(bool long_usage) {
133 std::set< pair<string, string> > usage_set;
134
135 cout << flag_usage << "\n";
136
137 FlagRegister<bool> *bool_register = FlagRegister<bool>::GetRegister();
138 bool_register->GetUsage(&usage_set);
139 FlagRegister<string> *string_register = FlagRegister<string>::GetRegister();
140 string_register->GetUsage(&usage_set);
141 FlagRegister<int32> *int32_register = FlagRegister<int32>::GetRegister();
142 int32_register->GetUsage(&usage_set);
143 FlagRegister<int64> *int64_register = FlagRegister<int64>::GetRegister();
144 int64_register->GetUsage(&usage_set);
145 FlagRegister<double> *double_register = FlagRegister<double>::GetRegister();
146 double_register->GetUsage(&usage_set);
147
148 if (!prog_src.empty()) {
149 cout << "PROGRAM FLAGS:\n\n";
150 ShowUsageRestrict(usage_set, prog_src, true, false);
151 }
152
153 if (!long_usage)
154 return;
155
156 if (!prog_src.empty())
157 cout << "LIBRARY FLAGS:\n\n";
158
159 ShowUsageRestrict(usage_set, prog_src, false, true);
160 }
161