10a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Copyright (c) 2006, Google Inc. 20a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// All rights reserved. 30a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 40a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Redistribution and use in source and binary forms, with or without 50a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// modification, are permitted provided that the following conditions are 60a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// met: 70a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 80a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * Redistributions of source code must retain the above copyright 90a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// notice, this list of conditions and the following disclaimer. 100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * Redistributions in binary form must reproduce the above 110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// copyright notice, this list of conditions and the following disclaimer 120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// in the documentation and/or other materials provided with the 130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// distribution. 140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// * Neither the name of Google Inc. nor the names of its 150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// contributors may be used to endorse or promote products derived from 160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// this software without specific prior written permission. 170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --- 310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Author: Ray Sidney 320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Revamped and reorganized by Craig Silverstein 330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This file contains code for handling the 'reporting' flags. These 350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// are flags that, when present, cause the program to report some 360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// information and then exit. --help and --version are the canonical 370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// reporting flags, but we also have flags like --helpxml, etc. 380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// There's only one function that's meant to be called externally: 400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(), 410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called 420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// externally too, but there's little need for it.) These are all 430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// declared in the main commandlineflags.h header file. 440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// HandleCommandLineHelpFlags() will check what 'reporting' flags have 460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// been defined, if any -- the "help" part of the function name is a 470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// bit misleading -- and do the relevant reporting. It should be 480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// called after all flag-values have been assigned, that is, after 490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// parsing the command-line. 500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "config.h" 520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stdio.h> 530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string.h> 540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <ctype.h> 550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <assert.h> 560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string> 570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <vector> 580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <gflags/gflags.h> 590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <gflags/gflags_completions.h> 600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef PATH_SEPARATOR 620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#define PATH_SEPARATOR '/' 630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif 640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The 'reporting' flags. They all call exit(). 660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(help, false, 670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show help on all flags [tip: all flags can have two dashes]"); 680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(helpfull, false, 690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show help on all flags -- same as -help"); 700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(helpshort, false, 710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show help on only the main module for this program"); 720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(helpon, "", 730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show help on the modules named by this flag value"); 740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(helpmatch, "", 750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show help on modules whose name contains the specified substr"); 760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(helppackage, false, 770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show help on all modules in the main package"); 780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(helpxml, false, 790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "produce an xml version of help"); 800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(version, false, 810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "show version and build info and exit"); 820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath_START_GOOGLE_NAMESPACE_ 840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::string; 860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::vector; 870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// DescribeOneFlag() 900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// DescribeOneFlagInXML() 910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Routines that pretty-print info about a flag. These use 920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// a CommandLineFlagInfo, which is the way the commandlineflags 930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// API exposes static info about a flag. 940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const int kLineLength = 80; 970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void AddString(const string& s, 990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string* final_string, int* chars_in_line) { 1000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const int slen = static_cast<int>(s.length()); 1010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (*chars_in_line + 1 + slen >= kLineLength) { // < 80 chars/line 1020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *final_string += "\n "; 1030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *chars_in_line = 6; 1040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 1050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *final_string += " "; 1060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *chars_in_line += 1; 1070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *final_string += s; 1090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *chars_in_line += slen; 1100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Create a descriptive string for a flag. 1130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Goes to some trouble to make pretty line breaks. 1140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstring DescribeOneFlag(const CommandLineFlagInfo& flag) { 1150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string main_part = (string(" -") + flag.name + 1160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " (" + flag.description + ')'); 1170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* c_string = main_part.c_str(); 1180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int chars_left = static_cast<int>(main_part.length()); 1190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string final_string = ""; 1200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int chars_in_line = 0; // how many chars in current line so far? 1210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath while (1) { 1220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath assert(chars_left == strlen(c_string)); // Unless there's a \0 in there? 1230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* newline = strchr(c_string, '\n'); 1240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (newline == NULL && chars_in_line+chars_left < kLineLength) { 1250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The whole remainder of the string fits on this line 1260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath final_string += c_string; 1270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath chars_in_line += chars_left; 1280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 1290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (newline != NULL && newline - c_string < kLineLength - chars_in_line) { 1310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int n = static_cast<int>(newline - c_string); 1320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath final_string.append(c_string, n); 1330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath chars_left -= n + 1; 1340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath c_string += n + 1; 1350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 1360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Find the last whitespace on this 80-char line 1370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int whitespace = kLineLength-chars_in_line-1; // < 80 chars/line 1380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath while ( whitespace > 0 && !isspace(c_string[whitespace]) ) { 1390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath --whitespace; 1400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (whitespace <= 0) { 1420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Couldn't find any whitespace to make a line break. Just dump the 1430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // rest out! 1440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath final_string += c_string; 1450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath chars_in_line = kLineLength; // next part gets its own line for sure! 1460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 1470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath final_string += string(c_string, whitespace); 1490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath chars_in_line += whitespace; 1500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath while (isspace(c_string[whitespace])) ++whitespace; 1510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath c_string += whitespace; 1520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath chars_left -= whitespace; 1530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (*c_string == '\0') 1550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 1560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath final_string += "\n "; 1570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath chars_in_line = 6; 1580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Append data type 1610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddString(string("type: ") + flag.type, &final_string, &chars_in_line); 1620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Append the effective default value (i.e., the value that the flag 1630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // will have after the command line is parsed if the flag is not 1640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // specified on the command line), which may be different from the 1650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // stored default value. This would happen if the value of the flag 1660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // was modified before the command line was parsed. (Unless the 1670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // value was modified using SetCommandLineOptionWithMode() with mode 1680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // SET_FLAGS_DEFAULT.) 1690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Note that we are assuming this code is being executed because a help 1700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // request was just parsed from the command line, in which case the 1710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // printed value is indeed the effective default, as long as no value 1720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // for the flag was parsed from the command line before "--help". 1730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings 1740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddString(string("default: \"") + flag.current_value + string("\""), 1750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &final_string, &chars_in_line); 1760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 1770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddString(string("default: ") + flag.current_value, 1780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &final_string, &chars_in_line); 1790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath final_string += '\n'; 1820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return final_string; 1830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Simple routine to xml-escape a string: escape & and < only. 1860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic string XMLText(const string& txt) { 1870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string ans = txt; 1880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath for (string::size_type pos = 0; (pos = ans.find("&", pos)) != string::npos; ) 1890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ans.replace(pos++, 1, "&"); 1900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath for (string::size_type pos = 0; (pos = ans.find("<", pos)) != string::npos; ) 1910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ans.replace(pos++, 1, "<"); 1920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return ans; 1930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void AddXMLTag(string* r, const char* tag, const string& txt) { 1960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += ('<'); 1970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += (tag); 1980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += ('>'); 1990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += (XMLText(txt)); 2000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += ("</"); 2010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += (tag); 2020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *r += ('>'); 2030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) { 2060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The file and flagname could have been attributes, but default 2070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and meaning need to avoid attribute normalization. This way it 2080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // can be parsed by simple programs, in addition to xml parsers. 2090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string r("<flag>"); 2100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddXMLTag(&r, "file", flag.filename); 2110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddXMLTag(&r, "name", flag.name); 2120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddXMLTag(&r, "meaning", flag.description); 2130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddXMLTag(&r, "default", flag.default_value); 2140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddXMLTag(&r, "current", flag.current_value); 2150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AddXMLTag(&r, "type", flag.type); 2160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath r += "</flag>"; 2170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return r; 2180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 2210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ShowUsageWithFlags() 2220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ShowUsageWithFlagsRestrict() 2230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ShowXMLOfFlags() 2240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// These routines variously expose the registry's list of flag 2250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// values. ShowUsage*() prints the flag-value information 2260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// to stdout in a user-readable format (that's what --help uses). 2270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The Restrict() version limits what flags are shown. 2280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ShowXMLOfFlags() prints the flag-value information to stdout 2290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// in a machine-readable format. In all cases, the flags are 2300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// sorted: first by filename they are defined in, then by flagname. 2310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 2320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const char* Basename(const char* filename) { 2340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* sep = strrchr(filename, PATH_SEPARATOR); 2350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return sep ? sep + 1 : filename; 2360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic string Dirname(const string& filename) { 2390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string::size_type sep = filename.rfind(PATH_SEPARATOR); 2400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return filename.substr(0, (sep == string::npos) ? 0 : sep); 2410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Test whether a filename contains at least one of the substrings. 2440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic bool FileMatchesSubstring(const string& filename, 2450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const vector<string>& substrings) { 2460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath for (vector<string>::const_iterator target = substrings.begin(); 2470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target != substrings.end(); 2480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ++target) { 2490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (strstr(filename.c_str(), target->c_str()) != NULL) 2500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If the substring starts with a '/', that means that we want 2520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the string to be at the beginning of a directory component. 2530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // That should match the first directory component as well, so 2540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // we allow '/foo' to match a filename of 'foo'. 2550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!target->empty() && (*target)[0] == '/' && 2560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath strncmp(filename.c_str(), target->c_str() + 1, 2570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath strlen(target->c_str() + 1)) == 0) 2580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Show help for every filename which matches any of the target substrings. 2640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// If substrings is empty, shows help for every file. If a flag's help message 2650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' before 2660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// including gflags/gflags.h), then this flag will not be displayed by 2670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// '--help' and its variants. 2680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void ShowUsageWithFlagsMatching(const char *argv0, 2690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const vector<string> &substrings) { 2700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage()); 2710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vector<CommandLineFlagInfo> flags; 2730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath GetAllFlags(&flags); // flags are sorted by filename, then flagname 2740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string last_filename; // so we know when we're at a new file 2760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool first_directory = true; // controls blank lines between dirs 2770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool found_match = false; // stays false iff no dir matches restrict 2780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin(); 2790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath flag != flags.end(); 2800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ++flag) { 2810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (substrings.empty() || 2820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FileMatchesSubstring(flag->filename, substrings)) { 2830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If the flag has been stripped, pretend that it doesn't exist. 2840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (flag->description == kStrippedFlagHelp) continue; 2850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath found_match = true; // this flag passed the match! 2860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (flag->filename != last_filename) { // new file 2870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir! 2880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!first_directory) 2890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "\n\n"); // put blank lines between directories 2900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath first_directory = false; 2910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str()); 2930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath last_filename = flag->filename; 2940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Now print this flag 2960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str()); 2970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!found_match && !substrings.empty()) { 3000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "\n No modules matched: use -help\n"); 3010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) { 3050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vector<string> substrings; 3060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (restrict != NULL && *restrict != '\0') { 3070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath substrings.push_back(restrict); 3080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsMatching(argv0, substrings); 3100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid ShowUsageWithFlags(const char *argv0) { 3130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(argv0, ""); 3140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Convert the help, program, and usage to xml. 3170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void ShowXMLOfFlags(const char *prog_name) { 3180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vector<CommandLineFlagInfo> flags; 3190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath GetAllFlags(&flags); // flags are sorted: by filename, then flagname 3200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // XML. There is no corresponding schema yet 3220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "<?xml version=\"1.0\"?>\n"); 3230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The document 3240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "<AllFlags>\n"); 3250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the program name and usage 3260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "<program>%s</program>\n", 3270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath XMLText(Basename(prog_name)).c_str()); 3280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "<usage>%s</usage>\n", 3290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath XMLText(ProgramUsage()).c_str()); 3300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // All the flags 3310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin(); 3320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath flag != flags.end(); 3330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ++flag) { 3340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (flag->description != kStrippedFlagHelp) 3350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str()); 3360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The end of the document 3380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "</AllFlags>\n"); 3390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 3420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ShowVersion() 3430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Called upon --version. Prints build-related info. 3440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 3450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void ShowVersion() { 3470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "%s\n", ProgramInvocationShortName()); 3480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // TODO: add other stuff, like a timestamp, who built it, what 3490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // target they built, etc. 3500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# if !defined(NDEBUG) 3520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stdout, "Debug build (NDEBUG not #defined)\n"); 3530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath# endif 3540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic void AppendPrognameStrings(vector<string>* substrings, 3570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* progname) { 3580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string r("/"); 3590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath r += progname; 3600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath substrings->push_back(r + "."); 3610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath substrings->push_back(r + "-main."); 3620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath substrings->push_back(r + "_main."); 3630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 3660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// HandleCommandLineHelpFlags() 3670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Checks all the 'reporting' commandline flags to see if any 3680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// have been set. If so, handles them appropriately. Note 3690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// that all of them, by definition, cause the program to exit 3700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// if they trigger. 3710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// -------------------------------------------------------------------- 3720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid HandleCommandLineHelpFlags() { 3740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* progname = ProgramInvocationShortName(); 3750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath extern void (*commandlineflags_exitfunc)(int); // in gflags.cc 3760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath HandleCommandLineCompletions(); 3780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vector<string> substrings; 3800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AppendPrognameStrings(&substrings, progname); 3810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_helpshort) { 3830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // show only flags related to this binary: 3840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // E.g. for fileutil.cc, want flags containing ... "/fileutil." cc 3850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsMatching(progname, substrings); 3860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(1); // almost certainly exit() 3870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (FLAGS_help || FLAGS_helpfull) { 3890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // show all options 3900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(progname, ""); // empty restrict 3910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(1); 3920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (!FLAGS_helpon.empty()) { 3940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string restrict = "/" + FLAGS_helpon + "."; 3950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(progname, restrict.c_str()); 3960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(1); 3970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (!FLAGS_helpmatch.empty()) { 3990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str()); 4000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(1); 4010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (FLAGS_helppackage) { 4030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Shows help for all files in the same directory as main(). We 4040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // don't want to resort to looking at dirname(progname), because 4050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the user can pick progname, and it may not relate to the file 4060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // where main() resides. So instead, we search the flags for a 4070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // filename like "/progname.cc", and take the dirname of that. 4080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vector<CommandLineFlagInfo> flags; 4090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath GetAllFlags(&flags); 4100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string last_package; 4110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin(); 4120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath flag != flags.end(); 4130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ++flag) { 4140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!FileMatchesSubstring(flag->filename, substrings)) 4150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath continue; 4160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const string package = Dirname(flag->filename) + "/"; 4170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (package != last_package) { 4180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(progname, package.c_str()); 4190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!last_package.empty()) { // means this isn't our first pkg 4200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stderr, "WARNING: Multiple packages contain a file=%s\n", 4210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath progname); 4220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath last_package = package; 4240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (last_package.empty()) { // never found a package to print 4270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fprintf(stderr, "WARNING: Unable to find a package for file=%s\n", 4280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath progname); 4290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(1); 4310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (FLAGS_helpxml) { 4330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowXMLOfFlags(progname); 4340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(1); 4350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (FLAGS_version) { 4370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowVersion(); 4380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Unlike help, we may be asking for version in a script, so return 0 4390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath commandlineflags_exitfunc(0); 4400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 4420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath_END_GOOGLE_NAMESPACE_ 444