Change loops to derive the number of tables automatically
[oota-llvm.git] / utils / TableGen / StringMatcher.cpp
index 2d2f77357886f27c00ecf669f4e74771f814ba00..6aedcbf458a86b3fcb6b3828cc4d015047aafa88 100644 (file)
@@ -51,9 +51,18 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
   if (CharNo == Matches[0]->first.size()) {
     assert(Matches.size() == 1 && "Had duplicate keys to match on");
     
-    // FIXME: If Matches[0].first has embeded \n, this will be bad.
-    OS << Indent << Matches[0]->second << "\t // \"" << Matches[0]->first
-    << "\"\n";
+    // If the to-execute code has \n's in it, indent each subsequent line.
+    StringRef Code = Matches[0]->second;
+    
+    std::pair<StringRef, StringRef> Split = Code.split('\n');
+    OS << Indent << Split.first << "\t // \"" << Matches[0]->first << "\"\n";
+
+    Code = Split.second;
+    while (!Code.empty()) {
+      Split = Code.split('\n');
+      OS << Indent << Split.first << "\n";
+      Code = Split.second;
+    }
     return false;
   }
   
@@ -78,9 +87,9 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
       << Matches[0]->first[CharNo] << "')\n";
       OS << Indent << "  break;\n";
     } else {
-      // Do the comparison with if (Str.substr(1,3) != "foo").    
+      // Do the comparison with if (Str.substr(1, 3) != "foo").    
       // FIXME: Need to escape general strings.
-      OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ","
+      OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ", "
       << NumChars << ") != \"";
       OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n";
       OS << Indent << "  break;\n";
@@ -98,7 +107,9 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
        MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) {
     // TODO: escape hard stuff (like \n) if we ever care about it.
     OS << Indent << "case '" << LI->first << "':\t // "
-    << LI->second.size() << " strings to match.\n";
+       << LI->second.size() << " string";
+    if (LI->second.size() != 1) OS << 's';
+    OS << " to match.\n";
     if (EmitStringMatcherForChar(LI->second, CharNo+1, IndentCount+1))
       OS << Indent << "  break;\n";
   }
@@ -110,7 +121,10 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
 
 /// Emit - Top level entry point.
 ///
-void StringMatcher::Emit() const {
+void StringMatcher::Emit(unsigned Indent) const {
+  // If nothing to match, just fall through.
+  if (Matches.empty()) return;
+  
   // First level categorization: group strings by length.
   std::map<unsigned, std::vector<const StringPair*> > MatchesByLength;
   
@@ -119,16 +133,17 @@ void StringMatcher::Emit() const {
   
   // Output a switch statement on length and categorize the elements within each
   // bin.
-  OS << "  switch (" << StrVariableName << ".size()) {\n";
-  OS << "  default: break;\n";
+  OS.indent(Indent*2+2) << "switch (" << StrVariableName << ".size()) {\n";
+  OS.indent(Indent*2+2) << "default: break;\n";
   
   for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI =
        MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) {
-    OS << "  case " << LI->first << ":\t // " << LI->second.size()
-    << " strings to match.\n";
-    if (EmitStringMatcherForChar(LI->second, 0, 0))
-      OS << "    break;\n";
+    OS.indent(Indent*2+2) << "case " << LI->first << ":\t // "
+       << LI->second.size()
+       << " string" << (LI->second.size() == 1 ? "" : "s") << " to match.\n";
+    if (EmitStringMatcherForChar(LI->second, 0, Indent))
+      OS.indent(Indent*2+4) << "break;\n";
   }
   
-  OS << "  }\n";
+  OS.indent(Indent*2+2) << "}\n";
 }