1 //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===//
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 // 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/Frontend/Utils.h"
16 #include "clang/Lex/MacroInfo.h"
17 #include "clang/Lex/PPCallbacks.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "clang/Lex/Pragma.h"
20 #include "clang/Lex/TokenConcatenation.h"
21 #include "clang/Basic/SourceManager.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/Config/config.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <cstdio>
28 using namespace clang;
29 
30 /// PrintMacroDefinition - Print a macro definition in a form that will be
31 /// properly accepted back as a definition.
32 static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
33                                  Preprocessor &PP, llvm::raw_ostream &OS) {
34   OS << "#define " << II.getName();
35 
36   if (MI.isFunctionLike()) {
37     OS << '(';
38     if (MI.arg_empty())
39       ;
40     else if (MI.getNumArgs() == 1)
41       OS << (*MI.arg_begin())->getName();
42     else {
43       MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
44       OS << (*AI++)->getName();
45       while (AI != E)
46         OS << ',' << (*AI++)->getName();
47     }
48 
49     if (MI.isVariadic()) {
50       if (!MI.arg_empty())
51         OS << ',';
52       OS << "...";
53     }
54     OS << ')';
55   }
56 
57   // GCC always emits a space, even if the macro body is empty.  However, do not
58   // want to emit two spaces if the first token has a leading space.
59   if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
60     OS << ' ';
61 
62   llvm::SmallVector<char, 128> SpellingBuffer;
63   for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
64        I != E; ++I) {
65     if (I->hasLeadingSpace())
66       OS << ' ';
67 
68     // Make sure we have enough space in the spelling buffer.
69     if (I->getLength() < SpellingBuffer.size())
70       SpellingBuffer.resize(I->getLength());
71     const char *Buffer = SpellingBuffer.data();
72     unsigned SpellingLen = PP.getSpelling(*I, Buffer);
73     OS.write(Buffer, SpellingLen);
74   }
75 }
76 
77 //===----------------------------------------------------------------------===//
78 // Preprocessed token printer
79 //===----------------------------------------------------------------------===//
80 
81 namespace {
82 class PrintPPOutputPPCallbacks : public PPCallbacks {
83   Preprocessor &PP;
84   TokenConcatenation ConcatInfo;
85 public:
86   llvm::raw_ostream &OS;
87 private:
88   unsigned CurLine;
89   bool EmittedTokensOnThisLine;
90   bool EmittedMacroOnThisLine;
91   SrcMgr::CharacteristicKind FileType;
92   llvm::SmallString<512> CurFilename;
93   bool Initialized;
94   bool DisableLineMarkers;
95   bool DumpDefines;
96 public:
97   PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
98                            bool lineMarkers, bool defines)
99      : PP(pp), ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
100        DumpDefines(defines) {
101     CurLine = 0;
102     CurFilename += "<uninit>";
103     EmittedTokensOnThisLine = false;
104     EmittedMacroOnThisLine = false;
105     FileType = SrcMgr::C_User;
106     Initialized = false;
107   }
108 
109   void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
110   bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
111 
112   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
113                            SrcMgr::CharacteristicKind FileType);
114   virtual void Ident(SourceLocation Loc, const std::string &str);
115   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
116                              const std::string &Str);
117 
118 
119   bool HandleFirstTokOnLine(Token &Tok);
120   bool MoveToLine(SourceLocation Loc);
121   bool AvoidConcat(const Token &PrevTok, const Token &Tok) {
122     return ConcatInfo.AvoidConcat(PrevTok, Tok);
123   }
124   void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
125 
126   /// MacroDefined - This hook is called whenever a macro definition is seen.
127   void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
128 
129 };
130 }  // end anonymous namespace
131 
132 void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
133                                              const char *Extra,
134                                              unsigned ExtraLen) {
135   if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
136     OS << '\n';
137     EmittedTokensOnThisLine = false;
138     EmittedMacroOnThisLine = false;
139   }
140 
141   OS << '#' << ' ' << LineNo << ' ' << '"';
142   OS.write(&CurFilename[0], CurFilename.size());
143   OS << '"';
144 
145   if (ExtraLen)
146     OS.write(Extra, ExtraLen);
147 
148   if (FileType == SrcMgr::C_System)
149     OS.write(" 3", 2);
150   else if (FileType == SrcMgr::C_ExternCSystem)
151     OS.write(" 3 4", 4);
152   OS << '\n';
153 }
154 
155 /// MoveToLine - Move the output to the source line specified by the location
156 /// object.  We can do this by emitting some number of \n's, or be emitting a
157 /// #line directive.  This returns false if already at the specified line, true
158 /// if some newlines were emitted.
159 bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) {
160   unsigned LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc);
161 
162   if (DisableLineMarkers) {
163     if (LineNo == CurLine) return false;
164 
165     CurLine = LineNo;
166 
167     if (!EmittedTokensOnThisLine && !EmittedMacroOnThisLine)
168       return true;
169 
170     OS << '\n';
171     EmittedTokensOnThisLine = false;
172     EmittedMacroOnThisLine = false;
173     return true;
174   }
175 
176   // If this line is "close enough" to the original line, just print newlines,
177   // otherwise print a #line directive.
178   if (LineNo-CurLine <= 8) {
179     if (LineNo-CurLine == 1)
180       OS << '\n';
181     else if (LineNo == CurLine)
182       return false;    // Spelling line moved, but instantiation line didn't.
183     else {
184       const char *NewLines = "\n\n\n\n\n\n\n\n";
185       OS.write(NewLines, LineNo-CurLine);
186     }
187   } else {
188     WriteLineInfo(LineNo, 0, 0);
189   }
190 
191   CurLine = LineNo;
192   return true;
193 }
194 
195 
196 /// FileChanged - Whenever the preprocessor enters or exits a #include file
197 /// it invokes this handler.  Update our conception of the current source
198 /// position.
199 void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
200                                            FileChangeReason Reason,
201                                        SrcMgr::CharacteristicKind NewFileType) {
202   // Unless we are exiting a #include, make sure to skip ahead to the line the
203   // #include directive was at.
204   SourceManager &SourceMgr = PP.getSourceManager();
205   if (Reason == PPCallbacks::EnterFile) {
206     SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc();
207     if (IncludeLoc.isValid())
208       MoveToLine(IncludeLoc);
209   } else if (Reason == PPCallbacks::SystemHeaderPragma) {
210     MoveToLine(Loc);
211 
212     // TODO GCC emits the # directive for this directive on the line AFTER the
213     // directive and emits a bunch of spaces that aren't needed.  Emulate this
214     // strange behavior.
215   }
216 
217   Loc = SourceMgr.getInstantiationLoc(Loc);
218   // FIXME: Should use presumed line #!
219   CurLine = SourceMgr.getInstantiationLineNumber(Loc);
220 
221   if (DisableLineMarkers) return;
222 
223   CurFilename.clear();
224   CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename();
225   Lexer::Stringify(CurFilename);
226   FileType = NewFileType;
227 
228   if (!Initialized) {
229     WriteLineInfo(CurLine);
230     Initialized = true;
231   }
232 
233   switch (Reason) {
234   case PPCallbacks::EnterFile:
235     WriteLineInfo(CurLine, " 1", 2);
236     break;
237   case PPCallbacks::ExitFile:
238     WriteLineInfo(CurLine, " 2", 2);
239     break;
240   case PPCallbacks::SystemHeaderPragma:
241   case PPCallbacks::RenameFile:
242     WriteLineInfo(CurLine);
243     break;
244   }
245 }
246 
247 /// Ident - Handle #ident directives when read by the preprocessor.
248 ///
249 void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
250   MoveToLine(Loc);
251 
252   OS.write("#ident ", strlen("#ident "));
253   OS.write(&S[0], S.size());
254   EmittedTokensOnThisLine = true;
255 }
256 
257 /// MacroDefined - This hook is called whenever a macro definition is seen.
258 void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II,
259                                             const MacroInfo *MI) {
260   // Only print out macro definitions in -dD mode.
261   if (!DumpDefines ||
262       // Ignore __FILE__ etc.
263       MI->isBuiltinMacro()) return;
264 
265   MoveToLine(MI->getDefinitionLoc());
266   PrintMacroDefinition(*II, *MI, PP, OS);
267   EmittedMacroOnThisLine = true;
268 }
269 
270 
271 void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
272                                              const IdentifierInfo *Kind,
273                                              const std::string &Str) {
274   MoveToLine(Loc);
275   OS << "#pragma comment(" << Kind->getName();
276 
277   if (!Str.empty()) {
278     OS << ", \"";
279 
280     for (unsigned i = 0, e = Str.size(); i != e; ++i) {
281       unsigned char Char = Str[i];
282       if (isprint(Char) && Char != '\\' && Char != '"')
283         OS << (char)Char;
284       else  // Output anything hard as an octal escape.
285         OS << '\\'
286            << (char)('0'+ ((Char >> 6) & 7))
287            << (char)('0'+ ((Char >> 3) & 7))
288            << (char)('0'+ ((Char >> 0) & 7));
289     }
290     OS << '"';
291   }
292 
293   OS << ')';
294   EmittedTokensOnThisLine = true;
295 }
296 
297 
298 /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
299 /// is called for the first token on each new line.  If this really is the start
300 /// of a new logical line, handle it and return true, otherwise return false.
301 /// This may not be the start of a logical line because the "start of line"
302 /// marker is set for spelling lines, not instantiation ones.
303 bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
304   // Figure out what line we went to and insert the appropriate number of
305   // newline characters.
306   if (!MoveToLine(Tok.getLocation()))
307     return false;
308 
309   // Print out space characters so that the first token on a line is
310   // indented for easy reading.
311   const SourceManager &SourceMgr = PP.getSourceManager();
312   unsigned ColNo = SourceMgr.getInstantiationColumnNumber(Tok.getLocation());
313 
314   // This hack prevents stuff like:
315   // #define HASH #
316   // HASH define foo bar
317   // From having the # character end up at column 1, which makes it so it
318   // is not handled as a #define next time through the preprocessor if in
319   // -fpreprocessed mode.
320   if (ColNo <= 1 && Tok.is(tok::hash))
321     OS << ' ';
322 
323   // Otherwise, indent the appropriate number of spaces.
324   for (; ColNo > 1; --ColNo)
325     OS << ' ';
326 
327   return true;
328 }
329 
330 namespace {
331 struct UnknownPragmaHandler : public PragmaHandler {
332   const char *Prefix;
333   PrintPPOutputPPCallbacks *Callbacks;
334 
335   UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks)
336     : PragmaHandler(0), Prefix(prefix), Callbacks(callbacks) {}
337   virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) {
338     // Figure out what line we went to and insert the appropriate number of
339     // newline characters.
340     Callbacks->MoveToLine(PragmaTok.getLocation());
341     Callbacks->OS.write(Prefix, strlen(Prefix));
342 
343     // Read and print all of the pragma tokens.
344     while (PragmaTok.isNot(tok::eom)) {
345       if (PragmaTok.hasLeadingSpace())
346         Callbacks->OS << ' ';
347       std::string TokSpell = PP.getSpelling(PragmaTok);
348       Callbacks->OS.write(&TokSpell[0], TokSpell.size());
349       PP.LexUnexpandedToken(PragmaTok);
350     }
351     Callbacks->OS << '\n';
352   }
353 };
354 } // end anonymous namespace
355 
356 
357 static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
358                                     PrintPPOutputPPCallbacks *Callbacks,
359                                     llvm::raw_ostream &OS) {
360   char Buffer[256];
361   Token PrevTok;
362   while (1) {
363 
364     // If this token is at the start of a line, emit newlines if needed.
365     if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
366       // done.
367     } else if (Tok.hasLeadingSpace() ||
368                // If we haven't emitted a token on this line yet, PrevTok isn't
369                // useful to look at and no concatenation could happen anyway.
370                (Callbacks->hasEmittedTokensOnThisLine() &&
371                 // Don't print "-" next to "-", it would form "--".
372                 Callbacks->AvoidConcat(PrevTok, Tok))) {
373       OS << ' ';
374     }
375 
376     if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
377       OS.write(II->getName(), II->getLength());
378     } else if (Tok.isLiteral() && !Tok.needsCleaning() &&
379                Tok.getLiteralData()) {
380       OS.write(Tok.getLiteralData(), Tok.getLength());
381     } else if (Tok.getLength() < 256) {
382       const char *TokPtr = Buffer;
383       unsigned Len = PP.getSpelling(Tok, TokPtr);
384       OS.write(TokPtr, Len);
385     } else {
386       std::string S = PP.getSpelling(Tok);
387       OS.write(&S[0], S.size());
388     }
389     Callbacks->SetEmittedTokensOnThisLine();
390 
391     if (Tok.is(tok::eof)) break;
392 
393     PrevTok = Tok;
394     PP.Lex(Tok);
395   }
396 }
397 
398 namespace {
399   struct SortMacrosByID {
400     typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
401     bool operator()(const id_macro_pair &LHS, const id_macro_pair &RHS) const {
402       return strcmp(LHS.first->getName(), RHS.first->getName()) < 0;
403     }
404   };
405 }
406 
407 void clang::DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
408   // -dM mode just scans and ignores all tokens in the files, then dumps out
409   // the macro table at the end.
410   PP.EnterMainSourceFile();
411 
412   Token Tok;
413   do PP.Lex(Tok);
414   while (Tok.isNot(tok::eof));
415 
416   std::vector<std::pair<IdentifierInfo*, MacroInfo*> > MacrosByID;
417   for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
418        I != E; ++I)
419     MacrosByID.push_back(*I);
420   std::sort(MacrosByID.begin(), MacrosByID.end(), SortMacrosByID());
421 
422   for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
423     MacroInfo &MI = *MacrosByID[i].second;
424     // Ignore computed macros like __LINE__ and friends.
425     if (MI.isBuiltinMacro()) continue;
426 
427     PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS);
428     *OS << "\n";
429   }
430 }
431 
432 /// DoPrintPreprocessedInput - This implements -E mode.
433 ///
434 void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
435                                      bool EnableCommentOutput,
436                                      bool EnableMacroCommentOutput,
437                                      bool DisableLineMarkers,
438                                      bool DumpDefines) {
439   // Inform the preprocessor whether we want it to retain comments or not, due
440   // to -C or -CC.
441   PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput);
442 
443   OS->SetBufferSize(64*1024);
444 
445   PrintPPOutputPPCallbacks *Callbacks =
446       new PrintPPOutputPPCallbacks(PP, *OS, DisableLineMarkers, DumpDefines);
447   PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
448   PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
449                                                       Callbacks));
450 
451   PP.setPPCallbacks(Callbacks);
452 
453   // After we have configured the preprocessor, enter the main file.
454   PP.EnterMainSourceFile();
455 
456   // Consume all of the tokens that come from the predefines buffer.  Those
457   // should not be emitted into the output and are guaranteed to be at the
458   // start.
459   const SourceManager &SourceMgr = PP.getSourceManager();
460   Token Tok;
461   do PP.Lex(Tok);
462   while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() &&
463          !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(),
464                  "<built-in>"));
465 
466   // Read all the preprocessed tokens, printing them out to the stream.
467   PrintPreprocessedTokens(PP, Tok, Callbacks, *OS);
468   *OS << '\n';
469 }
470 
471