OptTable.cpp revision 70a0dbbfbd933c80722549fef2d56de85c32d752
1//===--- Options.cpp - Option info table --------------------------------*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "clang/Driver/Options.h" 11 12#include "clang/Driver/Arg.h" 13#include "clang/Driver/ArgList.h" 14#include "clang/Driver/Option.h" 15#include <cassert> 16 17using namespace clang; 18using namespace clang::driver; 19using namespace clang::driver::options; 20 21struct Info { 22 Option::OptionClass Kind; 23 const char *Name; 24 unsigned GroupID; 25 unsigned AliasID; 26 const char *Flags; 27 unsigned Param; 28}; 29 30static Info OptionInfos[] = { 31 // The InputOption info 32 { Option::InputClass, "<input>", 0, 0, "", 0 }, 33 // The UnknownOption info 34 { Option::UnknownClass, "<unknown>", 0, 0, "", 0 }, 35 36#define OPTION(ID, KIND, NAME, GROUP, ALIAS, FLAGS, PARAM) \ 37 { Option::KIND##Class, NAME, GROUP, ALIAS, FLAGS, PARAM }, 38#include "clang/Driver/Options.def" 39}; 40static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]); 41 42static Info &getInfo(unsigned id) { 43 assert(id > 0 && id - 1 < numOptions && "Invalid Option ID."); 44 return OptionInfos[id - 1]; 45} 46 47OptTable::OptTable() : Options(new Option*[numOptions]) { 48} 49 50OptTable::~OptTable() { 51 for (unsigned i=0; i<numOptions; ++i) 52 delete Options[i]; 53 delete[] Options; 54} 55 56unsigned OptTable::getNumOptions() const { 57 return numOptions; 58} 59 60const char *OptTable::getOptionName(options::ID id) const { 61 return getInfo(id).Name; 62} 63 64const Option *OptTable::getOption(options::ID id) const { 65 if (id == NotOption) 66 return 0; 67 68 assert((unsigned) (id - 1) < numOptions && "Invalid ID."); 69 70 Option *&Entry = Options[id - 1]; 71 if (!Entry) 72 Entry = constructOption(id); 73 74 return Entry; 75} 76 77Option *OptTable::constructOption(options::ID id) const { 78 Info &info = getInfo(id); 79 const OptionGroup *Group = 80 cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID)); 81 const Option *Alias = getOption((options::ID) info.AliasID); 82 83 Option *Opt = 0; 84 switch (info.Kind) { 85 case Option::InputClass: 86 Opt = new InputOption(); break; 87 case Option::UnknownClass: 88 Opt = new UnknownOption(); break; 89 case Option::GroupClass: 90 Opt = new OptionGroup(id, info.Name, Group); break; 91 case Option::FlagClass: 92 Opt = new FlagOption(id, info.Name, Group, Alias); break; 93 case Option::JoinedClass: 94 Opt = new JoinedOption(id, info.Name, Group, Alias); break; 95 case Option::SeparateClass: 96 Opt = new SeparateOption(id, info.Name, Group, Alias); break; 97 case Option::CommaJoinedClass: 98 Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break; 99 case Option::MultiArgClass: 100 Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break; 101 case Option::JoinedOrSeparateClass: 102 Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break; 103 case Option::JoinedAndSeparateClass: 104 Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break; 105 } 106 107 for (const char *s = info.Flags; *s; ++s) { 108 switch (*s) { 109 default: assert(0 && "Invalid option flag."); 110 case 'l': Opt->setLinkerInput(true); break; 111 case 'i': Opt->setNoOptAsInput(true); break; 112 case 'J': Opt->setForceJoinedRender(true); break; 113 case 'S': Opt->setForceSeparateRender(true); break; 114 case 'U': Opt->setUnsupported(true); break; 115 } 116 } 117 118 return Opt; 119} 120 121Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index, 122 unsigned IndexEnd) const { 123 const char *Str = Args.getArgString(Index); 124 125 // Anything that doesn't start with '-' is an input. 126 if (Str[0] != '-') 127 return new PositionalArg(getOption(InputOpt), Index++); 128 129 for (unsigned j = UnknownOpt + 1; j < getNumOptions(); ++j) { 130 const char *OptName = getOptionName((options::ID) (j + 1)); 131 132 // Arguments are only accepted by options which prefix them. 133 if (memcmp(Str, OptName, strlen(OptName)) == 0) 134 if (Arg *A = getOption((options::ID) (j + 1))->accept(Args, Index)) 135 return A; 136 } 137 138 return new PositionalArg(getOption(UnknownOpt), Index++); 139} 140 141