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 (at) 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 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 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 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