#include #include "AST.h" #include "CfSource.h" #include "CodeContext.h" #include "compiler.h" #include "parse.h" const int CodeContext::recoverSlot = ios::xalloc(); void CodeContext::declare( const string &name, const CtType &type) { if (&whereDeclare == this) LocalVars::declare(name, type); else whereDeclare.declare(name, type); } inline CodeContext *CodeContext::recover( ostream &out ) { void * const pointer = out.pword( recoverSlot ); return static_cast< CodeContext * >( pointer ); } void CodeContext::emitLineFileDirective( const SourcePosn &position, ostream &sink ) const { if (!suppress_directives && position.known()) sink << "#line " << position.posnToLineNumber() << " \"" << *position.file << "\"\n"; } void CodeContext::emitLineDirective( const SourcePosn &position, ostream &sink ) const { if (!suppress_directives && position.known()) sink << "#line " << position.posnToLineNumber() << '\n'; } ostream &endCline( ostream &outs ) { outs << '\n'; CodeContext *context = CodeContext::recover( outs ); if (context == NULL) { cerr << "Internal Error: tried to use endCline outside any CodeContext" << endl; abort(); } context->emitLineDirective( context->currentPosition, *context ); return outs; } CodeContext::CodeContext( CodeContext &parent, ostream &sink ) : LocalVars( parent ), strings( parent.strings ), sink( sink ), parent( &parent ), whereDeclare( *this ), currentPosition( parent.currentPosition ), startPosition( parent.currentPosition ), level( parent.level + 1 ), suppress_directives( !line_directives ) { pword( recoverSlot ) = this; } CodeContext::CodeContext( CodeContext &parent ) : LocalVars( parent ), strings( parent.strings ), sink( parent ), parent( &parent ), whereDeclare( *this ), currentPosition( parent.currentPosition ), startPosition( parent.currentPosition ), level( parent.level + 1 ), suppress_directives( !line_directives ) { pword( recoverSlot ) = this; } CodeContext::CodeContext( CodeContext &parent, CodeContext &whereDeclare ) : LocalVars( parent ), strings( parent.strings ), sink( parent ), parent( &parent ), whereDeclare( whereDeclare ), currentPosition( parent.currentPosition ), startPosition( parent.currentPosition ), level( parent.level + 1 ), suppress_directives( !line_directives ) { pword( recoverSlot ) = this; } CodeContext::CodeContext( CodeContext &parent, CodeContext *w ) : LocalVars( parent ), strings( parent.strings ), sink( parent ), parent( &parent ), whereDeclare( w == NULL ? *this : *w ), currentPosition( parent.currentPosition ), startPosition( parent.currentPosition ), level( parent.level + 1 ), suppress_directives( !line_directives ) { pword( recoverSlot ) = this; } CodeContext::CodeContext( CfSource &file ) : LocalVars( file ), strings( file ), sink( file ), parent( 0 ), whereDeclare( *this ), currentPosition( NoSourcePosition ), startPosition( NoSourcePosition ), level( 0 ), suppress_directives( !line_directives ) { pword( recoverSlot ) = this; } CodeContext::~CodeContext() { codeGen(); if (parent) { /* Set parent line information to the start of this context. This is done in case the parent start_debug_{line,file} information has not been filed yet. */ parent->setPosition( startPosition ); /* Set parent line information to the end of this context, so that the parent can continue where this context left off. */ parent->setPosition( currentPosition ); } } void CodeContext::codeGen( ostream &sink ) const { emitLineFileDirective( startPosition, sink ); sink << "{/*L:" << level << "*/\n"; emitLineDirective( startPosition, sink ); LocalVars::codeGen( sink, suppress_directives ? 0 : startPosition.posnToLineNumber() ); sink << str() << "}/*L:" << level << "*/\n"; if (startPosition.file == currentPosition.file) emitLineDirective( currentPosition, sink ); else emitLineFileDirective( currentPosition, sink ); } void CodeContext::setPosition( const SourcePosn &newPosition ) { if (newPosition.known()) { if (newPosition.file == currentPosition.file) if (newPosition.posnToLineNumber() == currentPosition.posnToLineNumber()) // same file, same line ; else // same file, different line emitLineDirective( newPosition, *this ); else // different file, different line emitLineFileDirective( newPosition, *this ); currentPosition = newPosition; if (startPosition.unknown()) startPosition = newPosition; } }