#include <cstdio>
using namespace clang;
-static std::string OutputFilename;
-static llvm::raw_ostream *OutStream;
-
-/// InitOutputBuffer - Initialize our output buffer.
-///
-static void InitOutputBuffer(const std::string& Output) {
- if (!Output.size() || Output == "-") {
- OutputFilename = "<stdout>";
- OutStream = new llvm::raw_stdout_ostream();
- } else {
- OutputFilename = Output;
- std::string Err;
- OutStream = new llvm::raw_fd_ostream(Output.c_str(), Err);
-
- if (!Err.empty()) {
- delete OutStream;
- fprintf(stderr, "%s\n", Err.c_str());
- exit(1);
- }
- }
- OutStream->SetBufferSize(64*1024);
-}
-
-/// CleanupOutputBuffer - Finish up output.
-///
-static void CleanupOutputBuffer(bool ErrorOccurred) {
- delete OutStream;
-
- // If an error occurred, remove the output file.
- if (ErrorOccurred && !OutputFilename.empty())
- llvm::sys::Path(OutputFilename).eraseFromDisk();
-}
-
-static inline void OutputChar(char c) {
- *OutStream << c;
-}
-
-static inline void OutputString(const char *Ptr, unsigned Size) {
- OutStream->write(Ptr, Size);
-}
-
-
//===----------------------------------------------------------------------===//
// Preprocessed token printer
//===----------------------------------------------------------------------===//
namespace {
class PrintPPOutputPPCallbacks : public PPCallbacks {
Preprocessor &PP;
+public:
+ llvm::raw_ostream &OS;
+private:
unsigned CurLine;
bool EmittedTokensOnThisLine;
DirectoryLookup::DirType FileType;
llvm::SmallString<512> CurFilename;
public:
- PrintPPOutputPPCallbacks(Preprocessor &pp) : PP(pp) {
+ PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os)
+ : PP(pp), OS(os) {
CurLine = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
if (!EmittedTokensOnThisLine)
return true;
- OutputChar('\n');
+ OS << '\n';
EmittedTokensOnThisLine = false;
return true;
}
// otherwise print a #line directive.
if (LineNo-CurLine < 8) {
if (LineNo-CurLine == 1)
- OutputChar('\n');
+ OS << '\n';
else if (LineNo == CurLine)
return false; // Phys line moved, but logical line didn't.
else {
const char *NewLines = "\n\n\n\n\n\n\n\n";
- OutputString(NewLines, LineNo-CurLine);
+ OS.write(NewLines, LineNo-CurLine);
}
CurLine = LineNo;
} else {
if (EmittedTokensOnThisLine) {
- OutputChar('\n');
+ OS << '\n';
EmittedTokensOnThisLine = false;
}
CurLine = LineNo;
- OutputChar('#');
- OutputChar(' ');
+ OS << '#' << ' ';
char NumberBuffer[20];
const char *NumStr = UToStr(LineNo, NumberBuffer+20);
- OutputString(NumStr, (NumberBuffer+20)-NumStr-1);
- OutputChar(' ');
- OutputChar('"');
- OutputString(&CurFilename[0], CurFilename.size());
- OutputChar('"');
+ OS.write(NumStr, (NumberBuffer+20)-NumStr-1);
+ OS << ' ';
+ OS << '"';
+ OS.write(&CurFilename[0], CurFilename.size());
+ OS << '"';
if (FileType == DirectoryLookup::SystemHeaderDir)
- OutputString(" 3", 2);
+ OS.write(" 3", 2);
else if (FileType == DirectoryLookup::ExternCSystemHeaderDir)
- OutputString(" 3 4", 4);
- OutputChar('\n');
+ OS.write(" 3 4", 4);
+ OS << '\n';
}
return true;
}
FileType = FileType;
if (EmittedTokensOnThisLine) {
- OutputChar('\n');
+ OS << '\n';
EmittedTokensOnThisLine = false;
}
- OutputChar('#');
- OutputChar(' ');
+ OS << '#' << ' ';
char NumberBuffer[20];
const char *NumStr = UToStr(CurLine, NumberBuffer+20);
- OutputString(NumStr, (NumberBuffer+20)-NumStr-1);
- OutputChar(' ');
- OutputChar('"');
- OutputString(&CurFilename[0], CurFilename.size());
- OutputChar('"');
+ OS.write(NumStr, (NumberBuffer+20)-NumStr-1);
+ OS << ' ' << '"';
+ OS.write(&CurFilename[0], CurFilename.size());
+ OS << '"';
switch (Reason) {
case PPCallbacks::EnterFile:
- OutputString(" 1", 2);
+ OS.write(" 1", 2);
break;
case PPCallbacks::ExitFile:
- OutputString(" 2", 2);
+ OS.write(" 2", 2);
break;
case PPCallbacks::SystemHeaderPragma: break;
case PPCallbacks::RenameFile: break;
}
if (FileType == DirectoryLookup::SystemHeaderDir)
- OutputString(" 3", 2);
+ OS.write(" 3", 2);
else if (FileType == DirectoryLookup::ExternCSystemHeaderDir)
- OutputString(" 3 4", 4);
+ OS.write(" 3 4", 4);
- OutputChar('\n');
+ OS << '\n';
}
/// HandleIdent - Handle #ident directives when read by the preprocessor.
void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
MoveToLine(Loc);
- OutputString("#ident ", strlen("#ident "));
- OutputString(&S[0], S.size());
+ OS.write("#ident ", strlen("#ident "));
+ OS.write(&S[0], S.size());
EmittedTokensOnThisLine = true;
}
// is not handled as a #define next time through the preprocessor if in
// -fpreprocessed mode.
if (ColNo <= 1 && Tok.is(tok::hash))
- OutputChar(' ');
+ OS << ' ';
// Otherwise, indent the appropriate number of spaces.
for (; ColNo > 1; --ColNo)
- OutputChar(' ');
+ OS << ' ';
return true;
}
// Figure out what line we went to and insert the appropriate number of
// newline characters.
Callbacks->MoveToLine(PragmaTok.getLocation());
- OutputString(Prefix, strlen(Prefix));
+ Callbacks->OS.write(Prefix, strlen(Prefix));
// Read and print all of the pragma tokens.
while (PragmaTok.isNot(tok::eom)) {
if (PragmaTok.hasLeadingSpace())
- OutputChar(' ');
+ Callbacks->OS << ' ';
std::string TokSpell = PP.getSpelling(PragmaTok);
- OutputString(&TokSpell[0], TokSpell.size());
+ Callbacks->OS.write(&TokSpell[0], TokSpell.size());
PP.LexUnexpandedToken(PragmaTok);
}
- OutputChar('\n');
+ Callbacks->OS << '\n';
}
};
} // end anonymous namespace
// Inform the preprocessor whether we want it to retain comments or not, due
// to -C or -CC.
PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput);
-
- InitOutputBuffer(OutFile);
InitAvoidConcatTokenInfo();
+
+
+ // Open the output buffer.
+ static llvm::raw_ostream *OutStream;
+
+ if (!OutFile.size() || OutFile == "-") {
+ OutStream = new llvm::raw_stdout_ostream();
+ } else {
+ std::string Err;
+ OutStream = new llvm::raw_fd_ostream(OutFile.c_str(), Err);
+
+ if (!Err.empty()) {
+ delete OutStream;
+ fprintf(stderr, "%s\n", Err.c_str());
+ exit(1);
+ }
+ }
+ OutStream->SetBufferSize(64*1024);
+
+ llvm::raw_ostream &OS = *OutStream;
Token Tok, PrevTok;
char Buffer[256];
- PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP);
+ PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP, OS);
PP.setPPCallbacks(Callbacks);
PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
(Callbacks->hasEmittedTokensOnThisLine() &&
// Don't print "-" next to "-", it would form "--".
Callbacks->AvoidConcat(PrevTok, Tok))) {
- OutputChar(' ');
+ OS << ' ';
}
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
const char *Str = II->getName();
unsigned Len = Tok.needsCleaning() ? strlen(Str) : Tok.getLength();
- OutputString(Str, Len);
+ OS.write(Str, Len);
} else if (Tok.getLength() < 256) {
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
- OutputString(TokPtr, Len);
+ OS.write(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
- OutputString(&S[0], S.size());
+ OS.write(&S[0], S.size());
}
Callbacks->SetEmittedTokensOnThisLine();
PrevTok = Tok;
PP.Lex(Tok);
}
- OutputChar('\n');
+ OS << '\n';
- CleanupOutputBuffer(PP.getDiagnostics().hasErrorOccurred());
+ // Flush and free the ostream.
+ delete &OS;
+
+ // If an error occurred, remove the output file.
+ if (PP.getDiagnostics().hasErrorOccurred() && !OutFile.empty())
+ llvm::sys::Path(OutFile).eraseFromDisk();
}