196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer//===--- OptTable.cpp - Option Table Implementation -----------------------===// 296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// 396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// The LLVM Compiler Infrastructure 496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// 596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// This file is distributed under the University of Illinois Open Source 696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// License. See LICENSE.TXT for details. 796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// 896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer//===----------------------------------------------------------------------===// 996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 1096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include "llvm/Option/OptTable.h" 1196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include "llvm/Option/Arg.h" 1296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include "llvm/Option/ArgList.h" 1396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include "llvm/Option/Option.h" 1496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include "llvm/Support/ErrorHandling.h" 1558a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "llvm/Support/raw_ostream.h" 1696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include <algorithm> 172957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama#include <cctype> 1896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#include <map> 1996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 2096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerusing namespace llvm; 2196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerusing namespace llvm::opt; 2296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 232957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyamanamespace llvm { 242957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyamanamespace opt { 2596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 262957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama// Ordering on Info. The ordering is *almost* case-insensitive lexicographic, 272957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama// with an exceptions. '\0' comes at the end of the alphabet instead of the 282957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama// beginning (thus options precede any other options which prefix them). 292957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyamastatic int StrCmpOptionNameIgnoreCase(const char *A, const char *B) { 302957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama const char *X = A, *Y = B; 312957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama char a = tolower(*A), b = tolower(*B); 321997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama while (a == b) { 331997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama if (a == '\0') 341997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama return 0; 351997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama 362957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama a = tolower(*++X); 372957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama b = tolower(*++Y); 381997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama } 391997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama 401997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama if (a == '\0') // A is a prefix of B. 411997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama return 1; 421997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama if (b == '\0') // B is a prefix of A. 431997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama return -1; 441997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama 451997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama // Otherwise lexicographic. 461997734e37775a68182b3fd508a52e0c28ff36f8Rui Ueyama return (a < b) ? -1 : 1; 47055f4e99ffb32462db6fc62f9a306f2865acacb0Rui Ueyama} 4896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 49add560eee426339135fbabcad764b2afad46285eEli Friedman#ifndef NDEBUG 50add560eee426339135fbabcad764b2afad46285eEli Friedmanstatic int StrCmpOptionName(const char *A, const char *B) { 51add560eee426339135fbabcad764b2afad46285eEli Friedman if (int N = StrCmpOptionNameIgnoreCase(A, B)) 52add560eee426339135fbabcad764b2afad46285eEli Friedman return N; 53add560eee426339135fbabcad764b2afad46285eEli Friedman return strcmp(A, B); 54add560eee426339135fbabcad764b2afad46285eEli Friedman} 55add560eee426339135fbabcad764b2afad46285eEli Friedman 56add560eee426339135fbabcad764b2afad46285eEli Friedmanstatic inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { 57add560eee426339135fbabcad764b2afad46285eEli Friedman if (&A == &B) 58add560eee426339135fbabcad764b2afad46285eEli Friedman return false; 59add560eee426339135fbabcad764b2afad46285eEli Friedman 60add560eee426339135fbabcad764b2afad46285eEli Friedman if (int N = StrCmpOptionName(A.Name, B.Name)) 61add560eee426339135fbabcad764b2afad46285eEli Friedman return N < 0; 62add560eee426339135fbabcad764b2afad46285eEli Friedman 63add560eee426339135fbabcad764b2afad46285eEli Friedman for (const char * const *APre = A.Prefixes, 64add560eee426339135fbabcad764b2afad46285eEli Friedman * const *BPre = B.Prefixes; 65dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){ 66add560eee426339135fbabcad764b2afad46285eEli Friedman if (int N = StrCmpOptionName(*APre, *BPre)) 67add560eee426339135fbabcad764b2afad46285eEli Friedman return N < 0; 68add560eee426339135fbabcad764b2afad46285eEli Friedman } 69add560eee426339135fbabcad764b2afad46285eEli Friedman 70add560eee426339135fbabcad764b2afad46285eEli Friedman // Names are the same, check that classes are in order; exactly one 71add560eee426339135fbabcad764b2afad46285eEli Friedman // should be joined, and it should succeed the other. 72add560eee426339135fbabcad764b2afad46285eEli Friedman assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) && 73add560eee426339135fbabcad764b2afad46285eEli Friedman "Unexpected classes for options with same name."); 74add560eee426339135fbabcad764b2afad46285eEli Friedman return B.Kind == Option::JoinedClass; 75add560eee426339135fbabcad764b2afad46285eEli Friedman} 76add560eee426339135fbabcad764b2afad46285eEli Friedman#endif 77add560eee426339135fbabcad764b2afad46285eEli Friedman 7896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer// Support lower_bound between info and an option name. 7996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerstatic inline bool operator<(const OptTable::Info &I, const char *Name) { 802957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0; 8196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 8296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 8396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 8496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 8596a564f2beec8c1930f0640844eec433e03bbce8Michael J. SpencerOptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} 8696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 872957273b888dabe8be8e2fa5ac691e39879685c4Rui UeyamaOptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos, 882957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama bool _IgnoreCase) 8996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer : OptionInfos(_OptionInfos), 9096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer NumOptionInfos(_NumOptionInfos), 912957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama IgnoreCase(_IgnoreCase), 9296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer TheInputOptionID(0), 9396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer TheUnknownOptionID(0), 9496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer FirstSearchableIndex(0) 9596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer{ 9696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Explicitly zero initialize the error to work around a bug in array 9796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // value-initialization on MinGW with gcc 4.3.5. 9896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 9996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Find start of normal options. 10096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { 10196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned Kind = getInfo(i + 1).Kind; 10296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Kind == Option::InputClass) { 10396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert(!TheInputOptionID && "Cannot have multiple input options!"); 10496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer TheInputOptionID = getInfo(i + 1).ID; 10596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } else if (Kind == Option::UnknownClass) { 10696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert(!TheUnknownOptionID && "Cannot have multiple unknown options!"); 10796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer TheUnknownOptionID = getInfo(i + 1).ID; 10896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } else if (Kind != Option::GroupClass) { 10996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer FirstSearchableIndex = i; 11096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer break; 11196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 11296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 11396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert(FirstSearchableIndex != 0 && "No searchable options?"); 11496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 11596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#ifndef NDEBUG 11696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Check that everything after the first searchable option is a 11796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // regular option class. 11896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) { 11996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind; 12096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert((Kind != Option::InputClass && Kind != Option::UnknownClass && 12196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Kind != Option::GroupClass) && 12296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer "Special options should be defined first!"); 12396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 12496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 12596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Check that options are in order. 12696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){ 12796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (!(getInfo(i) < getInfo(i + 1))) { 12896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer getOption(i).dump(); 12996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer getOption(i + 1).dump(); 13096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer llvm_unreachable("Options are not in order!"); 13196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 13296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 13396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer#endif 13496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 13596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Build prefixes. 13696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1; 13796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer i != e; ++i) { 13896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (const char *const *P = getInfo(i).Prefixes) { 139dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (; *P != nullptr; ++P) { 14096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer PrefixesUnion.insert(*P); 14196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 14296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 14396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 14496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 14596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Build prefix chars. 14696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(), 14796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer E = PrefixesUnion.end(); I != E; ++I) { 14896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer StringRef Prefix = I->getKey(); 14996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end(); 15096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer C != CE; ++C) 15196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (std::find(PrefixChars.begin(), PrefixChars.end(), *C) 15296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer == PrefixChars.end()) 15396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer PrefixChars.push_back(*C); 15496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 15596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 15696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 15796a564f2beec8c1930f0640844eec433e03bbce8Michael J. SpencerOptTable::~OptTable() { 15896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 15996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 16096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerconst Option OptTable::getOption(OptSpecifier Opt) const { 16196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned id = Opt.getID(); 16296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (id == 0) 163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Option(nullptr, nullptr); 16496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); 16596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return Option(&getInfo(id), this); 16696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 16796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 16896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerstatic bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) { 16996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Arg == "-") 17096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return true; 17196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (llvm::StringSet<>::const_iterator I = Prefixes.begin(), 17296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer E = Prefixes.end(); I != E; ++I) 17396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Arg.startswith(I->getKey())) 17496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return false; 17596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return true; 17696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 17796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 17896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer/// \returns Matched size. 0 means no match. 1792957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyamastatic unsigned matchOption(const OptTable::Info *I, StringRef Str, 1802957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama bool IgnoreCase) { 181dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) { 18296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer StringRef Prefix(*Pre); 1832957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama if (Str.startswith(Prefix)) { 1842957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama StringRef Rest = Str.substr(Prefix.size()); 1852957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama bool Matched = IgnoreCase 18642f2a6b41ea62d4ccd10a6c469b27549881a7406Jakub Staszak ? Rest.startswith_lower(I->Name) 1872957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama : Rest.startswith(I->Name); 1882957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama if (Matched) 1892957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama return Prefix.size() + StringRef(I->Name).size(); 1902957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama } 19196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 19296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return 0; 19396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 19496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 195a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid KlecknerArg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index, 196a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner unsigned FlagsToInclude, 197a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner unsigned FlagsToExclude) const { 19896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned Prev = Index; 19996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const char *Str = Args.getArgString(Index); 20096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 20196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Anything that doesn't start with PrefixesUnion is an input, as is '-' 20296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // itself. 20396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (isInput(PrefixesUnion, Str)) 20496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return new Arg(getOption(TheInputOptionID), Str, Index++, Str); 20596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 20696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const Info *Start = OptionInfos + FirstSearchableIndex; 20796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const Info *End = OptionInfos + getNumOptions(); 20896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer StringRef Name = StringRef(Str).ltrim(PrefixChars); 20996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 21096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Search for the first next option which could be a prefix. 21196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Start = std::lower_bound(Start, End, Name.data()); 21296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 21396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Options are stored in sorted order, with '\0' at the end of the 21496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // alphabet. Since the only options which can accept a string must 21596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // prefix it, we iteratively search for the next option which could 21696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // be a prefix. 21796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // 21896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // FIXME: This is searching much more than necessary, but I am 21996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // blanking on the simplest way to make it fast. We can solve this 22096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // problem when we move to TableGen. 22196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (; Start != End; ++Start) { 22296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned ArgSize = 0; 22396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Scan for first option which is a proper prefix. 22496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (; Start != End; ++Start) 2252957273b888dabe8be8e2fa5ac691e39879685c4Rui Ueyama if ((ArgSize = matchOption(Start, Str, IgnoreCase))) 22696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer break; 22796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Start == End) 22896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer break; 22996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 230a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner Option Opt(Start, this); 231a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner 232a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude)) 233a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner continue; 234a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner if (Opt.hasFlag(FlagsToExclude)) 235a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner continue; 236a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner 23796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // See if this option matches. 238a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner if (Arg *A = Opt.accept(Args, Index, ArgSize)) 23996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return A; 24096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 24196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Otherwise, see if this argument was missing values. 24296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Prev != Index) 243dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 24496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 24596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 246a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner // If we failed to find an option and this arg started with /, then it's 247a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner // probably an input path. 248a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner if (Str[0] == '/') 249a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner return new Arg(getOption(TheInputOptionID), Str, Index++, Str); 250a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner 25196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str); 25296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 25396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 254a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid KlecknerInputArgList *OptTable::ParseArgs(const char *const *ArgBegin, 255a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner const char *const *ArgEnd, 25696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned &MissingArgIndex, 257a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner unsigned &MissingArgCount, 258a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner unsigned FlagsToInclude, 259a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner unsigned FlagsToExclude) const { 26096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); 26196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 26296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // FIXME: Handle '@' args (or at least error on them). 26396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 26496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer MissingArgIndex = MissingArgCount = 0; 26596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned Index = 0, End = ArgEnd - ArgBegin; 26696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer while (Index < End) { 26796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Ignore empty arguments (other things may still take them as arguments). 2686bf104b165cec9c14dacf10bf3380eeb32c278d7Hans Wennborg StringRef Str = Args->getArgString(Index); 2696bf104b165cec9c14dacf10bf3380eeb32c278d7Hans Wennborg if (Str == "") { 27096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer ++Index; 27196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer continue; 27296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 27396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 27496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned Prev = Index; 275a2549d382789fa33b5541708b2e4cf39e8bf56c9Reid Kleckner Arg *A = ParseOneArg(*Args, Index, FlagsToInclude, FlagsToExclude); 27696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert(Index > Prev && "Parser failed to consume argument."); 27796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 27896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Check for missing argument error. 27996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (!A) { 28096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert(Index >= End && "Unexpected parser error."); 28196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer assert(Index - Prev - 1 && "No missing arguments!"); 28296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer MissingArgIndex = Prev; 28396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer MissingArgCount = Index - Prev - 1; 28496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer break; 28596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 28696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 28796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Args->append(A); 28896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 28996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 29096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return Args; 29196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 29296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 29396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerstatic std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { 29496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const Option O = Opts.getOption(Id); 29596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer std::string Name = O.getPrefixedName(); 29696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 29796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Add metavar, if used. 29896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer switch (O.getKind()) { 29996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer case Option::GroupClass: case Option::InputClass: case Option::UnknownClass: 30096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer llvm_unreachable("Invalid option with help text."); 30196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 30296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer case Option::MultiArgClass: 30396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer llvm_unreachable("Cannot print metavar for this kind of option."); 30496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 30596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer case Option::FlagClass: 30696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer break; 30796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 30896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer case Option::SeparateClass: case Option::JoinedOrSeparateClass: 309af9e3557552c341615052a05d4eeb36d7fd5c33fHans Wennborg case Option::RemainingArgsClass: 31096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Name += ' '; 31196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // FALLTHROUGH 31296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer case Option::JoinedClass: case Option::CommaJoinedClass: 31396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer case Option::JoinedAndSeparateClass: 31496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) 31596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Name += MetaVarName; 31696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer else 31796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Name += "<value>"; 31896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer break; 31996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 32096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 32196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return Name; 32296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 32396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 32496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerstatic void PrintHelpOptionList(raw_ostream &OS, StringRef Title, 32596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer std::vector<std::pair<std::string, 32696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const char*> > &OptionHelp) { 32796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << Title << ":\n"; 32896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 32996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Find the maximum option length. 33096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned OptionFieldWidth = 0; 33196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) { 33296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Skip titles. 33396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (!OptionHelp[i].second) 33496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer continue; 33596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 33696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Limit the amount of padding we are willing to give up for alignment. 33796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned Length = OptionHelp[i].first.size(); 33896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Length <= 23) 33996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OptionFieldWidth = std::max(OptionFieldWidth, Length); 34096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 34196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 34296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const unsigned InitialPad = 2; 34396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) { 34496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const std::string &Option = OptionHelp[i].first; 34596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer int Pad = OptionFieldWidth - int(Option.size()); 34696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS.indent(InitialPad) << Option; 34796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 34896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Break on long option names. 34996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (Pad < 0) { 35096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << "\n"; 35196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer Pad = OptionFieldWidth + InitialPad; 35296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 35396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS.indent(Pad + 1) << OptionHelp[i].second << '\n'; 35496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 35596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 35696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 35796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencerstatic const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) { 35896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned GroupID = Opts.getOptionGroupID(Id); 35996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 36096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // If not in a group, return the default help group. 36196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (!GroupID) 36296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return "OPTIONS"; 36396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 36496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Abuse the help text of the option groups to store the "help group" 36596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // name. 36696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // 36796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // FIXME: Split out option groups. 36896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (const char *GroupHelp = Opts.getOptionHelpText(GroupID)) 36996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return GroupHelp; 37096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 37196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Otherwise keep looking. 37296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer return getOptionHelpGroup(Opts, GroupID); 37396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 37496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 3751ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Klecknervoid OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title, 3761ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner bool ShowHidden) const { 3771ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner PrintHelp(OS, Name, Title, /*Include*/ 0, /*Exclude*/ 3781ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner (ShowHidden ? 0 : HelpHidden)); 3791ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner} 3801ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner 3811ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner 3821ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Klecknervoid OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title, 3831ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner unsigned FlagsToInclude, 3841ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner unsigned FlagsToExclude) const { 38596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << "OVERVIEW: " << Title << "\n"; 38696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << '\n'; 38796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << "USAGE: " << Name << " [options] <inputs>\n"; 38896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << '\n'; 38996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 39096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // Render help text into a map of group-name to a list of (option, help) 39196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // pairs. 39296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer typedef std::map<std::string, 39396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer std::vector<std::pair<std::string, const char*> > > helpmap_ty; 39496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer helpmap_ty GroupedOptionHelp; 39596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 39696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { 39796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer unsigned Id = i + 1; 39896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 39996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer // FIXME: Split out option groups. 40096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (getOptionKind(Id) == Option::GroupClass) 40196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer continue; 40296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 4031ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner unsigned Flags = getInfo(Id).Flags; 4041ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner if (FlagsToInclude && !(Flags & FlagsToInclude)) 4051ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner continue; 4061ee21dc1e11abdc56102d0f54265af73f5468bf9Reid Kleckner if (Flags & FlagsToExclude) 40796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer continue; 40896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 40996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (const char *Text = getOptionHelpText(Id)) { 41096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const char *HelpGroup = getOptionHelpGroup(*this, Id); 41196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer const std::string &OptName = getOptionHelpName(*this, Id); 41296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text)); 41396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 41496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 41596a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 41696a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer for (helpmap_ty::iterator it = GroupedOptionHelp .begin(), 41796a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer ie = GroupedOptionHelp.end(); it != ie; ++it) { 41896a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer if (it != GroupedOptionHelp .begin()) 41996a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS << "\n"; 42096a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer PrintHelpOptionList(OS, it->first, it->second); 42196a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer } 42296a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer 42396a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer OS.flush(); 42496a564f2beec8c1930f0640844eec433e03bbce8Michael J. Spencer} 425