1//===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===//
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/Frontend/TextDiagnostic.h"
11#include "clang/Basic/FileManager.h"
12#include "clang/Basic/SourceManager.h"
13#include "clang/Basic/ConvertUTF.h"
14#include "clang/Frontend/DiagnosticOptions.h"
15#include "clang/Lex/Lexer.h"
16#include "llvm/Support/MemoryBuffer.h"
17#include "llvm/Support/raw_ostream.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/Locale.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/ADT/StringExtras.h"
22#include <algorithm>
23#include <cctype>
24
25using namespace clang;
26
27static const enum raw_ostream::Colors noteColor =
28  raw_ostream::BLACK;
29static const enum raw_ostream::Colors fixitColor =
30  raw_ostream::GREEN;
31static const enum raw_ostream::Colors caretColor =
32  raw_ostream::GREEN;
33static const enum raw_ostream::Colors warningColor =
34  raw_ostream::MAGENTA;
35static const enum raw_ostream::Colors templateColor =
36  raw_ostream::CYAN;
37static const enum raw_ostream::Colors errorColor = raw_ostream::RED;
38static const enum raw_ostream::Colors fatalColor = raw_ostream::RED;
39// Used for changing only the bold attribute.
40static const enum raw_ostream::Colors savedColor =
41  raw_ostream::SAVEDCOLOR;
42
43/// \brief Add highlights to differences in template strings.
44static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
45                                      bool &Normal, bool Bold) {
46  for (unsigned i = 0, e = Str.size(); i < e; ++i)
47    if (Str[i] != ToggleHighlight) {
48      OS << Str[i];
49    } else {
50      if (Normal)
51        OS.changeColor(templateColor, true);
52      else {
53        OS.resetColor();
54        if (Bold)
55          OS.changeColor(savedColor, true);
56      }
57      Normal = !Normal;
58    }
59}
60
61/// \brief Number of spaces to indent when word-wrapping.
62const unsigned WordWrapIndentation = 6;
63
64static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
65  int bytes = 0;
66  while (0<i) {
67    if (SourceLine[--i]=='\t')
68      break;
69    ++bytes;
70  }
71  return bytes;
72}
73
74/// \brief returns a printable representation of first item from input range
75///
76/// This function returns a printable representation of the next item in a line
77///  of source. If the next byte begins a valid and printable character, that
78///  character is returned along with 'true'.
79///
80/// Otherwise, if the next byte begins a valid, but unprintable character, a
81///  printable, escaped representation of the character is returned, along with
82///  'false'. Otherwise a printable, escaped representation of the next byte
83///  is returned along with 'false'.
84///
85/// \note The index is updated to be used with a subsequent call to
86///        printableTextForNextCharacter.
87///
88/// \param SourceLine The line of source
89/// \param i Pointer to byte index,
90/// \param TabStop used to expand tabs
91/// \return pair(printable text, 'true' iff original text was printable)
92///
93static std::pair<SmallString<16>, bool>
94printableTextForNextCharacter(StringRef SourceLine, size_t *i,
95                              unsigned TabStop) {
96  assert(i && "i must not be null");
97  assert(*i<SourceLine.size() && "must point to a valid index");
98
99  if (SourceLine[*i]=='\t') {
100    assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
101           "Invalid -ftabstop value");
102    unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i);
103    unsigned NumSpaces = TabStop - col%TabStop;
104    assert(0 < NumSpaces && NumSpaces <= TabStop
105           && "Invalid computation of space amt");
106    ++(*i);
107
108    SmallString<16> expandedTab;
109    expandedTab.assign(NumSpaces, ' ');
110    return std::make_pair(expandedTab, true);
111  }
112
113  // FIXME: this data is copied from the private implementation of ConvertUTF.h
114  static const char trailingBytesForUTF8[256] = {
115    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
116    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
117    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
118    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
119    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
120    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
121    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
122    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
123  };
124
125  unsigned char const *begin, *end;
126  begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
127  end = begin + SourceLine.size();
128
129  if (isLegalUTF8Sequence(begin, end)) {
130    UTF32 c;
131    UTF32 *cptr = &c;
132    unsigned char const *original_begin = begin;
133    char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]];
134    unsigned char const *cp_end = begin+trailingBytes+1;
135
136    ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
137                                              strictConversion);
138    (void)res;
139    assert(conversionOK==res);
140    assert(0 < begin-original_begin
141           && "we must be further along in the string now");
142    *i += begin-original_begin;
143
144    if (!llvm::sys::locale::isPrint(c)) {
145      // If next character is valid UTF-8, but not printable
146      SmallString<16> expandedCP("<U+>");
147      while (c) {
148        expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
149        c/=16;
150      }
151      while (expandedCP.size() < 8)
152        expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
153      return std::make_pair(expandedCP, false);
154    }
155
156    // If next character is valid UTF-8, and printable
157    return std::make_pair(SmallString<16>(original_begin, cp_end), true);
158
159  }
160
161  // If next byte is not valid UTF-8 (and therefore not printable)
162  SmallString<16> expandedByte("<XX>");
163  unsigned char byte = SourceLine[*i];
164  expandedByte[1] = llvm::hexdigit(byte / 16);
165  expandedByte[2] = llvm::hexdigit(byte % 16);
166  ++(*i);
167  return std::make_pair(expandedByte, false);
168}
169
170static void expandTabs(std::string &SourceLine, unsigned TabStop) {
171  size_t i = SourceLine.size();
172  while (i>0) {
173    i--;
174    if (SourceLine[i]!='\t')
175      continue;
176    size_t tmp_i = i;
177    std::pair<SmallString<16>,bool> res
178      = printableTextForNextCharacter(SourceLine, &tmp_i, TabStop);
179    SourceLine.replace(i, 1, res.first.c_str());
180  }
181}
182
183/// This function takes a raw source line and produces a mapping from the bytes
184///  of the printable representation of the line to the columns those printable
185///  characters will appear at (numbering the first column as 0).
186///
187/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
188///  character) then the array will map that byte to the first column the
189///  tab appears at and the next value in the map will have been incremented
190///  more than once.
191///
192/// If a byte is the first in a sequence of bytes that together map to a single
193///  entity in the output, then the array will map that byte to the appropriate
194///  column while the subsequent bytes will be -1.
195///
196/// The last element in the array does not correspond to any byte in the input
197///  and instead is the number of columns needed to display the source
198///
199/// example: (given a tabstop of 8)
200///
201///    "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
202///
203///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
204///   display)
205static void byteToColumn(StringRef SourceLine, unsigned TabStop,
206                         SmallVectorImpl<int> &out) {
207  out.clear();
208
209  if (SourceLine.empty()) {
210    out.resize(1u,0);
211    return;
212  }
213
214  out.resize(SourceLine.size()+1, -1);
215
216  int columns = 0;
217  size_t i = 0;
218  while (i<SourceLine.size()) {
219    out[i] = columns;
220    std::pair<SmallString<16>,bool> res
221      = printableTextForNextCharacter(SourceLine, &i, TabStop);
222    columns += llvm::sys::locale::columnWidth(res.first);
223  }
224  out.back() = columns;
225}
226
227/// This function takes a raw source line and produces a mapping from columns
228///  to the byte of the source line that produced the character displaying at
229///  that column. This is the inverse of the mapping produced by byteToColumn()
230///
231/// The last element in the array is the number of bytes in the source string
232///
233/// example: (given a tabstop of 8)
234///
235///    "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
236///
237///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
238///   display)
239static void columnToByte(StringRef SourceLine, unsigned TabStop,
240                         SmallVectorImpl<int> &out) {
241  out.clear();
242
243  if (SourceLine.empty()) {
244    out.resize(1u, 0);
245    return;
246  }
247
248  int columns = 0;
249  size_t i = 0;
250  while (i<SourceLine.size()) {
251    out.resize(columns+1, -1);
252    out.back() = i;
253    std::pair<SmallString<16>,bool> res
254      = printableTextForNextCharacter(SourceLine, &i, TabStop);
255    columns += llvm::sys::locale::columnWidth(res.first);
256  }
257  out.resize(columns+1, -1);
258  out.back() = i;
259}
260
261struct SourceColumnMap {
262  SourceColumnMap(StringRef SourceLine, unsigned TabStop)
263  : m_SourceLine(SourceLine) {
264
265    ::byteToColumn(SourceLine, TabStop, m_byteToColumn);
266    ::columnToByte(SourceLine, TabStop, m_columnToByte);
267
268    assert(m_byteToColumn.size()==SourceLine.size()+1);
269    assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
270    assert(m_byteToColumn.size()
271           == static_cast<unsigned>(m_columnToByte.back()+1));
272    assert(static_cast<unsigned>(m_byteToColumn.back()+1)
273           == m_columnToByte.size());
274  }
275  int columns() const { return m_byteToColumn.back(); }
276  int bytes() const { return m_columnToByte.back(); }
277  int byteToColumn(int n) const {
278    assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
279    return m_byteToColumn[n];
280  }
281  int columnToByte(int n) const {
282    assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
283    return m_columnToByte[n];
284  }
285  StringRef getSourceLine() const {
286    return m_SourceLine;
287  }
288
289private:
290  const std::string m_SourceLine;
291  SmallVector<int,200> m_byteToColumn;
292  SmallVector<int,200> m_columnToByte;
293};
294
295// used in assert in selectInterestingSourceRegion()
296namespace {
297struct char_out_of_range {
298  const char lower,upper;
299  char_out_of_range(char lower, char upper) :
300    lower(lower), upper(upper) {}
301  bool operator()(char c) { return c < lower || upper < c; }
302};
303}
304
305/// \brief When the source code line we want to print is too long for
306/// the terminal, select the "interesting" region.
307static void selectInterestingSourceRegion(std::string &SourceLine,
308                                          std::string &CaretLine,
309                                          std::string &FixItInsertionLine,
310                                          unsigned Columns,
311                                          const SourceColumnMap &map) {
312  unsigned MaxColumns = std::max<unsigned>(map.columns(),
313                                           std::max(CaretLine.size(),
314                                                    FixItInsertionLine.size()));
315  // if the number of columns is less than the desired number we're done
316  if (MaxColumns <= Columns)
317    return;
318
319  // no special characters allowed in CaretLine or FixItInsertionLine
320  assert(CaretLine.end() ==
321         std::find_if(CaretLine.begin(), CaretLine.end(),
322         char_out_of_range(' ','~')));
323  assert(FixItInsertionLine.end() ==
324         std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
325         char_out_of_range(' ','~')));
326
327  // Find the slice that we need to display the full caret line
328  // correctly.
329  unsigned CaretStart = 0, CaretEnd = CaretLine.size();
330  for (; CaretStart != CaretEnd; ++CaretStart)
331    if (!isspace(static_cast<unsigned char>(CaretLine[CaretStart])))
332      break;
333
334  for (; CaretEnd != CaretStart; --CaretEnd)
335    if (!isspace(static_cast<unsigned char>(CaretLine[CaretEnd - 1])))
336      break;
337
338  // caret has already been inserted into CaretLine so the above whitespace
339  // check is guaranteed to include the caret
340
341  // If we have a fix-it line, make sure the slice includes all of the
342  // fix-it information.
343  if (!FixItInsertionLine.empty()) {
344    unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
345    for (; FixItStart != FixItEnd; ++FixItStart)
346      if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItStart])))
347        break;
348
349    for (; FixItEnd != FixItStart; --FixItEnd)
350      if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItEnd - 1])))
351        break;
352
353    CaretStart = std::min(FixItStart, CaretStart);
354    CaretEnd = std::max(FixItEnd, CaretEnd);
355  }
356
357  // CaretEnd may have been set at the middle of a character
358  // If it's not at a character's first column then advance it past the current
359  //   character.
360  while (static_cast<int>(CaretEnd) < map.columns() &&
361         -1 == map.columnToByte(CaretEnd))
362    ++CaretEnd;
363
364  assert((static_cast<int>(CaretStart) > map.columns() ||
365          -1!=map.columnToByte(CaretStart)) &&
366         "CaretStart must not point to a column in the middle of a source"
367         " line character");
368  assert((static_cast<int>(CaretEnd) > map.columns() ||
369          -1!=map.columnToByte(CaretEnd)) &&
370         "CaretEnd must not point to a column in the middle of a source line"
371         " character");
372
373  // CaretLine[CaretStart, CaretEnd) contains all of the interesting
374  // parts of the caret line. While this slice is smaller than the
375  // number of columns we have, try to grow the slice to encompass
376  // more context.
377
378  unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
379                                                             map.columns()));
380  unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
381                                                           map.columns()));
382
383  unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
384    - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
385
386  char const *front_ellipse = "  ...";
387  char const *front_space   = "     ";
388  char const *back_ellipse = "...";
389  unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
390
391  unsigned TargetColumns = Columns;
392  // Give us extra room for the ellipses
393  //  and any of the caret line that extends past the source
394  if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
395    TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
396
397  while (SourceStart>0 || SourceEnd<SourceLine.size()) {
398    bool ExpandedRegion = false;
399
400    if (SourceStart>0) {
401      unsigned NewStart = SourceStart-1;
402
403      // Skip over any whitespace we see here; we're looking for
404      // another bit of interesting text.
405      while (NewStart &&
406             (map.byteToColumn(NewStart)==-1 ||
407             isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
408        --NewStart;
409
410      // Skip over this bit of "interesting" text.
411      while (NewStart &&
412             (map.byteToColumn(NewStart)!=-1 &&
413             !isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
414        --NewStart;
415
416      // Move up to the non-whitespace character we just saw.
417      if (NewStart)
418        ++NewStart;
419
420      unsigned NewColumns = map.byteToColumn(SourceEnd) -
421                              map.byteToColumn(NewStart);
422      if (NewColumns <= TargetColumns) {
423        SourceStart = NewStart;
424        ExpandedRegion = true;
425      }
426    }
427
428    if (SourceEnd<SourceLine.size()) {
429      unsigned NewEnd = SourceEnd+1;
430
431      // Skip over any whitespace we see here; we're looking for
432      // another bit of interesting text.
433      while (NewEnd<SourceLine.size() &&
434             (map.byteToColumn(NewEnd)==-1 ||
435             isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
436        ++NewEnd;
437
438      // Skip over this bit of "interesting" text.
439      while (NewEnd<SourceLine.size() &&
440             (map.byteToColumn(NewEnd)!=-1 &&
441             !isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
442        ++NewEnd;
443
444      unsigned NewColumns = map.byteToColumn(NewEnd) -
445                              map.byteToColumn(SourceStart);
446      if (NewColumns <= TargetColumns) {
447        SourceEnd = NewEnd;
448        ExpandedRegion = true;
449      }
450    }
451
452    if (!ExpandedRegion)
453      break;
454  }
455
456  CaretStart = map.byteToColumn(SourceStart);
457  CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
458
459  // [CaretStart, CaretEnd) is the slice we want. Update the various
460  // output lines to show only this slice, with two-space padding
461  // before the lines so that it looks nicer.
462
463  assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
464         SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
465  assert(SourceStart <= SourceEnd);
466  assert(CaretStart <= CaretEnd);
467
468  unsigned BackColumnsRemoved
469    = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
470  unsigned FrontColumnsRemoved = CaretStart;
471  unsigned ColumnsKept = CaretEnd-CaretStart;
472
473  // We checked up front that the line needed truncation
474  assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
475
476  // The line needs some trunctiona, and we'd prefer to keep the front
477  //  if possible, so remove the back
478  if (BackColumnsRemoved)
479    SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
480
481  // If that's enough then we're done
482  if (FrontColumnsRemoved+ColumnsKept <= Columns)
483    return;
484
485  // Otherwise remove the front as well
486  if (FrontColumnsRemoved) {
487    SourceLine.replace(0, SourceStart, front_ellipse);
488    CaretLine.replace(0, CaretStart, front_space);
489    if (!FixItInsertionLine.empty())
490      FixItInsertionLine.replace(0, CaretStart, front_space);
491  }
492}
493
494/// \brief Skip over whitespace in the string, starting at the given
495/// index.
496///
497/// \returns The index of the first non-whitespace character that is
498/// greater than or equal to Idx or, if no such character exists,
499/// returns the end of the string.
500static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {
501  while (Idx < Length && isspace(Str[Idx]))
502    ++Idx;
503  return Idx;
504}
505
506/// \brief If the given character is the start of some kind of
507/// balanced punctuation (e.g., quotes or parentheses), return the
508/// character that will terminate the punctuation.
509///
510/// \returns The ending punctuation character, if any, or the NULL
511/// character if the input character does not start any punctuation.
512static inline char findMatchingPunctuation(char c) {
513  switch (c) {
514  case '\'': return '\'';
515  case '`': return '\'';
516  case '"':  return '"';
517  case '(':  return ')';
518  case '[': return ']';
519  case '{': return '}';
520  default: break;
521  }
522
523  return 0;
524}
525
526/// \brief Find the end of the word starting at the given offset
527/// within a string.
528///
529/// \returns the index pointing one character past the end of the
530/// word.
531static unsigned findEndOfWord(unsigned Start, StringRef Str,
532                              unsigned Length, unsigned Column,
533                              unsigned Columns) {
534  assert(Start < Str.size() && "Invalid start position!");
535  unsigned End = Start + 1;
536
537  // If we are already at the end of the string, take that as the word.
538  if (End == Str.size())
539    return End;
540
541  // Determine if the start of the string is actually opening
542  // punctuation, e.g., a quote or parentheses.
543  char EndPunct = findMatchingPunctuation(Str[Start]);
544  if (!EndPunct) {
545    // This is a normal word. Just find the first space character.
546    while (End < Length && !isspace(Str[End]))
547      ++End;
548    return End;
549  }
550
551  // We have the start of a balanced punctuation sequence (quotes,
552  // parentheses, etc.). Determine the full sequence is.
553  SmallString<16> PunctuationEndStack;
554  PunctuationEndStack.push_back(EndPunct);
555  while (End < Length && !PunctuationEndStack.empty()) {
556    if (Str[End] == PunctuationEndStack.back())
557      PunctuationEndStack.pop_back();
558    else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
559      PunctuationEndStack.push_back(SubEndPunct);
560
561    ++End;
562  }
563
564  // Find the first space character after the punctuation ended.
565  while (End < Length && !isspace(Str[End]))
566    ++End;
567
568  unsigned PunctWordLength = End - Start;
569  if (// If the word fits on this line
570      Column + PunctWordLength <= Columns ||
571      // ... or the word is "short enough" to take up the next line
572      // without too much ugly white space
573      PunctWordLength < Columns/3)
574    return End; // Take the whole thing as a single "word".
575
576  // The whole quoted/parenthesized string is too long to print as a
577  // single "word". Instead, find the "word" that starts just after
578  // the punctuation and use that end-point instead. This will recurse
579  // until it finds something small enough to consider a word.
580  return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
581}
582
583/// \brief Print the given string to a stream, word-wrapping it to
584/// some number of columns in the process.
585///
586/// \param OS the stream to which the word-wrapping string will be
587/// emitted.
588/// \param Str the string to word-wrap and output.
589/// \param Columns the number of columns to word-wrap to.
590/// \param Column the column number at which the first character of \p
591/// Str will be printed. This will be non-zero when part of the first
592/// line has already been printed.
593/// \param Bold if the current text should be bold
594/// \param Indentation the number of spaces to indent any lines beyond
595/// the first line.
596/// \returns true if word-wrapping was required, or false if the
597/// string fit on the first line.
598static bool printWordWrapped(raw_ostream &OS, StringRef Str,
599                             unsigned Columns,
600                             unsigned Column = 0,
601                             bool Bold = false,
602                             unsigned Indentation = WordWrapIndentation) {
603  const unsigned Length = std::min(Str.find('\n'), Str.size());
604  bool TextNormal = true;
605
606  // The string used to indent each line.
607  SmallString<16> IndentStr;
608  IndentStr.assign(Indentation, ' ');
609  bool Wrapped = false;
610  for (unsigned WordStart = 0, WordEnd; WordStart < Length;
611       WordStart = WordEnd) {
612    // Find the beginning of the next word.
613    WordStart = skipWhitespace(WordStart, Str, Length);
614    if (WordStart == Length)
615      break;
616
617    // Find the end of this word.
618    WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
619
620    // Does this word fit on the current line?
621    unsigned WordLength = WordEnd - WordStart;
622    if (Column + WordLength < Columns) {
623      // This word fits on the current line; print it there.
624      if (WordStart) {
625        OS << ' ';
626        Column += 1;
627      }
628      applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
629                                TextNormal, Bold);
630      Column += WordLength;
631      continue;
632    }
633
634    // This word does not fit on the current line, so wrap to the next
635    // line.
636    OS << '\n';
637    OS.write(&IndentStr[0], Indentation);
638    applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
639                              TextNormal, Bold);
640    Column = Indentation + WordLength;
641    Wrapped = true;
642  }
643
644  // Append any remaning text from the message with its existing formatting.
645  applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold);
646
647  assert(TextNormal && "Text highlighted at end of diagnostic message.");
648
649  return Wrapped;
650}
651
652TextDiagnostic::TextDiagnostic(raw_ostream &OS,
653                               const LangOptions &LangOpts,
654                               const DiagnosticOptions &DiagOpts)
655  : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
656
657TextDiagnostic::~TextDiagnostic() {}
658
659void
660TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
661                                      PresumedLoc PLoc,
662                                      DiagnosticsEngine::Level Level,
663                                      StringRef Message,
664                                      ArrayRef<clang::CharSourceRange> Ranges,
665                                      const SourceManager *SM,
666                                      DiagOrStoredDiag D) {
667  uint64_t StartOfLocationInfo = OS.tell();
668
669  // Emit the location of this particular diagnostic.
670  if (Loc.isValid())
671    emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
672
673  if (DiagOpts.ShowColors)
674    OS.resetColor();
675
676  printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
677  printDiagnosticMessage(OS, Level, Message,
678                         OS.tell() - StartOfLocationInfo,
679                         DiagOpts.MessageLength, DiagOpts.ShowColors);
680}
681
682/*static*/ void
683TextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
684                                     DiagnosticsEngine::Level Level,
685                                     bool ShowColors) {
686  if (ShowColors) {
687    // Print diagnostic category in bold and color
688    switch (Level) {
689    case DiagnosticsEngine::Ignored:
690      llvm_unreachable("Invalid diagnostic type");
691    case DiagnosticsEngine::Note:    OS.changeColor(noteColor, true); break;
692    case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break;
693    case DiagnosticsEngine::Error:   OS.changeColor(errorColor, true); break;
694    case DiagnosticsEngine::Fatal:   OS.changeColor(fatalColor, true); break;
695    }
696  }
697
698  switch (Level) {
699  case DiagnosticsEngine::Ignored:
700    llvm_unreachable("Invalid diagnostic type");
701  case DiagnosticsEngine::Note:    OS << "note: "; break;
702  case DiagnosticsEngine::Warning: OS << "warning: "; break;
703  case DiagnosticsEngine::Error:   OS << "error: "; break;
704  case DiagnosticsEngine::Fatal:   OS << "fatal error: "; break;
705  }
706
707  if (ShowColors)
708    OS.resetColor();
709}
710
711/*static*/ void
712TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
713                                       DiagnosticsEngine::Level Level,
714                                       StringRef Message,
715                                       unsigned CurrentColumn, unsigned Columns,
716                                       bool ShowColors) {
717  bool Bold = false;
718  if (ShowColors) {
719    // Print warnings, errors and fatal errors in bold, no color
720    switch (Level) {
721    case DiagnosticsEngine::Warning:
722    case DiagnosticsEngine::Error:
723    case DiagnosticsEngine::Fatal:
724      OS.changeColor(savedColor, true);
725      Bold = true;
726      break;
727    default: break; //don't bold notes
728    }
729  }
730
731  if (Columns)
732    printWordWrapped(OS, Message, Columns, CurrentColumn, Bold);
733  else {
734    bool Normal = true;
735    applyTemplateHighlighting(OS, Message, Normal, Bold);
736    assert(Normal && "Formatting should have returned to normal");
737  }
738
739  if (ShowColors)
740    OS.resetColor();
741  OS << '\n';
742}
743
744/// \brief Print out the file/line/column information and include trace.
745///
746/// This method handlen the emission of the diagnostic location information.
747/// This includes extracting as much location information as is present for
748/// the diagnostic and printing it, as well as any include stack or source
749/// ranges necessary.
750void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
751                                       DiagnosticsEngine::Level Level,
752                                       ArrayRef<CharSourceRange> Ranges,
753                                       const SourceManager &SM) {
754  if (PLoc.isInvalid()) {
755    // At least print the file name if available:
756    FileID FID = SM.getFileID(Loc);
757    if (!FID.isInvalid()) {
758      const FileEntry* FE = SM.getFileEntryForID(FID);
759      if (FE && FE->getName()) {
760        OS << FE->getName();
761        if (FE->getDevice() == 0 && FE->getInode() == 0
762            && FE->getFileMode() == 0) {
763          // in PCH is a guess, but a good one:
764          OS << " (in PCH)";
765        }
766        OS << ": ";
767      }
768    }
769    return;
770  }
771  unsigned LineNo = PLoc.getLine();
772
773  if (!DiagOpts.ShowLocation)
774    return;
775
776  if (DiagOpts.ShowColors)
777    OS.changeColor(savedColor, true);
778
779  OS << PLoc.getFilename();
780  switch (DiagOpts.Format) {
781  case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
782  case DiagnosticOptions::Msvc:  OS << '('  << LineNo; break;
783  case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
784  }
785
786  if (DiagOpts.ShowColumn)
787    // Compute the column number.
788    if (unsigned ColNo = PLoc.getColumn()) {
789      if (DiagOpts.Format == DiagnosticOptions::Msvc) {
790        OS << ',';
791        ColNo--;
792      } else
793        OS << ':';
794      OS << ColNo;
795    }
796  switch (DiagOpts.Format) {
797  case DiagnosticOptions::Clang:
798  case DiagnosticOptions::Vi:    OS << ':';    break;
799  case DiagnosticOptions::Msvc:  OS << ") : "; break;
800  }
801
802  if (DiagOpts.ShowSourceRanges && !Ranges.empty()) {
803    FileID CaretFileID =
804      SM.getFileID(SM.getExpansionLoc(Loc));
805    bool PrintedRange = false;
806
807    for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
808         RE = Ranges.end();
809         RI != RE; ++RI) {
810      // Ignore invalid ranges.
811      if (!RI->isValid()) continue;
812
813      SourceLocation B = SM.getExpansionLoc(RI->getBegin());
814      SourceLocation E = SM.getExpansionLoc(RI->getEnd());
815
816      // If the End location and the start location are the same and are a
817      // macro location, then the range was something that came from a
818      // macro expansion or _Pragma.  If this is an object-like macro, the
819      // best we can do is to highlight the range.  If this is a
820      // function-like macro, we'd also like to highlight the arguments.
821      if (B == E && RI->getEnd().isMacroID())
822        E = SM.getExpansionRange(RI->getEnd()).second;
823
824      std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
825      std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
826
827      // If the start or end of the range is in another file, just discard
828      // it.
829      if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
830        continue;
831
832      // Add in the length of the token, so that we cover multi-char
833      // tokens.
834      unsigned TokSize = 0;
835      if (RI->isTokenRange())
836        TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
837
838      OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
839        << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
840        << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
841        << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
842        << '}';
843      PrintedRange = true;
844    }
845
846    if (PrintedRange)
847      OS << ':';
848  }
849  OS << ' ';
850}
851
852void TextDiagnostic::emitBasicNote(StringRef Message) {
853  // FIXME: Emit this as a real note diagnostic.
854  // FIXME: Format an actual diagnostic rather than a hard coded string.
855  OS << "note: " << Message << "\n";
856}
857
858void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
859                                         PresumedLoc PLoc,
860                                         const SourceManager &SM) {
861  if (DiagOpts.ShowLocation)
862    OS << "In file included from " << PLoc.getFilename() << ':'
863       << PLoc.getLine() << ":\n";
864  else
865    OS << "In included file:\n";
866}
867
868/// \brief Emit a code snippet and caret line.
869///
870/// This routine emits a single line's code snippet and caret line..
871///
872/// \param Loc The location for the caret.
873/// \param Ranges The underlined ranges for this code snippet.
874/// \param Hints The FixIt hints active for this diagnostic.
875void TextDiagnostic::emitSnippetAndCaret(
876    SourceLocation Loc, DiagnosticsEngine::Level Level,
877    SmallVectorImpl<CharSourceRange>& Ranges,
878    ArrayRef<FixItHint> Hints,
879    const SourceManager &SM) {
880  assert(!Loc.isInvalid() && "must have a valid source location here");
881  assert(Loc.isFileID() && "must have a file location here");
882
883  // If caret diagnostics are enabled and we have location, we want to
884  // emit the caret.  However, we only do this if the location moved
885  // from the last diagnostic, if the last diagnostic was a note that
886  // was part of a different warning or error diagnostic, or if the
887  // diagnostic has ranges.  We don't want to emit the same caret
888  // multiple times if one loc has multiple diagnostics.
889  if (!DiagOpts.ShowCarets)
890    return;
891  if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
892      (LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
893    return;
894
895  // Decompose the location into a FID/Offset pair.
896  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
897  FileID FID = LocInfo.first;
898  unsigned FileOffset = LocInfo.second;
899
900  // Get information about the buffer it points into.
901  bool Invalid = false;
902  const char *BufStart = SM.getBufferData(FID, &Invalid).data();
903  if (Invalid)
904    return;
905
906  unsigned LineNo = SM.getLineNumber(FID, FileOffset);
907  unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
908
909  // Rewind from the current position to the start of the line.
910  const char *TokPtr = BufStart+FileOffset;
911  const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
912
913
914  // Compute the line end.  Scan forward from the error position to the end of
915  // the line.
916  const char *LineEnd = TokPtr;
917  while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
918    ++LineEnd;
919
920  // Copy the line of code into an std::string for ease of manipulation.
921  std::string SourceLine(LineStart, LineEnd);
922
923  // Create a line for the caret that is filled with spaces that is the same
924  // length as the line of source code.
925  std::string CaretLine(LineEnd-LineStart, ' ');
926
927  const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
928
929  // Highlight all of the characters covered by Ranges with ~ characters.
930  for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
931                                                  E = Ranges.end();
932       I != E; ++I)
933    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
934
935  // Next, insert the caret itself.
936  ColNo = sourceColMap.byteToColumn(ColNo-1);
937  if (CaretLine.size()<ColNo+1)
938    CaretLine.resize(ColNo+1, ' ');
939  CaretLine[ColNo] = '^';
940
941  std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
942                                                           sourceColMap,
943                                                           Hints, SM);
944
945  // If the source line is too long for our terminal, select only the
946  // "interesting" source region within that line.
947  unsigned Columns = DiagOpts.MessageLength;
948  if (Columns)
949    selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
950                                  Columns, sourceColMap);
951
952  // If we are in -fdiagnostics-print-source-range-info mode, we are trying
953  // to produce easily machine parsable output.  Add a space before the
954  // source line and the caret to make it trivial to tell the main diagnostic
955  // line from what the user is intended to see.
956  if (DiagOpts.ShowSourceRanges) {
957    SourceLine = ' ' + SourceLine;
958    CaretLine = ' ' + CaretLine;
959  }
960
961  // Finally, remove any blank spaces from the end of CaretLine.
962  while (CaretLine[CaretLine.size()-1] == ' ')
963    CaretLine.erase(CaretLine.end()-1);
964
965  // Emit what we have computed.
966  emitSnippet(SourceLine);
967
968  if (DiagOpts.ShowColors)
969    OS.changeColor(caretColor, true);
970  OS << CaretLine << '\n';
971  if (DiagOpts.ShowColors)
972    OS.resetColor();
973
974  if (!FixItInsertionLine.empty()) {
975    if (DiagOpts.ShowColors)
976      // Print fixit line in color
977      OS.changeColor(fixitColor, false);
978    if (DiagOpts.ShowSourceRanges)
979      OS << ' ';
980    OS << FixItInsertionLine << '\n';
981    if (DiagOpts.ShowColors)
982      OS.resetColor();
983  }
984
985  // Print out any parseable fixit information requested by the options.
986  emitParseableFixits(Hints, SM);
987}
988
989void TextDiagnostic::emitSnippet(StringRef line) {
990  if (line.empty())
991    return;
992
993  size_t i = 0;
994
995  std::string to_print;
996  bool print_reversed = false;
997
998  while (i<line.size()) {
999    std::pair<SmallString<16>,bool> res
1000        = printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
1001    bool was_printable = res.second;
1002
1003    if (DiagOpts.ShowColors && was_printable == print_reversed) {
1004      if (print_reversed)
1005        OS.reverseColor();
1006      OS << to_print;
1007      to_print.clear();
1008      if (DiagOpts.ShowColors)
1009        OS.resetColor();
1010    }
1011
1012    print_reversed = !was_printable;
1013    to_print += res.first.str();
1014  }
1015
1016  if (print_reversed && DiagOpts.ShowColors)
1017    OS.reverseColor();
1018  OS << to_print;
1019  if (print_reversed && DiagOpts.ShowColors)
1020    OS.resetColor();
1021
1022  OS << '\n';
1023}
1024
1025/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
1026void TextDiagnostic::highlightRange(const CharSourceRange &R,
1027                                    unsigned LineNo, FileID FID,
1028                                    const SourceColumnMap &map,
1029                                    std::string &CaretLine,
1030                                    const SourceManager &SM) {
1031  if (!R.isValid()) return;
1032
1033  SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
1034  SourceLocation End = SM.getExpansionLoc(R.getEnd());
1035
1036  // If the End location and the start location are the same and are a macro
1037  // location, then the range was something that came from a macro expansion
1038  // or _Pragma.  If this is an object-like macro, the best we can do is to
1039  // highlight the range.  If this is a function-like macro, we'd also like to
1040  // highlight the arguments.
1041  if (Begin == End && R.getEnd().isMacroID())
1042    End = SM.getExpansionRange(R.getEnd()).second;
1043
1044  unsigned StartLineNo = SM.getExpansionLineNumber(Begin);
1045  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
1046    return;  // No intersection.
1047
1048  unsigned EndLineNo = SM.getExpansionLineNumber(End);
1049  if (EndLineNo < LineNo || SM.getFileID(End) != FID)
1050    return;  // No intersection.
1051
1052  // Compute the column number of the start.
1053  unsigned StartColNo = 0;
1054  if (StartLineNo == LineNo) {
1055    StartColNo = SM.getExpansionColumnNumber(Begin);
1056    if (StartColNo) --StartColNo;  // Zero base the col #.
1057  }
1058
1059  // Compute the column number of the end.
1060  unsigned EndColNo = map.getSourceLine().size();
1061  if (EndLineNo == LineNo) {
1062    EndColNo = SM.getExpansionColumnNumber(End);
1063    if (EndColNo) {
1064      --EndColNo;  // Zero base the col #.
1065
1066      // Add in the length of the token, so that we cover multi-char tokens if
1067      // this is a token range.
1068      if (R.isTokenRange())
1069        EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts);
1070    } else {
1071      EndColNo = CaretLine.size();
1072    }
1073  }
1074
1075  assert(StartColNo <= EndColNo && "Invalid range!");
1076
1077  // Check that a token range does not highlight only whitespace.
1078  if (R.isTokenRange()) {
1079    // Pick the first non-whitespace column.
1080    while (StartColNo < map.getSourceLine().size() &&
1081           (map.getSourceLine()[StartColNo] == ' ' ||
1082            map.getSourceLine()[StartColNo] == '\t'))
1083      ++StartColNo;
1084
1085    // Pick the last non-whitespace column.
1086    if (EndColNo > map.getSourceLine().size())
1087      EndColNo = map.getSourceLine().size();
1088    while (EndColNo-1 &&
1089           (map.getSourceLine()[EndColNo-1] == ' ' ||
1090            map.getSourceLine()[EndColNo-1] == '\t'))
1091      --EndColNo;
1092
1093    // If the start/end passed each other, then we are trying to highlight a
1094    // range that just exists in whitespace, which must be some sort of other
1095    // bug.
1096    assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
1097  }
1098
1099  assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
1100  assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
1101
1102  // Fill the range with ~'s.
1103  StartColNo = map.byteToColumn(StartColNo);
1104  EndColNo = map.byteToColumn(EndColNo);
1105
1106  assert(StartColNo <= EndColNo && "Invalid range!");
1107  if (CaretLine.size() < EndColNo)
1108    CaretLine.resize(EndColNo,' ');
1109  std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
1110}
1111
1112std::string TextDiagnostic::buildFixItInsertionLine(
1113  unsigned LineNo,
1114  const SourceColumnMap &map,
1115  ArrayRef<FixItHint> Hints,
1116  const SourceManager &SM) {
1117
1118  std::string FixItInsertionLine;
1119  if (Hints.empty() || !DiagOpts.ShowFixits)
1120    return FixItInsertionLine;
1121  unsigned PrevHintEndCol = 0;
1122
1123  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1124       I != E; ++I) {
1125    if (!I->CodeToInsert.empty()) {
1126      // We have an insertion hint. Determine whether the inserted
1127      // code contains no newlines and is on the same line as the caret.
1128      std::pair<FileID, unsigned> HintLocInfo
1129        = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin());
1130      if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1131          StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) {
1132        // Insert the new code into the line just below the code
1133        // that the user wrote.
1134        // Note: When modifying this function, be very careful about what is a
1135        // "column" (printed width, platform-dependent) and what is a
1136        // "byte offset" (SourceManager "column").
1137        unsigned HintByteOffset
1138          = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
1139
1140        // The hint must start inside the source or right at the end
1141        assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1142        unsigned HintCol = map.byteToColumn(HintByteOffset);
1143
1144        // If we inserted a long previous hint, push this one forwards, and add
1145        // an extra space to show that this is not part of the previous
1146        // completion. This is sort of the best we can do when two hints appear
1147        // to overlap.
1148        //
1149        // Note that if this hint is located immediately after the previous
1150        // hint, no space will be added, since the location is more important.
1151        if (HintCol < PrevHintEndCol)
1152          HintCol = PrevHintEndCol + 1;
1153
1154        // FIXME: This function handles multibyte characters in the source, but
1155        // not in the fixits. This assertion is intended to catch unintended
1156        // use of multibyte characters in fixits. If we decide to do this, we'll
1157        // have to track separate byte widths for the source and fixit lines.
1158        assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
1159               I->CodeToInsert.size());
1160
1161        // This relies on one byte per column in our fixit hints.
1162        // This should NOT use HintByteOffset, because the source might have
1163        // Unicode characters in earlier columns.
1164        unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
1165        if (LastColumnModified > FixItInsertionLine.size())
1166          FixItInsertionLine.resize(LastColumnModified, ' ');
1167
1168        std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1169                  FixItInsertionLine.begin() + HintCol);
1170
1171        PrevHintEndCol = LastColumnModified;
1172      } else {
1173        FixItInsertionLine.clear();
1174        break;
1175      }
1176    }
1177  }
1178
1179  expandTabs(FixItInsertionLine, DiagOpts.TabStop);
1180
1181  return FixItInsertionLine;
1182}
1183
1184void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
1185                                         const SourceManager &SM) {
1186  if (!DiagOpts.ShowParseableFixits)
1187    return;
1188
1189  // We follow FixItRewriter's example in not (yet) handling
1190  // fix-its in macros.
1191  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1192       I != E; ++I) {
1193    if (I->RemoveRange.isInvalid() ||
1194        I->RemoveRange.getBegin().isMacroID() ||
1195        I->RemoveRange.getEnd().isMacroID())
1196      return;
1197  }
1198
1199  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1200       I != E; ++I) {
1201    SourceLocation BLoc = I->RemoveRange.getBegin();
1202    SourceLocation ELoc = I->RemoveRange.getEnd();
1203
1204    std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
1205    std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
1206
1207    // Adjust for token ranges.
1208    if (I->RemoveRange.isTokenRange())
1209      EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts);
1210
1211    // We specifically do not do word-wrapping or tab-expansion here,
1212    // because this is supposed to be easy to parse.
1213    PresumedLoc PLoc = SM.getPresumedLoc(BLoc);
1214    if (PLoc.isInvalid())
1215      break;
1216
1217    OS << "fix-it:\"";
1218    OS.write_escaped(PLoc.getFilename());
1219    OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
1220      << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
1221      << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
1222      << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
1223      << "}:\"";
1224    OS.write_escaped(I->CodeToInsert);
1225    OS << "\"\n";
1226  }
1227}
1228