FileCheck.cpp revision 333fb04506233255f10d8095c9e2de5e5f0fdc6f
1//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
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// FileCheck does a line-by line check of a file that validates whether it
11// contains the expected content.  This is useful for regression tests etc.
12//
13// This program exits with an error status of 2 on error, exit status of 0 if
14// the file matched the expected contents, and exit status of 1 if it did not
15// contain the expected contents.
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/Support/CommandLine.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/PrettyStackTrace.h"
22#include "llvm/Support/Regex.h"
23#include "llvm/Support/SourceMgr.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/Support/Signals.h"
26#include "llvm/Support/system_error.h"
27#include "llvm/ADT/SmallString.h"
28#include "llvm/ADT/StringMap.h"
29#include <algorithm>
30using namespace llvm;
31
32static cl::opt<std::string>
33CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
34
35static cl::opt<std::string>
36InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
37              cl::init("-"), cl::value_desc("filename"));
38
39static cl::opt<std::string>
40CheckPrefix("check-prefix", cl::init("CHECK"),
41            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
42
43static cl::opt<bool>
44NoCanonicalizeWhiteSpace("strict-whitespace",
45              cl::desc("Do not treat all horizontal whitespace as equivalent"));
46
47//===----------------------------------------------------------------------===//
48// Pattern Handling Code.
49//===----------------------------------------------------------------------===//
50
51class Pattern {
52  SMLoc PatternLoc;
53
54  /// MatchEOF - When set, this pattern only matches the end of file. This is
55  /// used for trailing CHECK-NOTs.
56  bool MatchEOF;
57
58  /// FixedStr - If non-empty, this pattern is a fixed string match with the
59  /// specified fixed string.
60  StringRef FixedStr;
61
62  /// RegEx - If non-empty, this is a regex pattern.
63  std::string RegExStr;
64
65  /// VariableUses - Entries in this vector map to uses of a variable in the
66  /// pattern, e.g. "foo[[bar]]baz".  In this case, the RegExStr will contain
67  /// "foobaz" and we'll get an entry in this vector that tells us to insert the
68  /// value of bar at offset 3.
69  std::vector<std::pair<StringRef, unsigned> > VariableUses;
70
71  /// VariableDefs - Entries in this vector map to definitions of a variable in
72  /// the pattern, e.g. "foo[[bar:.*]]baz".  In this case, the RegExStr will
73  /// contain "foo(.*)baz" and VariableDefs will contain the pair "bar",1.  The
74  /// index indicates what parenthesized value captures the variable value.
75  std::vector<std::pair<StringRef, unsigned> > VariableDefs;
76
77public:
78
79  Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { }
80
81  bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
82
83  /// Match - Match the pattern string against the input buffer Buffer.  This
84  /// returns the position that is matched or npos if there is no match.  If
85  /// there is a match, the size of the matched string is returned in MatchLen.
86  ///
87  /// The VariableTable StringMap provides the current values of filecheck
88  /// variables and is updated if this match defines new values.
89  size_t Match(StringRef Buffer, size_t &MatchLen,
90               StringMap<StringRef> &VariableTable) const;
91
92  /// PrintFailureInfo - Print additional information about a failure to match
93  /// involving this pattern.
94  void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
95                        const StringMap<StringRef> &VariableTable) const;
96
97private:
98  static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr);
99  bool AddRegExToRegEx(StringRef RegExStr, unsigned &CurParen, SourceMgr &SM);
100
101  /// ComputeMatchDistance - Compute an arbitrary estimate for the quality of
102  /// matching this pattern at the start of \arg Buffer; a distance of zero
103  /// should correspond to a perfect match.
104  unsigned ComputeMatchDistance(StringRef Buffer,
105                               const StringMap<StringRef> &VariableTable) const;
106};
107
108
109bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
110  PatternLoc = SMLoc::getFromPointer(PatternStr.data());
111
112  // Ignore trailing whitespace.
113  while (!PatternStr.empty() &&
114         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
115    PatternStr = PatternStr.substr(0, PatternStr.size()-1);
116
117  // Check that there is something on the line.
118  if (PatternStr.empty()) {
119    SM.PrintMessage(PatternLoc, "found empty check string with prefix '" +
120                    CheckPrefix+":'", "error");
121    return true;
122  }
123
124  // Check to see if this is a fixed string, or if it has regex pieces.
125  if (PatternStr.size() < 2 ||
126      (PatternStr.find("{{") == StringRef::npos &&
127       PatternStr.find("[[") == StringRef::npos)) {
128    FixedStr = PatternStr;
129    return false;
130  }
131
132  // Paren value #0 is for the fully matched string.  Any new parenthesized
133  // values add from their.
134  unsigned CurParen = 1;
135
136  // Otherwise, there is at least one regex piece.  Build up the regex pattern
137  // by escaping scary characters in fixed strings, building up one big regex.
138  while (!PatternStr.empty()) {
139    // RegEx matches.
140    if (PatternStr.size() >= 2 &&
141        PatternStr[0] == '{' && PatternStr[1] == '{') {
142
143      // Otherwise, this is the start of a regex match.  Scan for the }}.
144      size_t End = PatternStr.find("}}");
145      if (End == StringRef::npos) {
146        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
147                        "found start of regex string with no end '}}'", "error");
148        return true;
149      }
150
151      if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
152        return true;
153      PatternStr = PatternStr.substr(End+2);
154      continue;
155    }
156
157    // Named RegEx matches.  These are of two forms: [[foo:.*]] which matches .*
158    // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
159    // second form is [[foo]] which is a reference to foo.  The variable name
160    // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
161    // it.  This is to catch some common errors.
162    if (PatternStr.size() >= 2 &&
163        PatternStr[0] == '[' && PatternStr[1] == '[') {
164      // Verify that it is terminated properly.
165      size_t End = PatternStr.find("]]");
166      if (End == StringRef::npos) {
167        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
168                        "invalid named regex reference, no ]] found", "error");
169        return true;
170      }
171
172      StringRef MatchStr = PatternStr.substr(2, End-2);
173      PatternStr = PatternStr.substr(End+2);
174
175      // Get the regex name (e.g. "foo").
176      size_t NameEnd = MatchStr.find(':');
177      StringRef Name = MatchStr.substr(0, NameEnd);
178
179      if (Name.empty()) {
180        SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
181                        "invalid name in named regex: empty name", "error");
182        return true;
183      }
184
185      // Verify that the name is well formed.
186      for (unsigned i = 0, e = Name.size(); i != e; ++i)
187        if (Name[i] != '_' &&
188            (Name[i] < 'a' || Name[i] > 'z') &&
189            (Name[i] < 'A' || Name[i] > 'Z') &&
190            (Name[i] < '0' || Name[i] > '9')) {
191          SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
192                          "invalid name in named regex", "error");
193          return true;
194        }
195
196      // Name can't start with a digit.
197      if (isdigit(Name[0])) {
198        SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
199                        "invalid name in named regex", "error");
200        return true;
201      }
202
203      // Handle [[foo]].
204      if (NameEnd == StringRef::npos) {
205        VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
206        continue;
207      }
208
209      // Handle [[foo:.*]].
210      VariableDefs.push_back(std::make_pair(Name, CurParen));
211      RegExStr += '(';
212      ++CurParen;
213
214      if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
215        return true;
216
217      RegExStr += ')';
218    }
219
220    // Handle fixed string matches.
221    // Find the end, which is the start of the next regex.
222    size_t FixedMatchEnd = PatternStr.find("{{");
223    FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
224    AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr);
225    PatternStr = PatternStr.substr(FixedMatchEnd);
226    continue;
227  }
228
229  return false;
230}
231
232void Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) {
233  // Add the characters from FixedStr to the regex, escaping as needed.  This
234  // avoids "leaning toothpicks" in common patterns.
235  for (unsigned i = 0, e = FixedStr.size(); i != e; ++i) {
236    switch (FixedStr[i]) {
237    // These are the special characters matched in "p_ere_exp".
238    case '(':
239    case ')':
240    case '^':
241    case '$':
242    case '|':
243    case '*':
244    case '+':
245    case '?':
246    case '.':
247    case '[':
248    case '\\':
249    case '{':
250      TheStr += '\\';
251      // FALL THROUGH.
252    default:
253      TheStr += FixedStr[i];
254      break;
255    }
256  }
257}
258
259bool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen,
260                              SourceMgr &SM) {
261  Regex R(RegexStr);
262  std::string Error;
263  if (!R.isValid(Error)) {
264    SM.PrintMessage(SMLoc::getFromPointer(RegexStr.data()),
265                    "invalid regex: " + Error, "error");
266    return true;
267  }
268
269  RegExStr += RegexStr.str();
270  CurParen += R.getNumMatches();
271  return false;
272}
273
274/// Match - Match the pattern string against the input buffer Buffer.  This
275/// returns the position that is matched or npos if there is no match.  If
276/// there is a match, the size of the matched string is returned in MatchLen.
277size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
278                      StringMap<StringRef> &VariableTable) const {
279  // If this is the EOF pattern, match it immediately.
280  if (MatchEOF) {
281    MatchLen = 0;
282    return Buffer.size();
283  }
284
285  // If this is a fixed string pattern, just match it now.
286  if (!FixedStr.empty()) {
287    MatchLen = FixedStr.size();
288    return Buffer.find(FixedStr);
289  }
290
291  // Regex match.
292
293  // If there are variable uses, we need to create a temporary string with the
294  // actual value.
295  StringRef RegExToMatch = RegExStr;
296  std::string TmpStr;
297  if (!VariableUses.empty()) {
298    TmpStr = RegExStr;
299
300    unsigned InsertOffset = 0;
301    for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
302      StringMap<StringRef>::iterator it =
303        VariableTable.find(VariableUses[i].first);
304      // If the variable is undefined, return an error.
305      if (it == VariableTable.end())
306        return StringRef::npos;
307
308      // Look up the value and escape it so that we can plop it into the regex.
309      std::string Value;
310      AddFixedStringToRegEx(it->second, Value);
311
312      // Plop it into the regex at the adjusted offset.
313      TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
314                    Value.begin(), Value.end());
315      InsertOffset += Value.size();
316    }
317
318    // Match the newly constructed regex.
319    RegExToMatch = TmpStr;
320  }
321
322
323  SmallVector<StringRef, 4> MatchInfo;
324  if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
325    return StringRef::npos;
326
327  // Successful regex match.
328  assert(!MatchInfo.empty() && "Didn't get any match");
329  StringRef FullMatch = MatchInfo[0];
330
331  // If this defines any variables, remember their values.
332  for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) {
333    assert(VariableDefs[i].second < MatchInfo.size() &&
334           "Internal paren error");
335    VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second];
336  }
337
338  MatchLen = FullMatch.size();
339  return FullMatch.data()-Buffer.data();
340}
341
342unsigned Pattern::ComputeMatchDistance(StringRef Buffer,
343                              const StringMap<StringRef> &VariableTable) const {
344  // Just compute the number of matching characters. For regular expressions, we
345  // just compare against the regex itself and hope for the best.
346  //
347  // FIXME: One easy improvement here is have the regex lib generate a single
348  // example regular expression which matches, and use that as the example
349  // string.
350  StringRef ExampleString(FixedStr);
351  if (ExampleString.empty())
352    ExampleString = RegExStr;
353
354  // Only compare up to the first line in the buffer, or the string size.
355  StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
356  BufferPrefix = BufferPrefix.split('\n').first;
357  return BufferPrefix.edit_distance(ExampleString);
358}
359
360void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
361                               const StringMap<StringRef> &VariableTable) const{
362  // If this was a regular expression using variables, print the current
363  // variable values.
364  if (!VariableUses.empty()) {
365    for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
366      StringRef Var = VariableUses[i].first;
367      StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
368      SmallString<256> Msg;
369      raw_svector_ostream OS(Msg);
370
371      // Check for undefined variable references.
372      if (it == VariableTable.end()) {
373        OS << "uses undefined variable \"";
374        OS.write_escaped(Var) << "\"";;
375      } else {
376        OS << "with variable \"";
377        OS.write_escaped(Var) << "\" equal to \"";
378        OS.write_escaped(it->second) << "\"";
379      }
380
381      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), OS.str(), "note",
382                      /*ShowLine=*/false);
383    }
384  }
385
386  // Attempt to find the closest/best fuzzy match.  Usually an error happens
387  // because some string in the output didn't exactly match. In these cases, we
388  // would like to show the user a best guess at what "should have" matched, to
389  // save them having to actually check the input manually.
390  size_t NumLinesForward = 0;
391  size_t Best = StringRef::npos;
392  double BestQuality = 0;
393
394  // Use an arbitrary 4k limit on how far we will search.
395  for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
396    if (Buffer[i] == '\n')
397      ++NumLinesForward;
398
399    // Patterns have leading whitespace stripped, so skip whitespace when
400    // looking for something which looks like a pattern.
401    if (Buffer[i] == ' ' || Buffer[i] == '\t')
402      continue;
403
404    // Compute the "quality" of this match as an arbitrary combination of the
405    // match distance and the number of lines skipped to get to this match.
406    unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
407    double Quality = Distance + (NumLinesForward / 100.);
408
409    if (Quality < BestQuality || Best == StringRef::npos) {
410      Best = i;
411      BestQuality = Quality;
412    }
413  }
414
415  // Print the "possible intended match here" line if we found something
416  // reasonable and not equal to what we showed in the "scanning from here"
417  // line.
418  if (Best && Best != StringRef::npos && BestQuality < 50) {
419      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best),
420                      "possible intended match here", "note");
421
422    // FIXME: If we wanted to be really friendly we would show why the match
423    // failed, as it can be hard to spot simple one character differences.
424  }
425}
426
427//===----------------------------------------------------------------------===//
428// Check Strings.
429//===----------------------------------------------------------------------===//
430
431/// CheckString - This is a check that we found in the input file.
432struct CheckString {
433  /// Pat - The pattern to match.
434  Pattern Pat;
435
436  /// Loc - The location in the match file that the check string was specified.
437  SMLoc Loc;
438
439  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
440  /// to a CHECK: directive.
441  bool IsCheckNext;
442
443  /// NotStrings - These are all of the strings that are disallowed from
444  /// occurring between this match string and the previous one (or start of
445  /// file).
446  std::vector<std::pair<SMLoc, Pattern> > NotStrings;
447
448  CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
449    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
450};
451
452/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
453/// memory buffer, free it, and return a new one.
454static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
455  SmallString<128> NewFile;
456  NewFile.reserve(MB->getBufferSize());
457
458  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
459       Ptr != End; ++Ptr) {
460    // Eliminate trailing dosish \r.
461    if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
462      continue;
463    }
464
465    // If C is not a horizontal whitespace, skip it.
466    if (*Ptr != ' ' && *Ptr != '\t') {
467      NewFile.push_back(*Ptr);
468      continue;
469    }
470
471    // Otherwise, add one space and advance over neighboring space.
472    NewFile.push_back(' ');
473    while (Ptr+1 != End &&
474           (Ptr[1] == ' ' || Ptr[1] == '\t'))
475      ++Ptr;
476  }
477
478  // Free the old buffer and return a new one.
479  MemoryBuffer *MB2 =
480    MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier());
481
482  delete MB;
483  return MB2;
484}
485
486
487/// ReadCheckFile - Read the check file, which specifies the sequence of
488/// expected strings.  The strings are added to the CheckStrings vector.
489static bool ReadCheckFile(SourceMgr &SM,
490                          std::vector<CheckString> &CheckStrings) {
491  // Open the check file, and tell SourceMgr about it.
492  error_code ec;
493  MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), ec);
494  if (F == 0) {
495    errs() << "Could not open check file '" << CheckFilename << "': "
496           << ec.message() << '\n';
497    return true;
498  }
499
500  // If we want to canonicalize whitespace, strip excess whitespace from the
501  // buffer containing the CHECK lines.
502  if (!NoCanonicalizeWhiteSpace)
503    F = CanonicalizeInputFile(F);
504
505  SM.AddNewSourceBuffer(F, SMLoc());
506
507  // Find all instances of CheckPrefix followed by : in the file.
508  StringRef Buffer = F->getBuffer();
509
510  std::vector<std::pair<SMLoc, Pattern> > NotMatches;
511
512  while (1) {
513    // See if Prefix occurs in the memory buffer.
514    Buffer = Buffer.substr(Buffer.find(CheckPrefix));
515
516    // If we didn't find a match, we're done.
517    if (Buffer.empty())
518      break;
519
520    const char *CheckPrefixStart = Buffer.data();
521
522    // When we find a check prefix, keep track of whether we find CHECK: or
523    // CHECK-NEXT:
524    bool IsCheckNext = false, IsCheckNot = false;
525
526    // Verify that the : is present after the prefix.
527    if (Buffer[CheckPrefix.size()] == ':') {
528      Buffer = Buffer.substr(CheckPrefix.size()+1);
529    } else if (Buffer.size() > CheckPrefix.size()+6 &&
530               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
531      Buffer = Buffer.substr(CheckPrefix.size()+7);
532      IsCheckNext = true;
533    } else if (Buffer.size() > CheckPrefix.size()+5 &&
534               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
535      Buffer = Buffer.substr(CheckPrefix.size()+6);
536      IsCheckNot = true;
537    } else {
538      Buffer = Buffer.substr(1);
539      continue;
540    }
541
542    // Okay, we found the prefix, yay.  Remember the rest of the line, but
543    // ignore leading and trailing whitespace.
544    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
545
546    // Scan ahead to the end of line.
547    size_t EOL = Buffer.find_first_of("\n\r");
548
549    // Remember the location of the start of the pattern, for diagnostics.
550    SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
551
552    // Parse the pattern.
553    Pattern P;
554    if (P.ParsePattern(Buffer.substr(0, EOL), SM))
555      return true;
556
557    Buffer = Buffer.substr(EOL);
558
559
560    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
561    if (IsCheckNext && CheckStrings.empty()) {
562      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
563                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
564                      CheckPrefix+ ": line", "error");
565      return true;
566    }
567
568    // Handle CHECK-NOT.
569    if (IsCheckNot) {
570      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
571                                          P));
572      continue;
573    }
574
575
576    // Okay, add the string we captured to the output vector and move on.
577    CheckStrings.push_back(CheckString(P,
578                                       PatternLoc,
579                                       IsCheckNext));
580    std::swap(NotMatches, CheckStrings.back().NotStrings);
581  }
582
583  // Add an EOF pattern for any trailing CHECK-NOTs.
584  if (!NotMatches.empty()) {
585    CheckStrings.push_back(CheckString(Pattern(true),
586                                       SMLoc::getFromPointer(Buffer.data()),
587                                       false));
588    std::swap(NotMatches, CheckStrings.back().NotStrings);
589  }
590
591  if (CheckStrings.empty()) {
592    errs() << "error: no check strings found with prefix '" << CheckPrefix
593           << ":'\n";
594    return true;
595  }
596
597  return false;
598}
599
600static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
601                             StringRef Buffer,
602                             StringMap<StringRef> &VariableTable) {
603  // Otherwise, we have an error, emit an error message.
604  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
605                  "error");
606
607  // Print the "scanning from here" line.  If the current position is at the
608  // end of a line, advance to the start of the next line.
609  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
610
611  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
612                  "note");
613
614  // Allow the pattern to print additional information if desired.
615  CheckStr.Pat.PrintFailureInfo(SM, Buffer, VariableTable);
616}
617
618/// CountNumNewlinesBetween - Count the number of newlines in the specified
619/// range.
620static unsigned CountNumNewlinesBetween(StringRef Range) {
621  unsigned NumNewLines = 0;
622  while (1) {
623    // Scan for newline.
624    Range = Range.substr(Range.find_first_of("\n\r"));
625    if (Range.empty()) return NumNewLines;
626
627    ++NumNewLines;
628
629    // Handle \n\r and \r\n as a single newline.
630    if (Range.size() > 1 &&
631        (Range[1] == '\n' || Range[1] == '\r') &&
632        (Range[0] != Range[1]))
633      Range = Range.substr(1);
634    Range = Range.substr(1);
635  }
636}
637
638int main(int argc, char **argv) {
639  sys::PrintStackTraceOnErrorSignal();
640  PrettyStackTraceProgram X(argc, argv);
641  cl::ParseCommandLineOptions(argc, argv);
642
643  SourceMgr SM;
644
645  // Read the expected strings from the check file.
646  std::vector<CheckString> CheckStrings;
647  if (ReadCheckFile(SM, CheckStrings))
648    return 2;
649
650  // Open the file to check and add it to SourceMgr.
651  error_code ec;
652  MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), ec);
653  if (F == 0) {
654    errs() << "Could not open input file '" << InputFilename << "': "
655           << ec.message() << '\n';
656    return true;
657  }
658
659  // Remove duplicate spaces in the input file if requested.
660  if (!NoCanonicalizeWhiteSpace)
661    F = CanonicalizeInputFile(F);
662
663  SM.AddNewSourceBuffer(F, SMLoc());
664
665  /// VariableTable - This holds all the current filecheck variables.
666  StringMap<StringRef> VariableTable;
667
668  // Check that we have all of the expected strings, in order, in the input
669  // file.
670  StringRef Buffer = F->getBuffer();
671
672  const char *LastMatch = Buffer.data();
673
674  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
675    const CheckString &CheckStr = CheckStrings[StrNo];
676
677    StringRef SearchFrom = Buffer;
678
679    // Find StrNo in the file.
680    size_t MatchLen = 0;
681    size_t MatchPos = CheckStr.Pat.Match(Buffer, MatchLen, VariableTable);
682    Buffer = Buffer.substr(MatchPos);
683
684    // If we didn't find a match, reject the input.
685    if (MatchPos == StringRef::npos) {
686      PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable);
687      return 1;
688    }
689
690    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
691
692    // If this check is a "CHECK-NEXT", verify that the previous match was on
693    // the previous line (i.e. that there is one newline between them).
694    if (CheckStr.IsCheckNext) {
695      // Count the number of newlines between the previous match and this one.
696      assert(LastMatch != F->getBufferStart() &&
697             "CHECK-NEXT can't be the first check in a file");
698
699      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
700      if (NumNewLines == 0) {
701        SM.PrintMessage(CheckStr.Loc,
702                    CheckPrefix+"-NEXT: is on the same line as previous match",
703                        "error");
704        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
705                        "'next' match was here", "note");
706        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
707                        "previous match was here", "note");
708        return 1;
709      }
710
711      if (NumNewLines != 1) {
712        SM.PrintMessage(CheckStr.Loc,
713                        CheckPrefix+
714                        "-NEXT: is not on the line after the previous match",
715                        "error");
716        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
717                        "'next' match was here", "note");
718        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
719                        "previous match was here", "note");
720        return 1;
721      }
722    }
723
724    // If this match had "not strings", verify that they don't exist in the
725    // skipped region.
726    for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size();
727         ChunkNo != e; ++ChunkNo) {
728      size_t MatchLen = 0;
729      size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion,
730                                                             MatchLen,
731                                                             VariableTable);
732      if (Pos == StringRef::npos) continue;
733
734      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
735                      CheckPrefix+"-NOT: string occurred!", "error");
736      SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first,
737                      CheckPrefix+"-NOT: pattern specified here", "note");
738      return 1;
739    }
740
741
742    // Otherwise, everything is good.  Step over the matched text and remember
743    // the position after the match as the end of the last match.
744    Buffer = Buffer.substr(MatchLen);
745    LastMatch = Buffer.data();
746  }
747
748  return 0;
749}
750