Home | History | Annotate | Download | only in lib
      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