// emitcode.cc see license.txt for copyright and terms of use // code for emitcode.h #include "emitcode.h" // this module #include "syserr.h" // xsyserror #include "SourceLocation.h" // SourceLocation using ellcc::SourceLocation; #include "SourceManager.h" // SourceManager #include "trace.h" // tracingSys #include // memcpy using namespace ellcc; EmitCode::EmitCode(rostring f) : stringBuilder(), os(f.c_str()), fname(f), line(1) { if (!os) { xsyserror("open", fname); } } EmitCode::~EmitCode() { flush(); } int EmitCode::getLine() { flush(); return line; } void EmitCode::flush() { // count newlines char const *p = c_str(); while (*p) { if (*p == '\n') { line++; } p++; } #if 0 // this is the original code os << *this; #else // 2005-06-28: There is a bug in the cygwin implementation of // ofstream::operator<< that causes a stack overflow segfault // when writing strings longer than about 2MB. So, I will // manually break up the string into little chunks to write it. // how long is the string? int len = p - c_str(); enum { SZ = 0x1000 }; // write in 4k chunks p = c_str(); while (len >= SZ) { char buf[SZ+1]; memcpy(buf, p, SZ); buf[SZ] = 0; os << buf; p += SZ; len -= SZ; } os << p; #endif setlength(0); } char const *hashLine() { if (tracingSys("nolines")) { // emit with comment to disable its effect return "// #line "; } else { return "#line "; } } // note that #line must be preceeded by a newline sm::string lineDirective(SourceLocation loc) { SourceManager SM; PresumedLoc ploc = SM.getPresumedLoc(loc); return stringc << hashLine() << ploc.getLine() << " \"" << ploc.getFilename() << "\"\n"; } stringBuilder &restoreLine(stringBuilder &sb) { // little hack.. EmitCode &os = (EmitCode&)sb; // +1 because we specify what line will be *next* int line = os.getLine()+1; return os << hashLine() << line << " \"" << os.getFname() << "\"\n"; }