Option.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //===--- Option.cpp - Abstract Driver Options -----------------------------===//
  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. #include "clang/Driver/Option.h"
  10. #include "clang/Driver/Arg.h"
  11. #include "clang/Driver/ArgList.h"
  12. #include "llvm/Support/raw_ostream.h"
  13. #include "llvm/Support/ErrorHandling.h"
  14. #include <cassert>
  15. #include <algorithm>
  16. using namespace clang::driver;
  17. Option::Option(const OptTable::Info *info,
  18. const Option *_Group, const Option *_Alias)
  19. : Info(info), Group(_Group), Alias(_Alias) {
  20. // Multi-level aliases are not supported, and alias options cannot
  21. // have groups. This just simplifies option tracking, it is not an
  22. // inherent limitation.
  23. assert((!Alias || (!Alias->Alias && !Group)) &&
  24. "Multi-level aliases and aliases with groups are unsupported.");
  25. }
  26. Option::~Option() {
  27. }
  28. void Option::dump() const {
  29. llvm::errs() << "<";
  30. switch (getKind()) {
  31. #define P(N) case N: llvm::errs() << #N; break
  32. P(GroupClass);
  33. P(InputClass);
  34. P(UnknownClass);
  35. P(FlagClass);
  36. P(JoinedClass);
  37. P(SeparateClass);
  38. P(CommaJoinedClass);
  39. P(MultiArgClass);
  40. P(JoinedOrSeparateClass);
  41. P(JoinedAndSeparateClass);
  42. #undef P
  43. }
  44. llvm::errs() << " Name:\"" << getName() << '"';
  45. if (Group) {
  46. llvm::errs() << " Group:";
  47. Group->dump();
  48. }
  49. if (Alias) {
  50. llvm::errs() << " Alias:";
  51. Alias->dump();
  52. }
  53. if (getKind() == MultiArgClass)
  54. llvm::errs() << " NumArgs:" << getNumArgs();
  55. llvm::errs() << ">\n";
  56. }
  57. bool Option::matches(OptSpecifier Opt) const {
  58. // Aliases are never considered in matching, look through them.
  59. if (Alias)
  60. return Alias->matches(Opt);
  61. // Check exact match.
  62. if (getID() == Opt.getID())
  63. return true;
  64. if (Group)
  65. return Group->matches(Opt);
  66. return false;
  67. }
  68. Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
  69. switch (getKind()) {
  70. case FlagClass:
  71. if (getName().size() != strlen(Args.getArgString(Index)))
  72. return 0;
  73. return new Arg(getUnaliasedOption(), Index++);
  74. case JoinedClass: {
  75. const char *Value = Args.getArgString(Index) + getName().size();
  76. return new Arg(getUnaliasedOption(), Index++, Value);
  77. }
  78. case CommaJoinedClass: {
  79. // Always matches.
  80. const char *Str = Args.getArgString(Index) + getName().size();
  81. Arg *A = new Arg(getUnaliasedOption(), Index++);
  82. // Parse out the comma separated values.
  83. const char *Prev = Str;
  84. for (;; ++Str) {
  85. char c = *Str;
  86. if (!c || c == ',') {
  87. if (Prev != Str) {
  88. char *Value = new char[Str - Prev + 1];
  89. memcpy(Value, Prev, Str - Prev);
  90. Value[Str - Prev] = '\0';
  91. A->getValues().push_back(Value);
  92. }
  93. if (!c)
  94. break;
  95. Prev = Str + 1;
  96. }
  97. }
  98. A->setOwnsValues(true);
  99. return A;
  100. }
  101. case SeparateClass:
  102. // Matches iff this is an exact match.
  103. // FIXME: Avoid strlen.
  104. if (getName().size() != strlen(Args.getArgString(Index)))
  105. return 0;
  106. Index += 2;
  107. if (Index > Args.getNumInputArgStrings())
  108. return 0;
  109. return new Arg(getUnaliasedOption(),
  110. Index - 2, Args.getArgString(Index - 1));
  111. case MultiArgClass: {
  112. // Matches iff this is an exact match.
  113. // FIXME: Avoid strlen.
  114. if (getName().size() != strlen(Args.getArgString(Index)))
  115. return 0;
  116. Index += 1 + getNumArgs();
  117. if (Index > Args.getNumInputArgStrings())
  118. return 0;
  119. Arg *A = new Arg(getUnaliasedOption(), Index - 1 - getNumArgs(),
  120. Args.getArgString(Index - getNumArgs()));
  121. for (unsigned i = 1; i != getNumArgs(); ++i)
  122. A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
  123. return A;
  124. }
  125. case JoinedOrSeparateClass: {
  126. // If this is not an exact match, it is a joined arg.
  127. // FIXME: Avoid strlen.
  128. if (getName().size() != strlen(Args.getArgString(Index))) {
  129. const char *Value = Args.getArgString(Index) + getName().size();
  130. return new Arg(this, Index++, Value);
  131. }
  132. // Otherwise it must be separate.
  133. Index += 2;
  134. if (Index > Args.getNumInputArgStrings())
  135. return 0;
  136. return new Arg(getUnaliasedOption(),
  137. Index - 2, Args.getArgString(Index - 1));
  138. }
  139. case JoinedAndSeparateClass:
  140. // Always matches.
  141. Index += 2;
  142. if (Index > Args.getNumInputArgStrings())
  143. return 0;
  144. return new Arg(getUnaliasedOption(), Index - 2,
  145. Args.getArgString(Index-2)+getName().size(),
  146. Args.getArgString(Index-1));
  147. default:
  148. llvm_unreachable("Invalid option kind!");
  149. }
  150. }