| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This code simply runs the preprocessor on the input file and prints out the | 
|  | 11 | // result.  This is the traditional behavior of the -E option. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "clang.h" | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 16 | #include "clang/Lex/MacroInfo.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 17 | #include "clang/Lex/PPCallbacks.h" | 
|  | 18 | #include "clang/Lex/Preprocessor.h" | 
|  | 19 | #include "clang/Lex/Pragma.h" | 
|  | 20 | #include "clang/Basic/SourceManager.h" | 
| Chris Lattner | 5db17c9 | 2008-04-08 04:16:20 +0000 | [diff] [blame] | 21 | #include "clang/Basic/Diagnostic.h" | 
| Chris Lattner | d8e3083 | 2007-07-24 06:57:14 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/SmallString.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/StringExtras.h" | 
| Chris Lattner | 5db17c9 | 2008-04-08 04:16:20 +0000 | [diff] [blame] | 24 | #include "llvm/System/Path.h" | 
|  | 25 | #include "llvm/Support/CommandLine.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 26 | #include "llvm/Config/config.h" | 
| Chris Lattner | dceb6a7 | 2008-08-17 01:47:12 +0000 | [diff] [blame] | 27 | #include "llvm/Support/raw_ostream.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 28 | #include <cstdio> | 
|  | 29 | using namespace clang; | 
|  | 30 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 31 | //===----------------------------------------------------------------------===// | 
|  | 32 | // Preprocessed token printer | 
|  | 33 | //===----------------------------------------------------------------------===// | 
|  | 34 |  | 
|  | 35 | static llvm::cl::opt<bool> | 
|  | 36 | DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode")); | 
|  | 37 | static llvm::cl::opt<bool> | 
|  | 38 | EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode")); | 
|  | 39 | static llvm::cl::opt<bool> | 
|  | 40 | EnableMacroCommentOutput("CC", | 
|  | 41 | llvm::cl::desc("Enable comment output in -E mode, " | 
|  | 42 | "even from macro expansions")); | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 43 | static llvm::cl::opt<bool> | 
|  | 44 | DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of" | 
|  | 45 | " normal output")); | 
|  | 46 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 47 |  | 
|  | 48 | namespace { | 
|  | 49 | class PrintPPOutputPPCallbacks : public PPCallbacks { | 
|  | 50 | Preprocessor &PP; | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 51 | public: | 
|  | 52 | llvm::raw_ostream &OS; | 
|  | 53 | private: | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 54 | unsigned CurLine; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 55 | bool EmittedTokensOnThisLine; | 
| Chris Lattner | 9d72851 | 2008-10-27 01:19:25 +0000 | [diff] [blame] | 56 | SrcMgr::CharacteristicKind FileType; | 
| Chris Lattner | d8e3083 | 2007-07-24 06:57:14 +0000 | [diff] [blame] | 57 | llvm::SmallString<512> CurFilename; | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 58 | bool Initialized; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 59 | public: | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 60 | PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os) | 
|  | 61 | : PP(pp), OS(os) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 62 | CurLine = 0; | 
| Chris Lattner | d8e3083 | 2007-07-24 06:57:14 +0000 | [diff] [blame] | 63 | CurFilename += "<uninit>"; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 64 | EmittedTokensOnThisLine = false; | 
| Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 65 | FileType = SrcMgr::C_User; | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 66 | Initialized = false; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 67 | } | 
|  | 68 |  | 
|  | 69 | void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 70 | bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 71 |  | 
|  | 72 | virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, | 
| Chris Lattner | 9d72851 | 2008-10-27 01:19:25 +0000 | [diff] [blame] | 73 | SrcMgr::CharacteristicKind FileType); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 74 | virtual void Ident(SourceLocation Loc, const std::string &str); | 
| Chris Lattner | c7d945d | 2009-01-16 19:25:54 +0000 | [diff] [blame] | 75 | virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, | 
|  | 76 | const std::string &Str); | 
|  | 77 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 78 |  | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 79 | bool HandleFirstTokOnLine(Token &Tok); | 
|  | 80 | bool MoveToLine(SourceLocation Loc); | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 81 | bool AvoidConcat(const Token &PrevTok, const Token &Tok); | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 82 | void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 83 | }; | 
| Chris Lattner | 5db17c9 | 2008-04-08 04:16:20 +0000 | [diff] [blame] | 84 | }  // end anonymous namespace | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 85 |  | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 86 | void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, | 
|  | 87 | const char *Extra, | 
|  | 88 | unsigned ExtraLen) { | 
|  | 89 | if (EmittedTokensOnThisLine) { | 
|  | 90 | OS << '\n'; | 
|  | 91 | EmittedTokensOnThisLine = false; | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | OS << '#' << ' ' << LineNo << ' ' << '"'; | 
|  | 95 | OS.write(&CurFilename[0], CurFilename.size()); | 
|  | 96 | OS << '"'; | 
|  | 97 |  | 
|  | 98 | if (ExtraLen) | 
|  | 99 | OS.write(Extra, ExtraLen); | 
|  | 100 |  | 
| Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 101 | if (FileType == SrcMgr::C_System) | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 102 | OS.write(" 3", 2); | 
| Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 103 | else if (FileType == SrcMgr::C_ExternCSystem) | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 104 | OS.write(" 3 4", 4); | 
|  | 105 | OS << '\n'; | 
|  | 106 | } | 
|  | 107 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 108 | /// MoveToLine - Move the output to the source line specified by the location | 
|  | 109 | /// object.  We can do this by emitting some number of \n's, or be emitting a | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 110 | /// #line directive.  This returns false if already at the specified line, true | 
|  | 111 | /// if some newlines were emitted. | 
|  | 112 | bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { | 
| Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 113 | unsigned LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc); | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 114 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 115 | if (DisableLineMarkers) { | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 116 | if (LineNo == CurLine) return false; | 
|  | 117 |  | 
|  | 118 | CurLine = LineNo; | 
|  | 119 |  | 
|  | 120 | if (!EmittedTokensOnThisLine) | 
|  | 121 | return true; | 
|  | 122 |  | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 123 | OS << '\n'; | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 124 | EmittedTokensOnThisLine = false; | 
|  | 125 | return true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 126 | } | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 127 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 128 | // If this line is "close enough" to the original line, just print newlines, | 
|  | 129 | // otherwise print a #line directive. | 
| Daniel Dunbar | fd96684 | 2008-09-26 01:13:35 +0000 | [diff] [blame] | 130 | if (LineNo-CurLine <= 8) { | 
| Chris Lattner | 822f940 | 2007-07-23 05:14:05 +0000 | [diff] [blame] | 131 | if (LineNo-CurLine == 1) | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 132 | OS << '\n'; | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 133 | else if (LineNo == CurLine) | 
| Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 134 | return false;    // Spelling line moved, but instantiation line didn't. | 
| Chris Lattner | 822f940 | 2007-07-23 05:14:05 +0000 | [diff] [blame] | 135 | else { | 
|  | 136 | const char *NewLines = "\n\n\n\n\n\n\n\n"; | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 137 | OS.write(NewLines, LineNo-CurLine); | 
| Chris Lattner | 822f940 | 2007-07-23 05:14:05 +0000 | [diff] [blame] | 138 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 139 | } else { | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 140 | WriteLineInfo(LineNo, 0, 0); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 141 | } | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 142 |  | 
|  | 143 | CurLine = LineNo; | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 144 | return true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 145 | } | 
|  | 146 |  | 
|  | 147 |  | 
|  | 148 | /// FileChanged - Whenever the preprocessor enters or exits a #include file | 
|  | 149 | /// it invokes this handler.  Update our conception of the current source | 
|  | 150 | /// position. | 
|  | 151 | void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, | 
|  | 152 | FileChangeReason Reason, | 
| Chris Lattner | 9d72851 | 2008-10-27 01:19:25 +0000 | [diff] [blame] | 153 | SrcMgr::CharacteristicKind NewFileType) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 154 | // Unless we are exiting a #include, make sure to skip ahead to the line the | 
|  | 155 | // #include directive was at. | 
|  | 156 | SourceManager &SourceMgr = PP.getSourceManager(); | 
|  | 157 | if (Reason == PPCallbacks::EnterFile) { | 
| Chris Lattner | 71d8bfb | 2009-01-30 18:44:17 +0000 | [diff] [blame] | 158 | SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc(); | 
|  | 159 | if (IncludeLoc.isValid()) | 
|  | 160 | MoveToLine(IncludeLoc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 161 | } else if (Reason == PPCallbacks::SystemHeaderPragma) { | 
|  | 162 | MoveToLine(Loc); | 
|  | 163 |  | 
|  | 164 | // TODO GCC emits the # directive for this directive on the line AFTER the | 
|  | 165 | // directive and emits a bunch of spaces that aren't needed.  Emulate this | 
|  | 166 | // strange behavior. | 
|  | 167 | } | 
|  | 168 |  | 
| Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 169 | Loc = SourceMgr.getInstantiationLoc(Loc); | 
| Chris Lattner | 30fc933 | 2009-02-04 01:06:56 +0000 | [diff] [blame] | 170 | CurLine = SourceMgr.getInstantiationLineNumber(Loc); | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 171 |  | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 172 | if (DisableLineMarkers) return; | 
|  | 173 |  | 
| Chris Lattner | d8e3083 | 2007-07-24 06:57:14 +0000 | [diff] [blame] | 174 | CurFilename.clear(); | 
| Chris Lattner | b9c3f96 | 2009-01-27 07:57:44 +0000 | [diff] [blame] | 175 | CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename(); | 
| Chris Lattner | d8e3083 | 2007-07-24 06:57:14 +0000 | [diff] [blame] | 176 | Lexer::Stringify(CurFilename); | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 177 | FileType = NewFileType; | 
|  | 178 |  | 
|  | 179 | if (!Initialized) { | 
|  | 180 | WriteLineInfo(CurLine); | 
|  | 181 | Initialized = true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 182 | } | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 183 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 184 | switch (Reason) { | 
|  | 185 | case PPCallbacks::EnterFile: | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 186 | WriteLineInfo(CurLine, " 1", 2); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 187 | break; | 
|  | 188 | case PPCallbacks::ExitFile: | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 189 | WriteLineInfo(CurLine, " 2", 2); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 190 | break; | 
| Daniel Dunbar | 737bdb4 | 2008-09-05 03:22:57 +0000 | [diff] [blame] | 191 | case PPCallbacks::SystemHeaderPragma: | 
|  | 192 | case PPCallbacks::RenameFile: | 
|  | 193 | WriteLineInfo(CurLine); | 
|  | 194 | break; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 195 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 196 | } | 
|  | 197 |  | 
| Chris Lattner | c7d945d | 2009-01-16 19:25:54 +0000 | [diff] [blame] | 198 | /// Ident - Handle #ident directives when read by the preprocessor. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 199 | /// | 
|  | 200 | void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) { | 
|  | 201 | MoveToLine(Loc); | 
|  | 202 |  | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 203 | OS.write("#ident ", strlen("#ident ")); | 
|  | 204 | OS.write(&S[0], S.size()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 205 | EmittedTokensOnThisLine = true; | 
|  | 206 | } | 
|  | 207 |  | 
| Chris Lattner | c7d945d | 2009-01-16 19:25:54 +0000 | [diff] [blame] | 208 | void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, | 
|  | 209 | const IdentifierInfo *Kind, | 
|  | 210 | const std::string &Str) { | 
|  | 211 | MoveToLine(Loc); | 
|  | 212 | OS << "#pragma comment(" << Kind->getName(); | 
|  | 213 |  | 
|  | 214 | if (!Str.empty()) { | 
|  | 215 | OS << ", \""; | 
|  | 216 |  | 
|  | 217 | for (unsigned i = 0, e = Str.size(); i != e; ++i) { | 
|  | 218 | unsigned char Char = Str[i]; | 
| Chris Lattner | 52a3e9e | 2009-01-16 22:13:37 +0000 | [diff] [blame] | 219 | if (isprint(Char) && Char != '\\' && Char != '"') | 
| Chris Lattner | c7d945d | 2009-01-16 19:25:54 +0000 | [diff] [blame] | 220 | OS << (char)Char; | 
|  | 221 | else  // Output anything hard as an octal escape. | 
|  | 222 | OS << '\\' | 
|  | 223 | << (char)('0'+ ((Char >> 6) & 7)) | 
|  | 224 | << (char)('0'+ ((Char >> 3) & 7)) | 
|  | 225 | << (char)('0'+ ((Char >> 0) & 7)); | 
|  | 226 | } | 
|  | 227 | OS << '"'; | 
|  | 228 | } | 
|  | 229 |  | 
|  | 230 | OS << ')'; | 
|  | 231 | EmittedTokensOnThisLine = true; | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 235 | /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 236 | /// is called for the first token on each new line.  If this really is the start | 
|  | 237 | /// of a new logical line, handle it and return true, otherwise return false. | 
|  | 238 | /// This may not be the start of a logical line because the "start of line" | 
| Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 239 | /// marker is set for spelling lines, not instantiation ones. | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 240 | bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 241 | // Figure out what line we went to and insert the appropriate number of | 
|  | 242 | // newline characters. | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 243 | if (!MoveToLine(Tok.getLocation())) | 
|  | 244 | return false; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 245 |  | 
|  | 246 | // Print out space characters so that the first token on a line is | 
|  | 247 | // indented for easy reading. | 
| Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 248 | const SourceManager &SourceMgr = PP.getSourceManager(); | 
| Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 249 | unsigned ColNo = SourceMgr.getInstantiationColumnNumber(Tok.getLocation()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 250 |  | 
|  | 251 | // This hack prevents stuff like: | 
|  | 252 | // #define HASH # | 
|  | 253 | // HASH define foo bar | 
|  | 254 | // From having the # character end up at column 1, which makes it so it | 
|  | 255 | // is not handled as a #define next time through the preprocessor if in | 
|  | 256 | // -fpreprocessed mode. | 
| Chris Lattner | 057aaf6 | 2007-10-09 18:03:42 +0000 | [diff] [blame] | 257 | if (ColNo <= 1 && Tok.is(tok::hash)) | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 258 | OS << ' '; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 259 |  | 
|  | 260 | // Otherwise, indent the appropriate number of spaces. | 
|  | 261 | for (; ColNo > 1; --ColNo) | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 262 | OS << ' '; | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 263 |  | 
|  | 264 | return true; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 265 | } | 
|  | 266 |  | 
|  | 267 | namespace { | 
|  | 268 | struct UnknownPragmaHandler : public PragmaHandler { | 
|  | 269 | const char *Prefix; | 
|  | 270 | PrintPPOutputPPCallbacks *Callbacks; | 
|  | 271 |  | 
|  | 272 | UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks) | 
|  | 273 | : PragmaHandler(0), Prefix(prefix), Callbacks(callbacks) {} | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 274 | virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 275 | // Figure out what line we went to and insert the appropriate number of | 
|  | 276 | // newline characters. | 
|  | 277 | Callbacks->MoveToLine(PragmaTok.getLocation()); | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 278 | Callbacks->OS.write(Prefix, strlen(Prefix)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 279 |  | 
|  | 280 | // Read and print all of the pragma tokens. | 
| Chris Lattner | 057aaf6 | 2007-10-09 18:03:42 +0000 | [diff] [blame] | 281 | while (PragmaTok.isNot(tok::eom)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 282 | if (PragmaTok.hasLeadingSpace()) | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 283 | Callbacks->OS << ' '; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 284 | std::string TokSpell = PP.getSpelling(PragmaTok); | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 285 | Callbacks->OS.write(&TokSpell[0], TokSpell.size()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 286 | PP.LexUnexpandedToken(PragmaTok); | 
|  | 287 | } | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 288 | Callbacks->OS << '\n'; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 289 | } | 
|  | 290 | }; | 
|  | 291 | } // end anonymous namespace | 
|  | 292 |  | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 293 |  | 
|  | 294 | enum AvoidConcatInfo { | 
|  | 295 | /// By default, a token never needs to avoid concatenation.  Most tokens (e.g. | 
|  | 296 | /// ',', ')', etc) don't cause a problem when concatenated. | 
|  | 297 | aci_never_avoid_concat = 0, | 
|  | 298 |  | 
|  | 299 | /// aci_custom_firstchar - AvoidConcat contains custom code to handle this | 
|  | 300 | /// token's requirements, and it needs to know the first character of the | 
|  | 301 | /// token. | 
|  | 302 | aci_custom_firstchar = 1, | 
|  | 303 |  | 
|  | 304 | /// aci_custom - AvoidConcat contains custom code to handle this token's | 
|  | 305 | /// requirements, but it doesn't need to know the first character of the | 
|  | 306 | /// token. | 
|  | 307 | aci_custom = 2, | 
|  | 308 |  | 
|  | 309 | /// aci_avoid_equal - Many tokens cannot be safely followed by an '=' | 
|  | 310 | /// character.  For example, "<<" turns into "<<=" when followed by an =. | 
|  | 311 | aci_avoid_equal = 4 | 
|  | 312 | }; | 
|  | 313 |  | 
|  | 314 | /// This array contains information for each token on what action to take when | 
|  | 315 | /// avoiding concatenation of tokens in the AvoidConcat method. | 
|  | 316 | static char TokenInfo[tok::NUM_TOKENS]; | 
|  | 317 |  | 
|  | 318 | /// InitAvoidConcatTokenInfo - Tokens that must avoid concatenation should be | 
|  | 319 | /// marked by this function. | 
|  | 320 | static void InitAvoidConcatTokenInfo() { | 
|  | 321 | // These tokens have custom code in AvoidConcat. | 
|  | 322 | TokenInfo[tok::identifier      ] |= aci_custom; | 
|  | 323 | TokenInfo[tok::numeric_constant] |= aci_custom_firstchar; | 
|  | 324 | TokenInfo[tok::period          ] |= aci_custom_firstchar; | 
|  | 325 | TokenInfo[tok::amp             ] |= aci_custom_firstchar; | 
|  | 326 | TokenInfo[tok::plus            ] |= aci_custom_firstchar; | 
|  | 327 | TokenInfo[tok::minus           ] |= aci_custom_firstchar; | 
|  | 328 | TokenInfo[tok::slash           ] |= aci_custom_firstchar; | 
|  | 329 | TokenInfo[tok::less            ] |= aci_custom_firstchar; | 
|  | 330 | TokenInfo[tok::greater         ] |= aci_custom_firstchar; | 
|  | 331 | TokenInfo[tok::pipe            ] |= aci_custom_firstchar; | 
|  | 332 | TokenInfo[tok::percent         ] |= aci_custom_firstchar; | 
|  | 333 | TokenInfo[tok::colon           ] |= aci_custom_firstchar; | 
|  | 334 | TokenInfo[tok::hash            ] |= aci_custom_firstchar; | 
|  | 335 | TokenInfo[tok::arrow           ] |= aci_custom_firstchar; | 
|  | 336 |  | 
|  | 337 | // These tokens change behavior if followed by an '='. | 
|  | 338 | TokenInfo[tok::amp         ] |= aci_avoid_equal;           // &= | 
|  | 339 | TokenInfo[tok::plus        ] |= aci_avoid_equal;           // += | 
|  | 340 | TokenInfo[tok::minus       ] |= aci_avoid_equal;           // -= | 
|  | 341 | TokenInfo[tok::slash       ] |= aci_avoid_equal;           // /= | 
|  | 342 | TokenInfo[tok::less        ] |= aci_avoid_equal;           // <= | 
|  | 343 | TokenInfo[tok::greater     ] |= aci_avoid_equal;           // >= | 
|  | 344 | TokenInfo[tok::pipe        ] |= aci_avoid_equal;           // |= | 
|  | 345 | TokenInfo[tok::percent     ] |= aci_avoid_equal;           // %= | 
|  | 346 | TokenInfo[tok::star        ] |= aci_avoid_equal;           // *= | 
|  | 347 | TokenInfo[tok::exclaim     ] |= aci_avoid_equal;           // != | 
|  | 348 | TokenInfo[tok::lessless    ] |= aci_avoid_equal;           // <<= | 
|  | 349 | TokenInfo[tok::greaterequal] |= aci_avoid_equal;           // >>= | 
|  | 350 | TokenInfo[tok::caret       ] |= aci_avoid_equal;           // ^= | 
|  | 351 | TokenInfo[tok::equal       ] |= aci_avoid_equal;           // == | 
|  | 352 | } | 
|  | 353 |  | 
| Chris Lattner | b1a17ae | 2008-01-15 05:22:14 +0000 | [diff] [blame] | 354 | /// StartsWithL - Return true if the spelling of this token starts with 'L'. | 
| Chris Lattner | fdc0d3c | 2008-01-15 05:14:19 +0000 | [diff] [blame] | 355 | static bool StartsWithL(const Token &Tok, Preprocessor &PP) { | 
| Chris Lattner | fdc0d3c | 2008-01-15 05:14:19 +0000 | [diff] [blame] | 356 | if (!Tok.needsCleaning()) { | 
|  | 357 | SourceManager &SrcMgr = PP.getSourceManager(); | 
| Chris Lattner | df7c17a | 2009-01-16 07:00:02 +0000 | [diff] [blame] | 358 | return *SrcMgr.getCharacterData(SrcMgr.getSpellingLoc(Tok.getLocation())) | 
| Chris Lattner | fdc0d3c | 2008-01-15 05:14:19 +0000 | [diff] [blame] | 359 | == 'L'; | 
|  | 360 | } | 
|  | 361 |  | 
|  | 362 | if (Tok.getLength() < 256) { | 
| Chris Lattner | b1a17ae | 2008-01-15 05:22:14 +0000 | [diff] [blame] | 363 | char Buffer[256]; | 
| Chris Lattner | fdc0d3c | 2008-01-15 05:14:19 +0000 | [diff] [blame] | 364 | const char *TokPtr = Buffer; | 
|  | 365 | PP.getSpelling(Tok, TokPtr); | 
|  | 366 | return TokPtr[0] == 'L'; | 
|  | 367 | } | 
|  | 368 |  | 
|  | 369 | return PP.getSpelling(Tok)[0] == 'L'; | 
|  | 370 | } | 
|  | 371 |  | 
| Chris Lattner | b1a17ae | 2008-01-15 05:22:14 +0000 | [diff] [blame] | 372 | /// IsIdentifierL - Return true if the spelling of this token is literally 'L'. | 
|  | 373 | static bool IsIdentifierL(const Token &Tok, Preprocessor &PP) { | 
|  | 374 | if (!Tok.needsCleaning()) { | 
|  | 375 | if (Tok.getLength() != 1) | 
|  | 376 | return false; | 
|  | 377 | SourceManager &SrcMgr = PP.getSourceManager(); | 
| Chris Lattner | df7c17a | 2009-01-16 07:00:02 +0000 | [diff] [blame] | 378 | return *SrcMgr.getCharacterData(SrcMgr.getSpellingLoc(Tok.getLocation())) | 
| Chris Lattner | b1a17ae | 2008-01-15 05:22:14 +0000 | [diff] [blame] | 379 | == 'L'; | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | if (Tok.getLength() < 256) { | 
|  | 383 | char Buffer[256]; | 
|  | 384 | const char *TokPtr = Buffer; | 
|  | 385 | if (PP.getSpelling(Tok, TokPtr) != 1) | 
|  | 386 | return false; | 
|  | 387 | return TokPtr[0] == 'L'; | 
|  | 388 | } | 
|  | 389 |  | 
|  | 390 | return PP.getSpelling(Tok) == "L"; | 
|  | 391 | } | 
|  | 392 |  | 
|  | 393 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 394 | /// AvoidConcat - If printing PrevTok immediately followed by Tok would cause | 
|  | 395 | /// the two individual tokens to be lexed as a single token, return true (which | 
|  | 396 | /// causes a space to be printed between them).  This allows the output of -E | 
|  | 397 | /// mode to be lexed to the same token stream as lexing the input directly | 
|  | 398 | /// would. | 
|  | 399 | /// | 
|  | 400 | /// This code must conservatively return true if it doesn't want to be 100% | 
|  | 401 | /// accurate.  This will cause the output to include extra space characters, but | 
|  | 402 | /// the resulting output won't have incorrect concatenations going on.  Examples | 
|  | 403 | /// include "..", which we print with a space between, because we don't want to | 
|  | 404 | /// track enough to tell "x.." from "...". | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 405 | bool PrintPPOutputPPCallbacks::AvoidConcat(const Token &PrevTok, | 
|  | 406 | const Token &Tok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 407 | char Buffer[256]; | 
|  | 408 |  | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 409 | tok::TokenKind PrevKind = PrevTok.getKind(); | 
|  | 410 | if (PrevTok.getIdentifierInfo())  // Language keyword or named operator. | 
|  | 411 | PrevKind = tok::identifier; | 
|  | 412 |  | 
|  | 413 | // Look up information on when we should avoid concatenation with prevtok. | 
|  | 414 | unsigned ConcatInfo = TokenInfo[PrevKind]; | 
|  | 415 |  | 
|  | 416 | // If prevtok never causes a problem for anything after it, return quickly. | 
|  | 417 | if (ConcatInfo == 0) return false; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 418 |  | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 419 | if (ConcatInfo & aci_avoid_equal) { | 
|  | 420 | // If the next token is '=' or '==', avoid concatenation. | 
| Chris Lattner | 057aaf6 | 2007-10-09 18:03:42 +0000 | [diff] [blame] | 421 | if (Tok.is(tok::equal) || Tok.is(tok::equalequal)) | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 422 | return true; | 
| Chris Lattner | b638a30 | 2007-07-23 23:21:34 +0000 | [diff] [blame] | 423 | ConcatInfo &= ~aci_avoid_equal; | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 424 | } | 
|  | 425 |  | 
|  | 426 | if (ConcatInfo == 0) return false; | 
|  | 427 |  | 
|  | 428 |  | 
|  | 429 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 430 | // Basic algorithm: we look at the first character of the second token, and | 
|  | 431 | // determine whether it, if appended to the first token, would form (or would | 
|  | 432 | // contribute) to a larger token if concatenated. | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 433 | char FirstChar = 0; | 
|  | 434 | if (ConcatInfo & aci_custom) { | 
|  | 435 | // If the token does not need to know the first character, don't get it. | 
|  | 436 | } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 437 | // Avoid spelling identifiers, the most common form of token. | 
|  | 438 | FirstChar = II->getName()[0]; | 
| Chris Lattner | b19f5e8 | 2007-07-23 05:18:42 +0000 | [diff] [blame] | 439 | } else if (!Tok.needsCleaning()) { | 
| Chris Lattner | 33116d6 | 2009-01-26 19:33:54 +0000 | [diff] [blame] | 440 | if (Tok.isLiteral() && Tok.getLiteralData()) { | 
|  | 441 | FirstChar = *Tok.getLiteralData(); | 
|  | 442 | } else { | 
|  | 443 | SourceManager &SrcMgr = PP.getSourceManager(); | 
|  | 444 | FirstChar = | 
|  | 445 | *SrcMgr.getCharacterData(SrcMgr.getSpellingLoc(Tok.getLocation())); | 
|  | 446 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 447 | } else if (Tok.getLength() < 256) { | 
|  | 448 | const char *TokPtr = Buffer; | 
|  | 449 | PP.getSpelling(Tok, TokPtr); | 
|  | 450 | FirstChar = TokPtr[0]; | 
|  | 451 | } else { | 
|  | 452 | FirstChar = PP.getSpelling(Tok)[0]; | 
|  | 453 | } | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 454 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 455 | switch (PrevKind) { | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 456 | default: assert(0 && "InitAvoidConcatTokenInfo built wrong"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 457 | case tok::identifier:   // id+id or id+number or id+L"foo". | 
| Chris Lattner | 057aaf6 | 2007-10-09 18:03:42 +0000 | [diff] [blame] | 458 | if (Tok.is(tok::numeric_constant) || Tok.getIdentifierInfo() || | 
|  | 459 | Tok.is(tok::wide_string_literal) /* || | 
|  | 460 | Tok.is(tok::wide_char_literal)*/) | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 461 | return true; | 
| Chris Lattner | fdc0d3c | 2008-01-15 05:14:19 +0000 | [diff] [blame] | 462 |  | 
|  | 463 | // If this isn't identifier + string, we're done. | 
|  | 464 | if (Tok.isNot(tok::char_constant) && Tok.isNot(tok::string_literal)) | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 465 | return false; | 
|  | 466 |  | 
|  | 467 | // FIXME: need a wide_char_constant! | 
| Chris Lattner | fdc0d3c | 2008-01-15 05:14:19 +0000 | [diff] [blame] | 468 |  | 
|  | 469 | // If the string was a wide string L"foo" or wide char L'f', it would concat | 
|  | 470 | // with the previous identifier into fooL"bar".  Avoid this. | 
|  | 471 | if (StartsWithL(Tok, PP)) | 
|  | 472 | return true; | 
|  | 473 |  | 
| Chris Lattner | b1a17ae | 2008-01-15 05:22:14 +0000 | [diff] [blame] | 474 | // Otherwise, this is a narrow character or string.  If the *identifier* is | 
|  | 475 | // a literal 'L', avoid pasting L "foo" -> L"foo". | 
|  | 476 | return IsIdentifierL(PrevTok, PP); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 477 | case tok::numeric_constant: | 
| Chris Lattner | 057aaf6 | 2007-10-09 18:03:42 +0000 | [diff] [blame] | 478 | return isalnum(FirstChar) || Tok.is(tok::numeric_constant) || | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 479 | FirstChar == '+' || FirstChar == '-' || FirstChar == '.'; | 
|  | 480 | case tok::period:          // ..., .*, .1234 | 
| Chris Lattner | d7a7c00 | 2009-01-11 19:48:19 +0000 | [diff] [blame] | 481 | return FirstChar == '.' || isdigit(FirstChar) || | 
|  | 482 | (FirstChar == '*' && PP.getLangOptions().CPlusPlus); | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 483 | case tok::amp:             // && | 
|  | 484 | return FirstChar == '&'; | 
|  | 485 | case tok::plus:            // ++ | 
|  | 486 | return FirstChar == '+'; | 
|  | 487 | case tok::minus:           // --, ->, ->* | 
|  | 488 | return FirstChar == '-' || FirstChar == '>'; | 
|  | 489 | case tok::slash:           //, /*, // | 
|  | 490 | return FirstChar == '*' || FirstChar == '/'; | 
|  | 491 | case tok::less:            // <<, <<=, <:, <% | 
|  | 492 | return FirstChar == '<' || FirstChar == ':' || FirstChar == '%'; | 
|  | 493 | case tok::greater:         // >>, >>= | 
|  | 494 | return FirstChar == '>'; | 
|  | 495 | case tok::pipe:            // || | 
|  | 496 | return FirstChar == '|'; | 
|  | 497 | case tok::percent:         // %>, %: | 
| Chris Lattner | d7a7c00 | 2009-01-11 19:48:19 +0000 | [diff] [blame] | 498 | return (FirstChar == '>' || FirstChar == ':') && | 
|  | 499 | PP.getLangOptions().Digraphs; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 500 | case tok::colon:           // ::, :> | 
| Chris Lattner | d7a7c00 | 2009-01-11 19:48:19 +0000 | [diff] [blame] | 501 | return (FirstChar == ':' && PP.getLangOptions().CPlusPlus) || | 
|  | 502 | (FirstChar == '>' && PP.getLangOptions().Digraphs); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 503 | case tok::hash:            // ##, #@, %:%: | 
|  | 504 | return FirstChar == '#' || FirstChar == '@' || FirstChar == '%'; | 
|  | 505 | case tok::arrow:           // ->* | 
|  | 506 | return FirstChar == '*'; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 507 | } | 
|  | 508 | } | 
|  | 509 |  | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 510 | static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, | 
|  | 511 | PrintPPOutputPPCallbacks *Callbacks, | 
|  | 512 | llvm::raw_ostream &OS) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 513 | char Buffer[256]; | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 514 | Token PrevTok; | 
| Chris Lattner | 6f688e1 | 2007-10-10 20:45:16 +0000 | [diff] [blame] | 515 | while (1) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 516 |  | 
|  | 517 | // If this token is at the start of a line, emit newlines if needed. | 
| Chris Lattner | 5f18032 | 2007-12-09 21:11:08 +0000 | [diff] [blame] | 518 | if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { | 
|  | 519 | // done. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 520 | } else if (Tok.hasLeadingSpace() || | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 521 | // If we haven't emitted a token on this line yet, PrevTok isn't | 
|  | 522 | // useful to look at and no concatenation could happen anyway. | 
| Chris Lattner | b638a30 | 2007-07-23 23:21:34 +0000 | [diff] [blame] | 523 | (Callbacks->hasEmittedTokensOnThisLine() && | 
| Chris Lattner | f0f2b29 | 2007-07-23 06:09:34 +0000 | [diff] [blame] | 524 | // Don't print "-" next to "-", it would form "--". | 
|  | 525 | Callbacks->AvoidConcat(PrevTok, Tok))) { | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 526 | OS << ' '; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 527 | } | 
|  | 528 |  | 
| Chris Lattner | 2933f41 | 2007-07-23 06:14:36 +0000 | [diff] [blame] | 529 | if (IdentifierInfo *II = Tok.getIdentifierInfo()) { | 
| Chris Lattner | 33116d6 | 2009-01-26 19:33:54 +0000 | [diff] [blame] | 530 | OS.write(II->getName(), II->getLength()); | 
|  | 531 | } else if (Tok.isLiteral() && !Tok.needsCleaning() && | 
|  | 532 | Tok.getLiteralData()) { | 
|  | 533 | OS.write(Tok.getLiteralData(), Tok.getLength()); | 
| Chris Lattner | 2933f41 | 2007-07-23 06:14:36 +0000 | [diff] [blame] | 534 | } else if (Tok.getLength() < 256) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 535 | const char *TokPtr = Buffer; | 
|  | 536 | unsigned Len = PP.getSpelling(Tok, TokPtr); | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 537 | OS.write(TokPtr, Len); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 538 | } else { | 
|  | 539 | std::string S = PP.getSpelling(Tok); | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 540 | OS.write(&S[0], S.size()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 541 | } | 
|  | 542 | Callbacks->SetEmittedTokensOnThisLine(); | 
| Chris Lattner | 6f688e1 | 2007-10-10 20:45:16 +0000 | [diff] [blame] | 543 |  | 
|  | 544 | if (Tok.is(tok::eof)) break; | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 545 |  | 
| Chris Lattner | 6f688e1 | 2007-10-10 20:45:16 +0000 | [diff] [blame] | 546 | PrevTok = Tok; | 
|  | 547 | PP.Lex(Tok); | 
|  | 548 | } | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 549 | } | 
|  | 550 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 551 | /// PrintMacroDefinition - Print a macro definition in a form that will be | 
|  | 552 | /// properly accepted back as a definition. | 
|  | 553 | static void PrintMacroDefinition(IdentifierInfo &II, const MacroInfo &MI, | 
|  | 554 | Preprocessor &PP, llvm::raw_ostream &OS) { | 
|  | 555 | // Ignore computed macros like __LINE__ and friends. | 
|  | 556 | if (MI.isBuiltinMacro()) return; | 
|  | 557 | OS << "#define " << II.getName(); | 
|  | 558 |  | 
|  | 559 | if (MI.isFunctionLike()) { | 
|  | 560 | OS << '('; | 
|  | 561 | if (MI.arg_empty()) | 
|  | 562 | ; | 
|  | 563 | else if (MI.getNumArgs() == 1) | 
|  | 564 | OS << (*MI.arg_begin())->getName(); | 
|  | 565 | else { | 
|  | 566 | MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end(); | 
|  | 567 | OS << (*AI++)->getName(); | 
|  | 568 | while (AI != E) | 
|  | 569 | OS << ',' << (*AI++)->getName(); | 
|  | 570 | } | 
|  | 571 |  | 
|  | 572 | if (MI.isVariadic()) { | 
|  | 573 | if (!MI.arg_empty()) | 
|  | 574 | OS << ','; | 
|  | 575 | OS << "..."; | 
|  | 576 | } | 
|  | 577 | OS << ')'; | 
|  | 578 | } | 
|  | 579 |  | 
|  | 580 | // GCC always emits a space, even if the macro body is empty.  However, do not | 
|  | 581 | // want to emit two spaces if the first token has a leading space. | 
|  | 582 | if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()) | 
|  | 583 | OS << ' '; | 
|  | 584 |  | 
| Chris Lattner | eb213da | 2009-02-10 22:16:03 +0000 | [diff] [blame^] | 585 | llvm::SmallVector<char, 128> SpellingBuffer; | 
|  | 586 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 587 | for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end(); | 
|  | 588 | I != E; ++I) { | 
|  | 589 | if (I->hasLeadingSpace()) | 
|  | 590 | OS << ' '; | 
| Chris Lattner | eb213da | 2009-02-10 22:16:03 +0000 | [diff] [blame^] | 591 |  | 
|  | 592 | // Make sure we have enough space in the spelling buffer. | 
|  | 593 | if (I->getLength() < SpellingBuffer.size()) | 
|  | 594 | SpellingBuffer.resize(I->getLength()); | 
|  | 595 | const char *Buffer = &SpellingBuffer[0]; | 
|  | 596 | unsigned SpellingLen = PP.getSpelling(*I, Buffer); | 
|  | 597 | OS.write(Buffer, SpellingLen); | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 598 | } | 
|  | 599 | OS << "\n"; | 
|  | 600 | } | 
|  | 601 |  | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 602 |  | 
|  | 603 | /// DoPrintPreprocessedInput - This implements -E mode. | 
|  | 604 | /// | 
|  | 605 | void clang::DoPrintPreprocessedInput(Preprocessor &PP, | 
|  | 606 | const std::string &OutFile) { | 
|  | 607 | // Inform the preprocessor whether we want it to retain comments or not, due | 
|  | 608 | // to -C or -CC. | 
|  | 609 | PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput); | 
|  | 610 | InitAvoidConcatTokenInfo(); | 
|  | 611 |  | 
|  | 612 |  | 
|  | 613 | // Open the output buffer. | 
|  | 614 | std::string Err; | 
|  | 615 | llvm::raw_fd_ostream OS(OutFile.empty() ? "-" : OutFile.c_str(), false, Err); | 
|  | 616 | if (!Err.empty()) { | 
|  | 617 | fprintf(stderr, "%s\n", Err.c_str()); | 
|  | 618 | exit(1); | 
|  | 619 | } | 
|  | 620 |  | 
|  | 621 | OS.SetBufferSize(64*1024); | 
|  | 622 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 623 | if (DumpMacros) { | 
|  | 624 | // -dM mode just scans and ignores all tokens in the files, then dumps out | 
|  | 625 | // the macro table at the end. | 
|  | 626 | PP.EnterMainSourceFile(); | 
|  | 627 |  | 
|  | 628 | Token Tok; | 
|  | 629 | do PP.Lex(Tok); | 
|  | 630 | while (Tok.isNot(tok::eof)); | 
|  | 631 |  | 
|  | 632 | for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); | 
|  | 633 | I != E; ++I) | 
|  | 634 | PrintMacroDefinition(*I->first, *I->second, PP, OS); | 
|  | 635 |  | 
|  | 636 | } else { | 
|  | 637 | PrintPPOutputPPCallbacks *Callbacks; | 
|  | 638 | Callbacks = new PrintPPOutputPPCallbacks(PP, OS); | 
|  | 639 | PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks)); | 
|  | 640 | PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC", | 
|  | 641 | Callbacks)); | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 642 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 643 | PP.setPPCallbacks(Callbacks); | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 644 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 645 | // After we have configured the preprocessor, enter the main file. | 
|  | 646 | PP.EnterMainSourceFile(); | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 647 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 648 | // Consume all of the tokens that come from the predefines buffer.  Those | 
|  | 649 | // should not be emitted into the output and are guaranteed to be at the | 
|  | 650 | // start. | 
|  | 651 | const SourceManager &SourceMgr = PP.getSourceManager(); | 
|  | 652 | Token Tok; | 
|  | 653 | do PP.Lex(Tok); | 
|  | 654 | while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() && | 
|  | 655 | !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(), | 
|  | 656 | "<predefines>")); | 
| Chris Lattner | 59076ab | 2009-02-06 05:56:11 +0000 | [diff] [blame] | 657 |  | 
| Chris Lattner | f73903a | 2009-02-06 06:45:26 +0000 | [diff] [blame] | 658 | // Read all the preprocessed tokens, printing them out to the stream. | 
|  | 659 | PrintPreprocessedTokens(PP, Tok, Callbacks, OS); | 
|  | 660 | OS << '\n'; | 
|  | 661 | } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 662 |  | 
| Chris Lattner | 76b3a72 | 2008-08-17 07:07:01 +0000 | [diff] [blame] | 663 | // Flush the ostream. | 
|  | 664 | OS.flush(); | 
| Chris Lattner | e96de3e | 2008-08-17 03:12:02 +0000 | [diff] [blame] | 665 |  | 
|  | 666 | // If an error occurred, remove the output file. | 
|  | 667 | if (PP.getDiagnostics().hasErrorOccurred() && !OutFile.empty()) | 
|  | 668 | llvm::sys::Path(OutFile).eraseFromDisk(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 669 | } | 
|  | 670 |  |