beebasm

changeset 35:5fedd5b15bd7

Fixed a serious issue with access to out-of-bounds indices in std::strings (I have no idea why this was working all along with GCC in release builds). Finished macro implementation (finally). Some minor changes to message output.
author RichTW <richtw1@gmail.com>
date Mon Apr 25 01:14:59 2011 +0200
parents 5aca9d5e4d02
children 9988a3cb5311
files beebasm.exe demo.ssd src/Makefile src/Makefile.inc src/VS2010/BeebAsm.vcxproj src/VS2010/BeebAsm.vcxproj.filters src/asmexception.cpp src/asmexception.h src/assemble.cpp src/commands.cpp src/expression.cpp src/lineparser.cpp src/lineparser.h src/macro.cpp src/macro.h src/sourcecode.cpp src/sourcecode.h src/sourcefile.cpp src/sourcefile.h
diffstat 19 files changed, 1058 insertions(+), 595 deletions(-) [+]
line diff
     1.1 Binary file beebasm.exe has changed
     2.1 Binary file demo.ssd has changed
     3.1 --- a/src/Makefile	Sun Mar 06 18:19:27 2011 +0100
     3.2 +++ b/src/Makefile	Mon Apr 25 01:14:59 2011 +0200
     3.3 @@ -51,8 +51,8 @@
     3.4  
     3.5  # Parameters to the executable
     3.6  
     3.7 -#PARAMS			:=		-i ../demo.6502 -do ../demo.ssd -boot Code
     3.8 -PARAMS			:=		-i ../test.6502 -v
     3.9 +PARAMS			:=		-i ../demo.6502 -do ../demo.ssd -boot Code -v
    3.10 +#PARAMS			:=		-i ../test.6502 -v
    3.11  
    3.12  
    3.13  
     4.1 --- a/src/Makefile.inc	Sun Mar 06 18:19:27 2011 +0100
     4.2 +++ b/src/Makefile.inc	Mon Apr 25 01:14:59 2011 +0200
     4.3 @@ -134,11 +134,16 @@
     4.4  
     4.5  # Add platform-specific flags
     4.6  
     4.7 +ifeq ($(PLATFORM),mingw-gcc3)
     4.8 +TARGET			:=		$(addsuffix .exe,$(TARGET))
     4.9 +endif
    4.10 +
    4.11  ifeq ($(PLATFORM),mingw-gcc4)
    4.12  LDFLAGS			+=		-static
    4.13  TARGET			:=		$(addsuffix .exe,$(TARGET))
    4.14  endif
    4.15  
    4.16 +
    4.17  # Declare default number of CPUs
    4.18  
    4.19  CPUS			?=		1
     5.1 --- a/src/VS2010/BeebAsm.vcxproj	Sun Mar 06 18:19:27 2011 +0100
     5.2 +++ b/src/VS2010/BeebAsm.vcxproj	Mon Apr 25 01:14:59 2011 +0200
     5.3 @@ -85,6 +85,7 @@
     5.4      <ClCompile Include="..\macro.cpp" />
     5.5      <ClCompile Include="..\main.cpp" />
     5.6      <ClCompile Include="..\objectcode.cpp" />
     5.7 +    <ClCompile Include="..\sourcecode.cpp" />
     5.8      <ClCompile Include="..\sourcefile.cpp" />
     5.9      <ClCompile Include="..\stringutils.cpp" />
    5.10      <ClCompile Include="..\symboltable.cpp" />
    5.11 @@ -98,6 +99,7 @@
    5.12      <ClInclude Include="..\macro.h" />
    5.13      <ClInclude Include="..\main.h" />
    5.14      <ClInclude Include="..\objectcode.h" />
    5.15 +    <ClInclude Include="..\sourcecode.h" />
    5.16      <ClInclude Include="..\sourcefile.h" />
    5.17      <ClInclude Include="..\stringutils.h" />
    5.18      <ClInclude Include="..\symboltable.h" />
     6.1 --- a/src/VS2010/BeebAsm.vcxproj.filters	Sun Mar 06 18:19:27 2011 +0100
     6.2 +++ b/src/VS2010/BeebAsm.vcxproj.filters	Mon Apr 25 01:14:59 2011 +0200
     6.3 @@ -57,6 +57,9 @@
     6.4      <ClCompile Include="..\macro.cpp">
     6.5        <Filter>Source Files</Filter>
     6.6      </ClCompile>
     6.7 +    <ClCompile Include="..\sourcecode.cpp">
     6.8 +      <Filter>Source Files</Filter>
     6.9 +    </ClCompile>
    6.10    </ItemGroup>
    6.11    <ItemGroup>
    6.12      <ClInclude Include="..\asmexception.h">
    6.13 @@ -92,5 +95,8 @@
    6.14      <ClInclude Include="..\macro.h">
    6.15        <Filter>Header Files</Filter>
    6.16      </ClInclude>
    6.17 +    <ClInclude Include="..\sourcecode.h">
    6.18 +      <Filter>Header Files</Filter>
    6.19 +    </ClInclude>
    6.20    </ItemGroup>
    6.21  </Project>
    6.22 \ No newline at end of file
     7.1 --- a/src/asmexception.cpp	Sun Mar 06 18:19:27 2011 +0100
     7.2 +++ b/src/asmexception.cpp	Mon Apr 25 01:14:59 2011 +0200
     7.3 @@ -41,7 +41,7 @@
     7.4  /*************************************************************************************************/
     7.5  void AsmException_FileError::Print() const
     7.6  {
     7.7 -	cerr << "Error: " << m_pFilename << ": " << Message() << endl;
     7.8 +	cerr << "Error: " << m_filename << ": " << Message() << endl;
     7.9  }
    7.10  
    7.11  
    7.12 @@ -55,10 +55,10 @@
    7.13  /*************************************************************************************************/
    7.14  void AsmException_SyntaxError::Print() const
    7.15  {
    7.16 -	assert( m_pFilename != NULL );
    7.17 +	assert( m_filename != "" );
    7.18  	assert( m_lineNumber != 0 );
    7.19  
    7.20 -	cerr << m_pFilename << ":" << m_lineNumber << ": error: ";
    7.21 +	cerr << m_filename << ":" << m_lineNumber << ": error: ";
    7.22  	cerr << Message() << endl << endl;
    7.23  	cerr << m_line << endl;
    7.24  	cerr << string( m_column, ' ' ) << "^" << endl;
     8.1 --- a/src/asmexception.h	Sun Mar 06 18:19:27 2011 +0100
     8.2 +++ b/src/asmexception.h	Mon Apr 25 01:14:59 2011 +0200
     8.3 @@ -57,8 +57,8 @@
     8.4  {
     8.5  public:
     8.6  
     8.7 -	explicit AsmException_FileError( const char* pFilename )
     8.8 -		:	m_pFilename( pFilename )
     8.9 +	explicit AsmException_FileError( const std::string& filename )
    8.10 +		:	m_filename( filename )
    8.11  	{
    8.12  	}
    8.13  
    8.14 @@ -73,7 +73,7 @@
    8.15  
    8.16  protected:
    8.17  
    8.18 -	const char*			m_pFilename;
    8.19 +	std::string			m_filename;
    8.20  };
    8.21  
    8.22  
    8.23 @@ -81,8 +81,8 @@
    8.24  class AsmException_FileError_##a : public AsmException_FileError			\
    8.25  {																			\
    8.26  public:																		\
    8.27 -	explicit AsmException_FileError_##a( const char* pFilename )			\
    8.28 -		:	AsmException_FileError( pFilename ) {}							\
    8.29 +	explicit AsmException_FileError_##a( const std::string filename )			\
    8.30 +		:	AsmException_FileError( filename ) {}							\
    8.31  																			\
    8.32  	virtual ~AsmException_FileError_##a() {}								\
    8.33  																			\
    8.34 @@ -116,7 +116,7 @@
    8.35  public:
    8.36  
    8.37  	AsmException_SyntaxError()
    8.38 -		:	m_pFilename( NULL ),
    8.39 +		:	m_filename( "" ),
    8.40  			m_lineNumber( 0 )
    8.41  	{
    8.42  	}
    8.43 @@ -124,14 +124,14 @@
    8.44  	AsmException_SyntaxError( std::string line, int column )
    8.45  		:	m_line( line ),
    8.46  			m_column( column ),
    8.47 -			m_pFilename( NULL ),
    8.48 +			m_filename( "" ),
    8.49  			m_lineNumber( 0 )
    8.50  	{
    8.51  	}
    8.52  
    8.53  	virtual ~AsmException_SyntaxError() {}
    8.54  
    8.55 -	void SetFilename( const char* filename )	{ if ( m_pFilename == NULL ) m_pFilename = filename; }
    8.56 +	void SetFilename( const std::string& filename )	{ if ( m_filename == "" ) m_filename = filename; }
    8.57  	void SetLineNumber( int lineNumber )		{ if ( m_lineNumber == 0 ) m_lineNumber = lineNumber; }
    8.58  
    8.59  	virtual void Print() const;
    8.60 @@ -145,7 +145,7 @@
    8.61  
    8.62  	std::string			m_line;
    8.63  	int					m_column;
    8.64 -	const char*			m_pFilename;
    8.65 +	std::string			m_filename;
    8.66  	int					m_lineNumber;
    8.67  };
    8.68  
     9.1 --- a/src/assemble.cpp	Sun Mar 06 18:19:27 2011 +0100
     9.2 +++ b/src/assemble.cpp	Mon Apr 25 01:14:59 2011 +0200
     9.3 @@ -394,7 +394,7 @@
     9.4  
     9.5  	// OK, something follows... maybe it's immediate mode
     9.6  
     9.7 -	if ( m_line[ m_column ] == '#' )
     9.8 +	if ( m_column < m_line.length() && m_line[ m_column ] == '#' )
     9.9  	{
    9.10  		if ( !HasAddressingMode( instruction, IMM ) )
    9.11  		{
    9.12 @@ -435,7 +435,7 @@
    9.13  			throw AsmException_SyntaxError_ImmNegative( m_line, oldColumn );
    9.14  		}
    9.15  
    9.16 -		if ( m_line[ m_column ] == ',' )
    9.17 +		if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
    9.18  		{
    9.19  			// Unexpected comma (remembering that an expression can validly end with a comma)
    9.20  			throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
    9.21 @@ -448,7 +448,7 @@
    9.22  
    9.23  	// see if it's accumulator mode
    9.24  
    9.25 -	if ( toupper( m_line[ m_column ] ) == 'A' && HasAddressingMode( instruction, ACC ) )
    9.26 +	if ( m_column < m_line.length() && toupper( m_line[ m_column ] ) == 'A' && HasAddressingMode( instruction, ACC ) )
    9.27  	{
    9.28  		// might be... but only if the next character is a separator or whitespace
    9.29  		// otherwise, we must assume a label beginning with A
    9.30 @@ -472,7 +472,7 @@
    9.31  
    9.32  	// see if it's (ind,X), (ind),Y or (ind16)
    9.33  
    9.34 -	if ( m_line[ m_column ] == '(' )
    9.35 +	if ( m_column < m_line.length() && m_line[ m_column ] == '(' )
    9.36  	{
    9.37  		oldColumn = m_column;
    9.38  		m_column++;
    9.39 @@ -501,7 +501,7 @@
    9.40  		// we know that ind and ind16 forms are exclusive
    9.41  		// check (ind), (ind16) and (ind),Y
    9.42  
    9.43 -		if ( m_line[ m_column ] == ')' )
    9.44 +		if ( m_column < m_line.length() && m_line[ m_column ] == ')' )
    9.45  		{
    9.46  			m_column++;
    9.47  
    9.48 @@ -549,7 +549,7 @@
    9.49  
    9.50  			// if we find ,Y then it's an (ind),Y
    9.51  
    9.52 -			if ( m_line[ m_column ] == ',' )
    9.53 +			if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
    9.54  			{
    9.55  				m_column++;
    9.56  
    9.57 @@ -606,7 +606,7 @@
    9.58  
    9.59  		// check (ind,X) or (ind16,X)
    9.60  
    9.61 -		if ( m_line[ m_column ] == ',' )
    9.62 +		if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
    9.63  		{
    9.64  			m_column++;
    9.65  
    9.66 @@ -758,7 +758,7 @@
    9.67  
    9.68  	// finally, check for indexed versions of the opcode
    9.69  
    9.70 -	if ( m_line[ m_column ] != ',' )
    9.71 +	if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
    9.72  	{
    9.73  		// weird character - throw error
    9.74  		throw AsmException_SyntaxError_BadAbsolute( m_line, m_column );
    9.75 @@ -772,7 +772,7 @@
    9.76  		throw AsmException_SyntaxError_BadAbsolute( m_line, m_column );
    9.77  	}
    9.78  
    9.79 -	if ( toupper( m_line[ m_column ] ) == 'X' )
    9.80 +	if ( m_column < m_line.length() && toupper( m_line[ m_column ] ) == 'X' )
    9.81  	{
    9.82  		m_column++;
    9.83  
    9.84 @@ -803,7 +803,7 @@
    9.85  		}
    9.86  	}
    9.87  
    9.88 -	if ( toupper( m_line[ m_column ] ) == 'Y' )
    9.89 +	if ( m_column < m_line.length() && toupper( m_line[ m_column ] ) == 'Y' )
    9.90  	{
    9.91  		m_column++;
    9.92  
    10.1 --- a/src/commands.cpp	Sun Mar 06 18:19:27 2011 +0100
    10.2 +++ b/src/commands.cpp	Mon Apr 25 01:14:59 2011 +0200
    10.3 @@ -130,7 +130,7 @@
    10.4  /*************************************************************************************************/
    10.5  void LineParser::HandleDefineLabel()
    10.6  {
    10.7 -	if ( isalpha( m_line[ m_column ] ) || m_line[ m_column ] == '_' )
    10.8 +	if ( m_column < m_line.length() && ( isalpha( m_line[ m_column ] ) || m_line[ m_column ] == '_' ) )
    10.9  	{
   10.10  		// Symbol starts with a valid character
   10.11  
   10.12 @@ -142,7 +142,7 @@
   10.13  
   10.14  		// ...and mangle it according to whether we are in a FOR loop
   10.15  
   10.16 -		string fullSymbolName = symbolName + m_sourceFile->GetSymbolNameSuffix();
   10.17 +		string fullSymbolName = symbolName + m_sourceCode->GetSymbolNameSuffix();
   10.18  
   10.19  		if ( GlobalData::Instance().IsFirstPass() )
   10.20  		{
   10.21 @@ -238,7 +238,7 @@
   10.22  	ObjectCode::Instance().SetPC( newPC );
   10.23  	SymbolTable::Instance().ChangeSymbol( "P%", newPC );
   10.24  
   10.25 -	if ( m_line[ m_column ] == ',' )
   10.26 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.27  	{
   10.28  		// Unexpected comma (remembering that an expression can validly end with a comma)
   10.29  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   10.30 @@ -262,7 +262,7 @@
   10.31  
   10.32  	ObjectCode::Instance().SetCPU( newCpu );
   10.33  
   10.34 -	if ( m_line[ m_column ] == ',' )
   10.35 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.36  	{
   10.37  		// Unexpected comma (remembering that an expression can validly end with a comma)
   10.38  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   10.39 @@ -286,7 +286,7 @@
   10.40  
   10.41  	ObjectCode::Instance().SetGuard( val );
   10.42  
   10.43 -	if ( m_line[ m_column ] == ',' )
   10.44 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.45  	{
   10.46  		// Unexpected comma (remembering that an expression can validly end with a comma)
   10.47  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   10.48 @@ -308,7 +308,7 @@
   10.49  		throw AsmException_SyntaxError_OutOfRange( m_line, m_column );
   10.50  	}
   10.51  
   10.52 -	if ( m_line[ m_column ] != ',' )
   10.53 +	if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
   10.54  	{
   10.55  		// did not find a comma
   10.56  		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
   10.57 @@ -324,7 +324,7 @@
   10.58  
   10.59  	ObjectCode::Instance().Clear( start, end );
   10.60  
   10.61 -	if ( m_line[ m_column ] == ',' )
   10.62 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.63  	{
   10.64  		// Unexpected comma (remembering that an expression can validly end with a comma)
   10.65  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   10.66 @@ -345,7 +345,7 @@
   10.67  	int param3 = -1;
   10.68  	int param1 = EvaluateExpressionAsInt();
   10.69  
   10.70 -	if ( m_line[ m_column ] != ',' )
   10.71 +	if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
   10.72  	{
   10.73  		// did not find a comma
   10.74  		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
   10.75 @@ -355,14 +355,14 @@
   10.76  
   10.77  	int param2 = EvaluateExpressionAsInt();
   10.78  
   10.79 -	if ( m_line[ m_column ] == ',' )
   10.80 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.81  	{
   10.82  		m_column++;
   10.83  
   10.84  		param3 = EvaluateExpressionAsInt();
   10.85  	}
   10.86  
   10.87 -	if ( m_line[ m_column ] == ',' )
   10.88 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.89  	{
   10.90  		// Unexpected comma (remembering that an expression can validly end with a comma)
   10.91  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   10.92 @@ -440,7 +440,7 @@
   10.93  		}
   10.94  	}
   10.95  
   10.96 -	if ( m_line[ m_column ] == ',' )
   10.97 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   10.98  	{
   10.99  		// Unexpected comma (remembering that an expression can validly end with a comma)
  10.100  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
  10.101 @@ -484,7 +484,7 @@
  10.102  		}
  10.103  	}
  10.104  
  10.105 -	if ( m_line[ m_column ] == ',' )
  10.106 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.107  	{
  10.108  		// Unexpected comma (remembering that an expression can validly end with a comma)
  10.109  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
  10.110 @@ -527,7 +527,7 @@
  10.111  		}
  10.112  	}
  10.113  
  10.114 -	if ( m_line[ m_column ] == ',' )
  10.115 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.116  	{
  10.117  		// Unexpected comma (remembering that an expression can validly end with a comma)
  10.118  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
  10.119 @@ -543,7 +543,7 @@
  10.120  /*************************************************************************************************/
  10.121  void LineParser::HandleInclude()
  10.122  {
  10.123 -	if ( m_sourceFile->GetForLevel() > 0 )
  10.124 +	if ( m_sourceCode->GetForLevel() > 0 )
  10.125  	{
  10.126  		// disallow an include within a FOR loop
  10.127  		throw AsmException_SyntaxError_CantInclude( m_line, m_column );
  10.128 @@ -554,7 +554,7 @@
  10.129  		throw AsmException_SyntaxError_EmptyExpression( m_line, m_column );
  10.130  	}
  10.131  
  10.132 -	if ( m_line[ m_column ] != '\"' )
  10.133 +	if ( m_column >= m_line.length() || m_line[ m_column ] != '\"' )
  10.134  	{
  10.135  		throw AsmException_SyntaxError_EmptyExpression( m_line, m_column );
  10.136  	}
  10.137 @@ -601,7 +601,7 @@
  10.138  		throw AsmException_SyntaxError_EmptyExpression( m_line, m_column );
  10.139  	}
  10.140  
  10.141 -	if ( m_line[ m_column ] != '\"' )
  10.142 +	if ( m_column >= m_line.length() || m_line[ m_column ] != '\"' )
  10.143  	{
  10.144  		throw AsmException_SyntaxError_EmptyExpression( m_line, m_column );
  10.145  	}
  10.146 @@ -655,7 +655,7 @@
  10.147  
  10.148  		// handle string
  10.149  
  10.150 -		if ( m_line[ m_column ] == '\"' )
  10.151 +		if ( m_column < m_line.length() && m_line[ m_column ] == '\"' )
  10.152  		{
  10.153  			size_t endQuotePos = m_line.find_first_of( '\"', m_column + 1 );
  10.154  
  10.155 @@ -762,7 +762,7 @@
  10.156  			break;
  10.157  		}
  10.158  
  10.159 -		if ( m_line[ m_column ] != ',' )
  10.160 +		if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
  10.161  		{
  10.162  			throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  10.163  		}
  10.164 @@ -832,7 +832,7 @@
  10.165  			break;
  10.166  		}
  10.167  
  10.168 -		if ( m_line[ m_column ] != ',' )
  10.169 +		if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
  10.170  		{
  10.171  			throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  10.172  		}
  10.173 @@ -906,7 +906,7 @@
  10.174  			break;
  10.175  		}
  10.176  
  10.177 -		if ( m_line[ m_column ] != ',' )
  10.178 +		if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
  10.179  		{
  10.180  			throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  10.181  		}
  10.182 @@ -995,7 +995,7 @@
  10.183  
  10.184  	// get end address
  10.185  
  10.186 -	if ( m_line[ m_column ] != ',' )
  10.187 +	if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
  10.188  	{
  10.189  		// did not find a comma
  10.190  		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  10.191 @@ -1013,7 +1013,7 @@
  10.192  	// get optional exec address
  10.193  	// we allow this to be a forward define as it needn't be within the block we actually save
  10.194  
  10.195 -	if ( m_line[ m_column ] == ',' )
  10.196 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.197  	{
  10.198  		m_column++;
  10.199  
  10.200 @@ -1036,7 +1036,7 @@
  10.201  
  10.202  		// get optional reload address
  10.203  
  10.204 -		if ( m_line[ m_column ] == ',' )
  10.205 +		if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.206  		{
  10.207  			m_column++;
  10.208  
  10.209 @@ -1051,7 +1051,7 @@
  10.210  
  10.211  	// expect no more
  10.212  
  10.213 -	if ( m_line[ m_column ] == ',' )
  10.214 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.215  	{
  10.216  		// Unexpected comma (remembering that an expression can validly end with a comma)
  10.217  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
  10.218 @@ -1121,7 +1121,7 @@
  10.219  	// Symbol starts with a valid character
  10.220  
  10.221  	int oldColumn = m_column;
  10.222 -	string symbolName = GetSymbolName() + m_sourceFile->GetSymbolNameSuffix();
  10.223 +	string symbolName = GetSymbolName() + m_sourceCode->GetSymbolNameSuffix();
  10.224  
  10.225  	// Check variable has not yet been defined
  10.226  
  10.227 @@ -1196,9 +1196,9 @@
  10.228  
  10.229  	}
  10.230  
  10.231 -	m_sourceFile->AddFor( symbolName,
  10.232 +	m_sourceCode->AddFor( symbolName,
  10.233  						  start, end, step,
  10.234 -						  m_sourceFile->GetFilePointer() + m_column,
  10.235 +						  m_sourceCode->GetLineStartPointer() + m_column,
  10.236  						  m_line,
  10.237  						  oldColumn );
  10.238  }
  10.239 @@ -1212,7 +1212,7 @@
  10.240  /*************************************************************************************************/
  10.241  void LineParser::HandleOpenBrace()
  10.242  {
  10.243 -	m_sourceFile->OpenBrace( m_line, m_column - 1 );
  10.244 +	m_sourceCode->OpenBrace( m_line, m_column - 1 );
  10.245  }
  10.246  
  10.247  
  10.248 @@ -1232,7 +1232,7 @@
  10.249  		throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  10.250  	}
  10.251  
  10.252 -	m_sourceFile->UpdateFor( m_line, oldColumn );
  10.253 +	m_sourceCode->UpdateFor( m_line, oldColumn );
  10.254  }
  10.255  
  10.256  
  10.257 @@ -1246,7 +1246,7 @@
  10.258  /*************************************************************************************************/
  10.259  void LineParser::HandleCloseBrace()
  10.260  {
  10.261 -	m_sourceFile->CloseBrace( m_line, m_column - 1 );
  10.262 +	m_sourceCode->CloseBrace( m_line, m_column - 1 );
  10.263  }
  10.264  
  10.265  
  10.266 @@ -1260,9 +1260,9 @@
  10.267  {
  10.268  	// Handles both IF and ELIF
  10.269  	bool condition = (EvaluateExpressionAsInt() != 0);
  10.270 -	m_sourceFile->SetCurrentIfCondition( condition );
  10.271 +	m_sourceCode->SetCurrentIfCondition( condition );
  10.272  
  10.273 -	if ( m_line[ m_column ] == ',' )
  10.274 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.275  	{
  10.276  		// Unexpected comma (remembering that an expression can validly end with a comma)
  10.277  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
  10.278 @@ -1490,7 +1490,7 @@
  10.279  		throw AsmException_SyntaxError_OutOfRange( m_line, m_column );
  10.280  	}
  10.281  
  10.282 -	if ( m_line[ m_column ] == ',' )
  10.283 +	if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
  10.284  	{
  10.285  		m_column++;
  10.286  
  10.287 @@ -1682,8 +1682,8 @@
  10.288  				throw AsmException_SyntaxError_DuplicateMacroName( m_line, m_column );
  10.289  			}
  10.290  
  10.291 -			m_sourceFile->GetCurrentMacro()->SetName( macroName );
  10.292 -			cout << "MACRO '" << macroName << "'" << endl;
  10.293 +			m_sourceCode->GetCurrentMacro()->SetName( macroName );
  10.294 +//			cout << "MACRO '" << macroName << "'" << endl;
  10.295  		}
  10.296  	}
  10.297  	else
  10.298 @@ -1714,8 +1714,8 @@
  10.299  
  10.300  			if ( GlobalData::Instance().IsFirstPass() )
  10.301  			{
  10.302 -				m_sourceFile->GetCurrentMacro()->AddParameter( param );
  10.303 -				cout << "  param: '" << param << "'" << endl;
  10.304 +				m_sourceCode->GetCurrentMacro()->AddParameter( param );
  10.305 +//				cout << "  param: '" << param << "'" << endl;
  10.306  			}
  10.307  			bExpectComma = true;
  10.308  			bHasParameters = true;
  10.309 @@ -1731,7 +1731,7 @@
  10.310  		throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column - 1 );
  10.311  	}
  10.312  
  10.313 -	m_sourceFile->SetCurrentIfCondition(false);
  10.314 +	m_sourceCode->SetCurrentIfCondition(false);
  10.315  }
  10.316  
  10.317  
    11.1 --- a/src/expression.cpp	Sun Mar 06 18:19:27 2011 +0100
    11.2 +++ b/src/expression.cpp	Mon Apr 25 01:14:59 2011 +0200
    11.3 @@ -22,6 +22,7 @@
    11.4  */
    11.5  /*************************************************************************************************/
    11.6  
    11.7 +#include <iostream>
    11.8  #include <cmath>
    11.9  #include <cstring>
   11.10  #include <cerrno>
   11.11 @@ -119,7 +120,7 @@
   11.12  {
   11.13  	double value = 0;
   11.14  
   11.15 -	if ( isdigit( m_line[ m_column ] ) || m_line[ m_column ] == '.' )
   11.16 +	if ( m_column < m_line.length() && ( isdigit( m_line[ m_column ] ) || m_line[ m_column ] == '.' ) )
   11.17  	{
   11.18  		// get a number
   11.19  
   11.20 @@ -128,13 +129,13 @@
   11.21  		str >> value;
   11.22  		m_column = static_cast< size_t >( str.tellg() );
   11.23  	}
   11.24 -	else if ( m_line[ m_column ] == '&' || m_line[ m_column ] == '$' )
   11.25 +	else if ( m_column < m_line.length() && ( m_line[ m_column ] == '&' || m_line[ m_column ] == '$' ) )
   11.26  	{
   11.27  		// get a hex digit
   11.28  
   11.29  		m_column++;
   11.30  
   11.31 -		if ( !isxdigit( m_line[ m_column ] ) )
   11.32 +		if ( m_column >= m_line.length() || !isxdigit( m_line[ m_column ] ) )
   11.33  		{
   11.34  			// badly formed hex literal
   11.35  			throw AsmException_SyntaxError_BadHex( m_line, m_column );
   11.36 @@ -153,13 +154,13 @@
   11.37  			value = static_cast< double >( hexValue );
   11.38  		}
   11.39  	}
   11.40 -	else if ( m_line[ m_column ] == '%' )
   11.41 +	else if ( m_column < m_line.length() && m_line[ m_column ] == '%' )
   11.42  	{
   11.43  		// get binary
   11.44  
   11.45  		m_column++;
   11.46  
   11.47 -		if ( m_line[ m_column ] != '0' && m_line[ m_column ] != '1' )
   11.48 +		if ( m_column >= m_line.length() || ( m_line[ m_column ] != '0' && m_line[ m_column ] != '1' ) )
   11.49  		{
   11.50  			// badly formed bin literal
   11.51  			throw AsmException_SyntaxError_BadBin( m_line, m_column );
   11.52 @@ -175,19 +176,19 @@
   11.53  				binValue = ( binValue * 2 ) + ( m_line[ m_column ] - '0' );
   11.54  				m_column++;
   11.55  			}
   11.56 -			while ( m_line[ m_column ] == '0' || m_line[ m_column ] == '1' );
   11.57 +			while ( m_column < m_line.length() && ( m_line[ m_column ] == '0' || m_line[ m_column ] == '1' ) );
   11.58  
   11.59  			value = static_cast< double >( binValue );
   11.60  		}
   11.61  	}
   11.62 -	else if ( m_line[ m_column ] == '*' )
   11.63 +	else if ( m_column < m_line.length() && m_line[ m_column ] == '*' )
   11.64  	{
   11.65  		// get current PC
   11.66  
   11.67  		m_column++;
   11.68  		value = static_cast< double >( ObjectCode::Instance().GetPC() );
   11.69  	}
   11.70 -	else if ( m_line[ m_column ] == '\'' )
   11.71 +	else if ( m_column < m_line.length() && m_line[ m_column ] == '\'' )
   11.72  	{
   11.73  		// get char literal
   11.74  
   11.75 @@ -200,7 +201,7 @@
   11.76  		value = static_cast< double >( m_line[ m_column + 1 ] );
   11.77  		m_column += 3;
   11.78  	}
   11.79 -	else if ( isalpha( m_line[ m_column ] ) || m_line[ m_column ] == '_' )
   11.80 +	else if ( m_column < m_line.length() && ( isalpha( m_line[ m_column ] ) || m_line[ m_column ] == '_' ) )
   11.81  	{
   11.82  		// get a symbol
   11.83  
   11.84 @@ -208,9 +209,9 @@
   11.85  		string symbolName = GetSymbolName();
   11.86  		bool bFoundSymbol = false;
   11.87  
   11.88 -		for ( int forLevel = m_sourceFile->GetForLevel(); forLevel >= 0; forLevel-- )
   11.89 +		for ( int forLevel = m_sourceCode->GetForLevel(); forLevel >= 0; forLevel-- )
   11.90  		{
   11.91 -			string fullSymbolName = symbolName + m_sourceFile->GetSymbolNameSuffix( forLevel );
   11.92 +			string fullSymbolName = symbolName + m_sourceCode->GetSymbolNameSuffix( forLevel );
   11.93  
   11.94  			if ( SymbolTable::Instance().IsSymbolDefined( fullSymbolName ) )
   11.95  			{
    12.1 --- a/src/lineparser.cpp	Sun Mar 06 18:19:27 2011 +0100
    12.2 +++ b/src/lineparser.cpp	Mon Apr 25 01:14:59 2011 +0200
    12.3 @@ -42,8 +42,8 @@
    12.4  	Constructor for LineParser
    12.5  */
    12.6  /*************************************************************************************************/
    12.7 -LineParser::LineParser( SourceFile* sourceFile, string line )
    12.8 -	:	m_sourceFile( sourceFile ),
    12.9 +LineParser::LineParser( SourceCode* sourceCode, string line )
   12.10 +	:	m_sourceCode( sourceCode ),
   12.11  		m_line( line ),
   12.12  		m_column( 0 )
   12.13  {
   12.14 @@ -92,7 +92,8 @@
   12.15  			{
   12.16  				m_column++;
   12.17  
   12.18 -			} while ( ( isalpha( m_line[ m_column ] ) ||
   12.19 +			} while ( m_column < m_line.length() &&
   12.20 +					  ( isalpha( m_line[ m_column ] ) ||
   12.21  						isdigit( m_line[ m_column ] ) ||
   12.22  						m_line[ m_column ] == '_' ||
   12.23  						m_line[ m_column ] == '%' ) &&
   12.24 @@ -127,7 +128,7 @@
   12.25  
   12.26  		// Next we see if we should even be trying to execute anything.... maybe the if condition is false
   12.27  
   12.28 -		if ( !m_sourceFile->IsIfConditionTrue() )
   12.29 +		if ( !m_sourceCode->IsIfConditionTrue() )
   12.30  		{
   12.31  			m_column = oldColumn;
   12.32  			SkipStatement();
   12.33 @@ -148,53 +149,128 @@
   12.34  			}
   12.35  		}
   12.36  
   12.37 -		// Check to see if it's symbol assignment
   12.38 +		if ( bIsSymbolAssignment )
   12.39 +		{
   12.40 +			// Deal here with symbol assignment
   12.41  
   12.42 -		if ( !isalpha( m_line[ m_column ] ) && m_line[ m_column ] != '_' )
   12.43 -		{
   12.44 -			throw AsmException_SyntaxError_UnrecognisedToken( m_line, m_column );
   12.45 +			string symbolName = GetSymbolName() + m_sourceCode->GetSymbolNameSuffix();
   12.46 +
   12.47 +			if ( !AdvanceAndCheckEndOfStatement() )
   12.48 +			{
   12.49 +				throw AsmException_SyntaxError_UnrecognisedToken( m_line, oldColumn );
   12.50 +			}
   12.51 +
   12.52 +			if ( m_line[ m_column ] != '=' )
   12.53 +			{
   12.54 +				throw AsmException_SyntaxError_UnrecognisedToken( m_line, oldColumn );
   12.55 +			}
   12.56 +
   12.57 +			m_column++;
   12.58 +
   12.59 +			double value = EvaluateExpression();
   12.60 +
   12.61 +			if ( GlobalData::Instance().IsFirstPass() )
   12.62 +			{
   12.63 +				// only add the symbol on the first pass
   12.64 +
   12.65 +				if ( SymbolTable::Instance().IsSymbolDefined( symbolName ) )
   12.66 +				{
   12.67 +					throw AsmException_SyntaxError_LabelAlreadyDefined( m_line, oldColumn );
   12.68 +				}
   12.69 +				else
   12.70 +				{
   12.71 +					SymbolTable::Instance().AddSymbol( symbolName, value );
   12.72 +				}
   12.73 +			}
   12.74 +
   12.75 +			if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
   12.76 +			{
   12.77 +				// Unexpected comma (remembering that an expression can validly end with a comma)
   12.78 +				throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
   12.79 +			}
   12.80 +
   12.81 +			continue;
   12.82  		}
   12.83  
   12.84 -		// Must be symbol assignment
   12.85 +		// Check macro matches
   12.86  
   12.87 -		// Symbol starts with a valid character
   12.88 +		if ( isalpha( m_line[ m_column ] ) || m_line[ m_column ] == '_' )
   12.89 +		{
   12.90 +			string macroName = GetSymbolName();
   12.91 +			const Macro* macro = MacroTable::Instance().Get( macroName );
   12.92 +			if ( macro != NULL )
   12.93 +			{
   12.94 +				if ( GlobalData::Instance().ShouldOutputAsm() )
   12.95 +				{
   12.96 +					cout << "Macro " << macroName << ":" << endl;
   12.97 +				}
   12.98  
   12.99 -		string symbolName = GetSymbolName() + m_sourceFile->GetSymbolNameSuffix();
  12.100 +				HandleOpenBrace();
  12.101  
  12.102 -		if ( !AdvanceAndCheckEndOfStatement() )
  12.103 -		{
  12.104 -			throw AsmException_SyntaxError_UnrecognisedToken( m_line, oldColumn );
  12.105 -		}
  12.106 +				for ( int i = 0; i < macro->GetNumberOfParameters(); i++ )
  12.107 +				{
  12.108 +					string paramName = macro->GetParameter( i ) + m_sourceCode->GetSymbolNameSuffix();
  12.109  
  12.110 -		if ( m_line[ m_column ] != '=' )
  12.111 -		{
  12.112 -			throw AsmException_SyntaxError_UnrecognisedToken( m_line, oldColumn );
  12.113 -		}
  12.114 +					try
  12.115 +					{
  12.116 +						double value = EvaluateExpression();
  12.117  
  12.118 -		m_column++;
  12.119 +						if ( !SymbolTable::Instance().IsSymbolDefined( paramName ) )
  12.120 +						{
  12.121 +//							cout << "   (symbol '" << paramName << "' = " << value << ")" << endl;
  12.122 +							SymbolTable::Instance().AddSymbol( paramName, value );
  12.123 +						}
  12.124  
  12.125 -		double value = EvaluateExpression();
  12.126 +					}
  12.127 +					catch ( AsmException_SyntaxError_SymbolNotDefined& )
  12.128 +					{
  12.129 +//						cout << "   (symbol '" << paramName << "' not yet known)" << endl;
  12.130 +						if ( GlobalData::Instance().IsSecondPass() )
  12.131 +						{
  12.132 +							throw;
  12.133 +						}
  12.134 +					}
  12.135  
  12.136 -		if ( GlobalData::Instance().IsFirstPass() )
  12.137 -		{
  12.138 -			// only add the symbol on the first pass
  12.139 +					if ( i != macro->GetNumberOfParameters() - 1 )
  12.140 +					{
  12.141 +						if ( m_column >= m_line.length() || m_line[ m_column ] != ',' )
  12.142 +						{
  12.143 +							throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  12.144 +						}
  12.145  
  12.146 -			if ( SymbolTable::Instance().IsSymbolDefined( symbolName ) )
  12.147 -			{
  12.148 -				throw AsmException_SyntaxError_LabelAlreadyDefined( m_line, oldColumn );
  12.149 -			}
  12.150 -			else
  12.151 -			{
  12.152 -				SymbolTable::Instance().AddSymbol( symbolName, value );
  12.153 +						m_column++;
  12.154 +					}
  12.155 +				}
  12.156 +				
  12.157 +				if ( AdvanceAndCheckEndOfStatement() )
  12.158 +				{
  12.159 +					throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column );
  12.160 +				}
  12.161 +
  12.162 +				MacroInstance macroInstance( macro, m_sourceCode );
  12.163 +				macroInstance.Process();
  12.164 +
  12.165 +//				for ( int i = 0; i < macro->GetNumberOfLines(); i++ )
  12.166 +//				{
  12.167 +//					LineParser macroLine( m_sourceCode, macro->GetLine( i ) );
  12.168 +//					cout << "   macro: " << macro->GetLine( i ) << endl;
  12.169 +//					macroLine.Process();
  12.170 +//				}
  12.171 +
  12.172 +				HandleCloseBrace();
  12.173 +
  12.174 +				if ( GlobalData::Instance().ShouldOutputAsm() )
  12.175 +				{
  12.176 +					cout << "End macro " << macroName << endl;
  12.177 +				}
  12.178 +
  12.179 +				continue;
  12.180  			}
  12.181  		}
  12.182  
  12.183 -		if ( m_line[ m_column ] == ',' )
  12.184 -		{
  12.185 -			// Unexpected comma (remembering that an expression can validly end with a comma)
  12.186 -			throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
  12.187 -		}
  12.188 +		// If we got this far, we didn't recognise anything, so throw an error
  12.189  
  12.190 +		throw AsmException_SyntaxError_UnrecognisedToken( m_line, oldColumn );
  12.191  	}
  12.192  }
  12.193  
  12.194 @@ -214,11 +290,11 @@
  12.195  
  12.196  	int oldColumn = m_column;
  12.197  
  12.198 -	if ( m_line[ m_column ] == '{' || m_line[ m_column ] == '}' || m_line[ m_column ] == ':' )
  12.199 +	if ( m_column < m_line.length() && ( m_line[ m_column ] == '{' || m_line[ m_column ] == '}' || m_line[ m_column ] == ':' ) )
  12.200  	{
  12.201  		m_column++;
  12.202  	}
  12.203 -	else if ( m_line[ m_column ] == '\\' || m_line[ m_column ] == ';' )
  12.204 +	else if ( m_column < m_line.length() && ( m_line[ m_column ] == '\\' || m_line[ m_column ] == ';' ) )
  12.205  	{
  12.206  		m_column = m_line.length();
  12.207  	}
  12.208 @@ -226,17 +302,17 @@
  12.209  	{
  12.210  		while ( m_column < m_line.length() && ( bInQuotes || bInSingleQuotes || MoveToNextAtom( ":;\\{}" ) ) )
  12.211  		{
  12.212 -			if ( m_line[ m_column ] == '\"' && !bInSingleQuotes )
  12.213 +			if ( m_column < m_line.length() && m_line[ m_column ] == '\"' && !bInSingleQuotes )
  12.214  			{
  12.215  				bInQuotes = !bInQuotes;
  12.216  			}
  12.217 -			else if ( m_line[ m_column ] == '\'' )
  12.218 +			else if ( m_column < m_line.length() && m_line[ m_column ] == '\'' )
  12.219  			{
  12.220  				if ( bInSingleQuotes )
  12.221  				{
  12.222  					bInSingleQuotes = false;
  12.223  				}
  12.224 -				else if ( m_line[ m_column + 2 ] == '\'' && !bInQuotes )
  12.225 +				else if ( m_column + 2 < m_line.length() && m_line[ m_column + 2 ] == '\'' && !bInQuotes )
  12.226  				{
  12.227  					bInSingleQuotes = true;
  12.228  					m_column++;
  12.229 @@ -247,14 +323,20 @@
  12.230  		}
  12.231  	}
  12.232  
  12.233 -	if ( m_sourceFile->GetCurrentMacro() != NULL &&
  12.234 -		 m_line[ oldColumn ] != ':' &&
  12.235 -		 m_line[ oldColumn ] != '\\' &&
  12.236 -		 m_line[ oldColumn ] != ';' )
  12.237 +	if ( m_sourceCode->GetCurrentMacro() != NULL )//&&
  12.238 +//		 m_line[ oldColumn ] != ':' &&
  12.239 +//		 m_line[ oldColumn ] != '\\' &&
  12.240 +//		 m_line[ oldColumn ] != ';' )
  12.241  	{
  12.242  		string command = m_line.substr( oldColumn, m_column - oldColumn );
  12.243 -		m_sourceFile->GetCurrentMacro()->AddLine( command );
  12.244 -		cout << "   '" << command << "'" << endl;
  12.245 +
  12.246 +		if ( m_column == m_line.length() )
  12.247 +		{
  12.248 +			command += '\n';
  12.249 +		}
  12.250 +
  12.251 +		m_sourceCode->GetCurrentMacro()->AddLine( command );
  12.252 +//		cout << "   '" << command << "'" << endl;
  12.253  	}
  12.254  }
  12.255  
  12.256 @@ -309,10 +391,10 @@
  12.257  
  12.258  	if ( m_gaTokenTable[ i ].m_directiveHandler )
  12.259  	{
  12.260 -		( m_sourceFile->*m_gaTokenTable[ i ].m_directiveHandler )( m_line, m_column );
  12.261 +		( m_sourceCode->*m_gaTokenTable[ i ].m_directiveHandler )( m_line, m_column );
  12.262  	}
  12.263  
  12.264 -	if ( m_sourceFile->IsIfConditionTrue() )
  12.265 +	if ( m_sourceCode->IsIfConditionTrue() )
  12.266  	{
  12.267  		( this->*m_gaTokenTable[ i ].m_handler )();
  12.268  	}
  12.269 @@ -437,7 +519,8 @@
  12.270  	{
  12.271  		symbolName += m_line[ m_column++ ];
  12.272  
  12.273 -	} while ( ( isalpha( m_line[ m_column ] ) ||
  12.274 +	} while ( m_column < m_line.length() &&
  12.275 +			  ( isalpha( m_line[ m_column ] ) ||
  12.276  				isdigit( m_line[ m_column ] ) ||
  12.277  				m_line[ m_column ] == '_' ||
  12.278  				m_line[ m_column ] == '%' ) &&
    13.1 --- a/src/lineparser.h	Sun Mar 06 18:19:27 2011 +0100
    13.2 +++ b/src/lineparser.h	Mon Apr 25 01:14:59 2011 +0200
    13.3 @@ -25,7 +25,7 @@
    13.4  
    13.5  #include <string>
    13.6  
    13.7 -class SourceFile;
    13.8 +class SourceCode;
    13.9  
   13.10  class LineParser
   13.11  {
   13.12 @@ -33,7 +33,7 @@
   13.13  
   13.14  	// Constructor/destructor
   13.15  
   13.16 -	LineParser( SourceFile* sourceFile, std::string line );
   13.17 +	LineParser( SourceCode* sourceCode, std::string line );
   13.18  	~LineParser();
   13.19  
   13.20  	// Process the line
   13.21 @@ -46,7 +46,7 @@
   13.22  private:
   13.23  
   13.24  	typedef void ( LineParser::*TokenHandler )();
   13.25 -	typedef void ( SourceFile::*DirectiveHandler )( const std::string& line, int column );
   13.26 +	typedef void ( SourceCode::*DirectiveHandler )( const std::string& line, int column );
   13.27  
   13.28  	struct Token
   13.29  	{
   13.30 @@ -105,6 +105,7 @@
   13.31  	int				GetTokenAndAdvanceColumn();
   13.32  	void			HandleToken( int i, int oldColumn );
   13.33  	int				GetInstructionAndAdvanceColumn();
   13.34 +	int				CheckMacroMatches();
   13.35  	bool			MoveToNextAtom( const char* pTerminators = NULL );
   13.36  	bool			AdvanceAndCheckEndOfLine();
   13.37  	bool			AdvanceAndCheckEndOfStatement();
   13.38 @@ -201,7 +202,7 @@
   13.39  	void			EvalExp();
   13.40  
   13.41  
   13.42 -	SourceFile*				m_sourceFile;
   13.43 +	SourceCode*				m_sourceCode;
   13.44  	std::string				m_line;
   13.45  	size_t					m_column;
   13.46  
    14.1 --- a/src/macro.cpp	Sun Mar 06 18:19:27 2011 +0100
    14.2 +++ b/src/macro.cpp	Mon Apr 25 01:14:59 2011 +0200
    14.3 @@ -34,6 +34,104 @@
    14.4  
    14.5  /*************************************************************************************************/
    14.6  /**
    14.7 +	Macro::Macro()
    14.8 +
    14.9 +	Constructor for Macro
   14.10 +
   14.11 +	@param		pFilename		Filename of source file which contains the macro
   14.12 +	@param		lineNumber		Start line number of the macro in the file
   14.13 +*/
   14.14 +/*************************************************************************************************/
   14.15 +Macro::Macro( const string& filename, int lineNumber )
   14.16 +	:	m_filename( filename ),
   14.17 +		m_lineNumber( lineNumber )
   14.18 +{
   14.19 +}
   14.20 +
   14.21 +
   14.22 +
   14.23 +/*************************************************************************************************/
   14.24 +/**
   14.25 +	MacroInstance::MacroInstance()
   14.26 +
   14.27 +	Constructor for MacroInstance
   14.28 +
   14.29 +	@param		macro			Macro definition to instance
   14.30 +*/
   14.31 +/*************************************************************************************************/
   14.32 +MacroInstance::MacroInstance( const Macro* macro, const SourceCode* sourceCode )
   14.33 +	:	SourceCode( macro->GetFilename(), macro->GetLineNumber() ),
   14.34 +		m_stream( macro->GetBody() ),
   14.35 +		m_macro( macro )
   14.36 +{
   14.37 +//	cout << "Instance macro: " << m_macro->GetName() << " (" << m_filename << ":" << m_lineNumber << ")" << endl;
   14.38 +
   14.39 +	// Copy FOR stack from the parent
   14.40 +
   14.41 +	CopyForStack( sourceCode );
   14.42 +}
   14.43 +
   14.44 +
   14.45 +
   14.46 +/*************************************************************************************************/
   14.47 +/**
   14.48 +	MacroInstance::GetLine()
   14.49 +
   14.50 +	Reads a line from the source code and returns it into lineFromFile
   14.51 +*/
   14.52 +/*************************************************************************************************/
   14.53 +istream& MacroInstance::GetLine( string& lineFromFile ) 
   14.54 +{
   14.55 +	return getline( m_stream, lineFromFile );
   14.56 +}
   14.57 +
   14.58 +
   14.59 +
   14.60 +/*************************************************************************************************/
   14.61 +/**
   14.62 +	MacroInstance::GetFilePointer()
   14.63 +
   14.64 +	Returns the current file pointer
   14.65 +*/
   14.66 +/*************************************************************************************************/
   14.67 +int MacroInstance::GetFilePointer()
   14.68 +{
   14.69 +	return static_cast< int >( m_stream.tellg() );
   14.70 +}
   14.71 +
   14.72 +
   14.73 +
   14.74 +/*************************************************************************************************/
   14.75 +/**
   14.76 +	MacroInstance::SetFilePointer()
   14.77 +
   14.78 +	Sets the current file pointer
   14.79 +*/
   14.80 +/*************************************************************************************************/
   14.81 +void MacroInstance::SetFilePointer( int i )
   14.82 +{
   14.83 +	m_lineStartPointer = i;
   14.84 +	m_stream.seekg( i );
   14.85 +}
   14.86 +
   14.87 +
   14.88 +
   14.89 +/*************************************************************************************************/
   14.90 +/**
   14.91 +	MacroInstance::IsAtEnd()
   14.92 +
   14.93 +	Returns whether the current stream is in an end-of-file state
   14.94 +*/
   14.95 +/*************************************************************************************************/
   14.96 +bool MacroInstance::IsAtEnd()
   14.97 +{
   14.98 +	return m_stream.eof();
   14.99 +}
  14.100 +
  14.101 +
  14.102 +
  14.103 +/*************************************************************************************************/
  14.104 +/**
  14.105  	MacroTable::Create()
  14.106  
  14.107  	Creates the MacroTable singleton
    15.1 --- a/src/macro.h	Sun Mar 06 18:19:27 2011 +0100
    15.2 +++ b/src/macro.h	Mon Apr 25 01:14:59 2011 +0200
    15.3 @@ -27,13 +27,18 @@
    15.4  #include <cstdlib>
    15.5  #include <map>
    15.6  #include <string>
    15.7 +#include <sstream>
    15.8  #include <vector>
    15.9 +#include "sourcecode.h"
   15.10  
   15.11  
   15.12  class Macro
   15.13  {
   15.14  public:
   15.15  
   15.16 +	Macro( const std::string& filename, int lineNumber );
   15.17 +
   15.18 +
   15.19  	void SetName( const std::string& name )
   15.20  	{
   15.21  		m_name = name;
   15.22 @@ -46,7 +51,7 @@
   15.23  
   15.24  	void AddLine( const std::string& line )
   15.25  	{
   15.26 -		m_content.push_back( line );
   15.27 +		m_body += line;
   15.28  	}
   15.29  
   15.30  	const std::string& GetName() const
   15.31 @@ -64,12 +69,53 @@
   15.32  		return m_parameters[ i ];
   15.33  	}
   15.34  
   15.35 +	const std::string& GetBody() const
   15.36 +	{
   15.37 +		return m_body;
   15.38 +	}
   15.39 +
   15.40 +	const std::string& GetFilename() const
   15.41 +	{
   15.42 +		return m_filename;
   15.43 +	}
   15.44 +
   15.45 +	int GetLineNumber() const
   15.46 +	{
   15.47 +		return m_lineNumber;
   15.48 +	}
   15.49 +
   15.50  
   15.51  private:
   15.52  
   15.53 +	std::string						m_filename;
   15.54 +	int								m_lineNumber;
   15.55 +
   15.56  	std::string						m_name;
   15.57  	std::vector< std::string >		m_parameters;
   15.58 -	std::vector< std::string >		m_content;
   15.59 +	std::string						m_body;
   15.60 +
   15.61 +};
   15.62 +
   15.63 +
   15.64 +class MacroInstance : public SourceCode
   15.65 +{
   15.66 +public:
   15.67 +
   15.68 +	MacroInstance( const Macro* macro, const SourceCode* parent );
   15.69 +	virtual ~MacroInstance() {}
   15.70 +
   15.71 +	// Accessors
   15.72 +
   15.73 +	virtual int						GetFilePointer();
   15.74 +	virtual void					SetFilePointer( int i );
   15.75 +	virtual std::istream&			GetLine( std::string& lineFromFile );
   15.76 +	virtual bool					IsAtEnd();
   15.77 +
   15.78 +
   15.79 +private:
   15.80 +
   15.81 +	std::istringstream				m_stream;
   15.82 +	const Macro*					m_macro;
   15.83  };
   15.84  
   15.85  
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/sourcecode.cpp	Mon Apr 25 01:14:59 2011 +0200
    16.3 @@ -0,0 +1,514 @@
    16.4 +/*************************************************************************************************/
    16.5 +/**
    16.6 +	sourcecode.cpp
    16.7 +
    16.8 +	Represents a piece of source code, whether from a file, or a macro definition.
    16.9 +
   16.10 +
   16.11 +	Copyright (C) Rich Talbot-Watkins 2007, 2008
   16.12 +
   16.13 +	This file is part of BeebAsm.
   16.14 +
   16.15 +	BeebAsm is free software: you can redistribute it and/or modify it under the terms of the GNU
   16.16 +	General Public License as published by the Free Software Foundation, either version 3 of the
   16.17 +	License, or (at your option) any later version.
   16.18 +
   16.19 +	BeebAsm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
   16.20 +	even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.21 +	GNU General Public License for more details.
   16.22 +
   16.23 +	You should have received a copy of the GNU General Public License along with BeebAsm, as
   16.24 +	COPYING.txt.  If not, see <http://www.gnu.org/licenses/>.
   16.25 +*/
   16.26 +/*************************************************************************************************/
   16.27 +
   16.28 +#include <iostream>
   16.29 +#include <iomanip>
   16.30 +#include <sstream>
   16.31 +
   16.32 +#include "sourcecode.h"
   16.33 +#include "asmexception.h"
   16.34 +#include "stringutils.h"
   16.35 +#include "globaldata.h"
   16.36 +#include "lineparser.h"
   16.37 +#include "symboltable.h"
   16.38 +#include "macro.h"
   16.39 +
   16.40 +using namespace std;
   16.41 +
   16.42 +
   16.43 +
   16.44 +/*************************************************************************************************/
   16.45 +/**
   16.46 +	SourceCode::SourceCode()
   16.47 +
   16.48 +	Constructor for SourceCode
   16.49 +
   16.50 +	@param		pFilename		Filename of source file to open
   16.51 +
   16.52 +	The supplied file will be opened.  If there is a problem, an AsmException will be thrown.
   16.53 +*/
   16.54 +/*************************************************************************************************/
   16.55 +SourceCode::SourceCode( const string& filename, int lineNumber )
   16.56 +	:	m_forStackPtr( 0 ),
   16.57 +		m_ifStackPtr( 0 ),
   16.58 +		m_currentMacro( NULL ),
   16.59 +		m_filename( filename ),
   16.60 +		m_lineNumber( lineNumber ),
   16.61 +		m_lineStartPointer( 0 )
   16.62 +{
   16.63 +}
   16.64 +
   16.65 +
   16.66 +
   16.67 +/*************************************************************************************************/
   16.68 +/**
   16.69 +	SourceCode::~SourceCode()
   16.70 +
   16.71 +	Destructor for SourceCode
   16.72 +
   16.73 +	The associated source file will be closed.
   16.74 +*/
   16.75 +/*************************************************************************************************/
   16.76 +SourceCode::~SourceCode()
   16.77 +{
   16.78 +}
   16.79 +
   16.80 +
   16.81 +
   16.82 +/*************************************************************************************************/
   16.83 +/**
   16.84 +	SourceCode::Process()
   16.85 +
   16.86 +	Process the associated source file
   16.87 +*/
   16.88 +/*************************************************************************************************/
   16.89 +void SourceCode::Process()
   16.90 +{
   16.91 +	// Remember the FOR and IF stack initial pointer values
   16.92 +
   16.93 +	int initialForStackPtr = m_forStackPtr;
   16.94 +	int initialIfStackPtr = m_ifStackPtr;
   16.95 +
   16.96 +	// Iterate through the file line-by-line
   16.97 +
   16.98 +	string lineFromFile;
   16.99 +
  16.100 +//	while ( getline( m_file, lineFromFile ) )
  16.101 +	while ( GetLine( lineFromFile ) )
  16.102 +	{
  16.103 +		// Convert tabs to spaces
  16.104 +
  16.105 +		StringUtils::ExpandTabsToSpaces( lineFromFile, 8 );
  16.106 +
  16.107 +//		// Display and process
  16.108 +//
  16.109 +//		if ( GlobalData::Instance().IsFirstPass() )
  16.110 +//		{
  16.111 +//			cout << setw( 5 ) << m_lineNumber << ": " << lineFromFile << endl;
  16.112 +//		}
  16.113 +
  16.114 +		try
  16.115 +		{
  16.116 +			LineParser thisLine( this, lineFromFile );
  16.117 +			thisLine.Process();
  16.118 +		}
  16.119 +		catch ( AsmException_SyntaxError& e )
  16.120 +		{
  16.121 +			// Augment exception with more details
  16.122 +			e.SetFilename( m_filename );
  16.123 +			e.SetLineNumber( m_lineNumber );
  16.124 +			throw;
  16.125 +		}
  16.126 +
  16.127 +		m_lineNumber++;
  16.128 +		m_lineStartPointer = GetFilePointer();
  16.129 +	}
  16.130 +
  16.131 +	// Check whether we aborted prematurely
  16.132 +
  16.133 +	if ( !IsAtEnd() )
  16.134 +	{
  16.135 +		throw AsmException_FileError_ReadSourceFile( m_filename );
  16.136 +	}
  16.137 +
  16.138 +	// Check that we have no FOR / braces mismatch
  16.139 +
  16.140 +	if ( m_forStackPtr > initialForStackPtr )
  16.141 +	{
  16.142 +		For& mismatchedFor = m_forStack[ m_forStackPtr - 1 ];
  16.143 +
  16.144 +		if ( mismatchedFor.m_step == 0.0 )
  16.145 +		{
  16.146 +			AsmException_SyntaxError_MismatchedBraces e( mismatchedFor.m_line, mismatchedFor.m_column );
  16.147 +			e.SetFilename( m_filename );
  16.148 +			e.SetLineNumber( mismatchedFor.m_lineNumber );
  16.149 +			throw e;
  16.150 +		}
  16.151 +		else
  16.152 +		{
  16.153 +			AsmException_SyntaxError_ForWithoutNext e( mismatchedFor.m_line, mismatchedFor.m_column );
  16.154 +			e.SetFilename( m_filename );
  16.155 +			e.SetLineNumber( mismatchedFor.m_lineNumber );
  16.156 +			throw e;
  16.157 +		}
  16.158 +	}
  16.159 +
  16.160 +	// Check that we have no IF mismatch
  16.161 +
  16.162 +	if ( m_ifStackPtr > initialIfStackPtr )
  16.163 +	{
  16.164 +		If& mismatchedIf = m_ifStack[ m_ifStackPtr - 1 ];
  16.165 +
  16.166 +		AsmException_SyntaxError_IfWithoutEndif e( mismatchedIf.m_line, mismatchedIf.m_column );
  16.167 +		e.SetFilename( m_filename );
  16.168 +		e.SetLineNumber( mismatchedIf.m_lineNumber );
  16.169 +		throw e;
  16.170 +	}
  16.171 +}
  16.172 +
  16.173 +
  16.174 +
  16.175 +/*************************************************************************************************/
  16.176 +/**
  16.177 +	SourceCode::AddFor()
  16.178 +*/
  16.179 +/*************************************************************************************************/
  16.180 +void SourceCode::AddFor( const string& varName,
  16.181 +						 double start,
  16.182 +						 double end,
  16.183 +						 double step,
  16.184 +						 int filePtr,
  16.185 +						 const string& line,
  16.186 +						 int column )
  16.187 +{
  16.188 +	if ( m_forStackPtr == MAX_FOR_LEVELS )
  16.189 +	{
  16.190 +		throw AsmException_SyntaxError_TooManyFORs( line, column );
  16.191 +	}
  16.192 +
  16.193 +	// Add symbol to table
  16.194 +
  16.195 +	SymbolTable::Instance().AddSymbol( varName, start );
  16.196 +
  16.197 +	// Fill in FOR block
  16.198 +
  16.199 +	m_forStack[ m_forStackPtr ].m_varName		= varName;
  16.200 +	m_forStack[ m_forStackPtr ].m_current		= start;
  16.201 +	m_forStack[ m_forStackPtr ].m_end			= end;
  16.202 +	m_forStack[ m_forStackPtr ].m_step			= step;
  16.203 +	m_forStack[ m_forStackPtr ].m_filePtr		= filePtr;
  16.204 +	m_forStack[ m_forStackPtr ].m_id			= GlobalData::Instance().GetNextForId();
  16.205 +	m_forStack[ m_forStackPtr ].m_count			= 0;
  16.206 +	m_forStack[ m_forStackPtr ].m_line			= line;
  16.207 +	m_forStack[ m_forStackPtr ].m_column		= column;
  16.208 +	m_forStack[ m_forStackPtr ].m_lineNumber	= m_lineNumber;
  16.209 +
  16.210 +	m_forStackPtr++;
  16.211 +}
  16.212 +
  16.213 +
  16.214 +
  16.215 +/*************************************************************************************************/
  16.216 +/**
  16.217 +	SourceCode::OpenBrace()
  16.218 +
  16.219 +	Braces for scoping variables are just FORs in disguise...
  16.220 +*/
  16.221 +/*************************************************************************************************/
  16.222 +void SourceCode::OpenBrace( const string& line, int column )
  16.223 +{
  16.224 +	if ( m_forStackPtr == MAX_FOR_LEVELS )
  16.225 +	{
  16.226 +		throw AsmException_SyntaxError_TooManyFORs( line, column );
  16.227 +	}
  16.228 +
  16.229 +	// Fill in FOR block
  16.230 +
  16.231 +	m_forStack[ m_forStackPtr ].m_varName		= "";
  16.232 +	m_forStack[ m_forStackPtr ].m_current		= 1.0;
  16.233 +	m_forStack[ m_forStackPtr ].m_end			= 0.0;
  16.234 +	m_forStack[ m_forStackPtr ].m_step			= 0.0;
  16.235 +	m_forStack[ m_forStackPtr ].m_filePtr		= 0;
  16.236 +	m_forStack[ m_forStackPtr ].m_id			= GlobalData::Instance().GetNextForId();
  16.237 +	m_forStack[ m_forStackPtr ].m_count			= 0;
  16.238 +	m_forStack[ m_forStackPtr ].m_line			= line;
  16.239 +	m_forStack[ m_forStackPtr ].m_column		= column;
  16.240 +	m_forStack[ m_forStackPtr ].m_lineNumber	= m_lineNumber;
  16.241 +
  16.242 +	m_forStackPtr++;
  16.243 +}
  16.244 +
  16.245 +
  16.246 +
  16.247 +/*************************************************************************************************/
  16.248 +/**
  16.249 +	SourceCode::UpdateFor()
  16.250 +*/
  16.251 +/*************************************************************************************************/
  16.252 +void SourceCode::UpdateFor( const string& line, int column )
  16.253 +{
  16.254 +	if ( m_forStackPtr == 0 )
  16.255 +	{
  16.256 +		throw AsmException_SyntaxError_NextWithoutFor( line, column );
  16.257 +	}
  16.258 +
  16.259 +	For& thisFor = m_forStack[ m_forStackPtr - 1 ];
  16.260 +
  16.261 +	// step of 0.0 here means that the 'for' is in fact an open brace, so throw an error
  16.262 +
  16.263 +	if ( thisFor.m_step == 0.0 )
  16.264 +	{
  16.265 +		throw AsmException_SyntaxError_NextWithoutFor( line, column );
  16.266 +	}
  16.267 +
  16.268 +	thisFor.m_current += thisFor.m_step;
  16.269 +
  16.270 +	if ( ( thisFor.m_step > 0.0 && thisFor.m_current > thisFor.m_end ) ||
  16.271 +		 ( thisFor.m_step < 0.0 && thisFor.m_current < thisFor.m_end ) )
  16.272 +	{
  16.273 +		// we have reached the end of the FOR
  16.274 +		SymbolTable::Instance().RemoveSymbol( thisFor.m_varName );
  16.275 +		m_forStackPtr--;
  16.276 +	}
  16.277 +	else
  16.278 +	{
  16.279 +		// reloop
  16.280 +		SymbolTable::Instance().ChangeSymbol( thisFor.m_varName, thisFor.m_current );
  16.281 +		SetFilePointer( thisFor.m_filePtr );
  16.282 +		thisFor.m_count++;
  16.283 +		m_lineNumber = thisFor.m_lineNumber - 1;
  16.284 +	}
  16.285 +}
  16.286 +
  16.287 +
  16.288 +
  16.289 +/*************************************************************************************************/
  16.290 +/**
  16.291 +	SourceCode::CloseBrace()
  16.292 +
  16.293 +	Braces for scoping variables are just FORs in disguise...
  16.294 +*/
  16.295 +/*************************************************************************************************/
  16.296 +void SourceCode::CloseBrace( const string& line, int column )
  16.297 +{
  16.298 +	if ( m_forStackPtr == 0 )
  16.299 +	{
  16.300 +		throw AsmException_SyntaxError_MismatchedBraces( line, column );
  16.301 +	}
  16.302 +
  16.303 +	For& thisFor = m_forStack[ m_forStackPtr - 1 ];
  16.304 +
  16.305 +	// step of non-0.0 here means that this a real 'for', so throw an error
  16.306 +
  16.307 +	if ( thisFor.m_step != 0.0 )
  16.308 +	{
  16.309 +		throw AsmException_SyntaxError_MismatchedBraces( line, column );
  16.310 +	}
  16.311 +
  16.312 +	m_forStackPtr--;
  16.313 +}
  16.314 +
  16.315 +
  16.316 +/*************************************************************************************************/
  16.317 +/**
  16.318 +	SourceCode::CopyForStack()
  16.319 +*/
  16.320 +/*************************************************************************************************/
  16.321 +void SourceCode::CopyForStack( const SourceCode* copyFrom )
  16.322 +{
  16.323 +	m_forStackPtr = copyFrom->m_forStackPtr;
  16.324 +
  16.325 +	for ( int i = 0; i < m_forStackPtr; i++ )
  16.326 +	{
  16.327 +		m_forStack[ i ] = copyFrom->m_forStack[ i ];
  16.328 +	}
  16.329 +}
  16.330 +
  16.331 +
  16.332 +/*************************************************************************************************/
  16.333 +/**
  16.334 +	SourceCode::GetSymbolNameSuffix()
  16.335 +*/
  16.336 +/*************************************************************************************************/
  16.337 +string SourceCode::GetSymbolNameSuffix( int level ) const
  16.338 +{
  16.339 +	if ( level == -1 )
  16.340 +	{
  16.341 +		level = m_forStackPtr;
  16.342 +	}
  16.343 +
  16.344 +	ostringstream suffix;
  16.345 +
  16.346 +	for ( int i = 0; i < level; i++ )
  16.347 +	{
  16.348 +		suffix << "@";
  16.349 +		suffix << m_forStack[ i ].m_id;
  16.350 +		suffix << "_";
  16.351 +		suffix << m_forStack[ i ].m_count;
  16.352 +	}
  16.353 +
  16.354 +	return suffix.str();
  16.355 +}
  16.356 +
  16.357 +
  16.358 +
  16.359 +/*************************************************************************************************/
  16.360 +/**
  16.361 +	SourceCode::IsIfConditionTrue()
  16.362 +*/
  16.363 +/*************************************************************************************************/
  16.364 +bool SourceCode::IsIfConditionTrue() const
  16.365 +{
  16.366 +	for ( int i = 0; i < m_ifStackPtr; i++ )
  16.367 +	{
  16.368 +		if ( !m_ifStack[ i ].m_condition )
  16.369 +		{
  16.370 +			return false;
  16.371 +		}
  16.372 +	}
  16.373 +
  16.374 +	return true;
  16.375 +}
  16.376 +
  16.377 +
  16.378 +
  16.379 +/*************************************************************************************************/
  16.380 +/**
  16.381 +	SourceCode::AddIfLevel()
  16.382 +*/
  16.383 +/*************************************************************************************************/
  16.384 +void SourceCode::AddIfLevel( const string& line, int column )
  16.385 +{
  16.386 +	if ( m_ifStackPtr == MAX_IF_LEVELS )
  16.387 +	{
  16.388 +		throw AsmException_SyntaxError_TooManyIFs( line, column );
  16.389 +	}
  16.390 +
  16.391 +	m_ifStack[ m_ifStackPtr ].m_condition	= true;
  16.392 +	m_ifStack[ m_ifStackPtr ].m_passed		= false;
  16.393 +	m_ifStack[ m_ifStackPtr ].m_hadElse		= false;
  16.394 +	m_ifStack[ m_ifStackPtr ].m_line		= line;
  16.395 +	m_ifStack[ m_ifStackPtr ].m_column		= column;
  16.396 +	m_ifStack[ m_ifStackPtr ].m_lineNumber	= m_lineNumber;
  16.397 +	m_ifStackPtr++;
  16.398 +}
  16.399 +
  16.400 +
  16.401 +
  16.402 +/*************************************************************************************************/
  16.403 +/**
  16.404 +	SourceCode::SetCurrentIfCondition()
  16.405 +*/
  16.406 +/*************************************************************************************************/
  16.407 +void SourceCode::SetCurrentIfCondition( bool b )
  16.408 +{
  16.409 +	assert( m_ifStackPtr > 0 );
  16.410 +	m_ifStack[ m_ifStackPtr - 1 ].m_condition = b;
  16.411 +	if ( b )
  16.412 +	{
  16.413 +		m_ifStack[ m_ifStackPtr - 1 ].m_passed = true;
  16.414 +	}
  16.415 +}
  16.416 +
  16.417 +
  16.418 +
  16.419 +/*************************************************************************************************/
  16.420 +/**
  16.421 +	SourceCode::StartElse()
  16.422 +*/
  16.423 +/*************************************************************************************************/
  16.424 +void SourceCode::StartElse( const string& line, int column )
  16.425 +{
  16.426 +	if ( m_ifStack[ m_ifStackPtr - 1 ].m_hadElse )
  16.427 +	{
  16.428 +		throw AsmException_SyntaxError_ElseWithoutIf( line, column );
  16.429 +	}
  16.430 +
  16.431 +	m_ifStack[ m_ifStackPtr - 1 ].m_hadElse = true;
  16.432 +
  16.433 +	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_passed;
  16.434 +}
  16.435 +
  16.436 +
  16.437 +
  16.438 +/*************************************************************************************************/
  16.439 +/**
  16.440 +	SourceCode::StartElif()
  16.441 +*/
  16.442 +/*************************************************************************************************/
  16.443 +void SourceCode::StartElif( const string& line, int column )
  16.444 +{
  16.445 +	if ( m_ifStack[ m_ifStackPtr - 1 ].m_hadElse )
  16.446 +	{
  16.447 +		throw AsmException_SyntaxError_ElifWithoutIf( line, column );
  16.448 +	}
  16.449 +
  16.450 +	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_passed;
  16.451 +}
  16.452 +
  16.453 +
  16.454 +
  16.455 +/*************************************************************************************************/
  16.456 +/**
  16.457 +	SourceCode::RemoveIfLevel()
  16.458 +*/
  16.459 +/*************************************************************************************************/
  16.460 +void SourceCode::RemoveIfLevel( const string& line, int column )
  16.461 +{
  16.462 +	if ( m_ifStackPtr == 0 )
  16.463 +	{
  16.464 +		throw AsmException_SyntaxError_EndifWithoutIf( line, column );
  16.465 +	}
  16.466 +
  16.467 +	m_ifStackPtr--;
  16.468 +}
  16.469 +
  16.470 +
  16.471 +
  16.472 +/*************************************************************************************************/
  16.473 +/**
  16.474 +	SourceCode::StartMacro()
  16.475 +*/
  16.476 +/*************************************************************************************************/
  16.477 +void SourceCode::StartMacro( const string& line, int column )
  16.478 +{
  16.479 +	if ( GlobalData::Instance().IsFirstPass() )
  16.480 +	{
  16.481 +		if ( m_currentMacro == NULL )
  16.482 +		{
  16.483 +			m_currentMacro = new Macro( m_filename, m_lineNumber );
  16.484 +		}
  16.485 +		else
  16.486 +		{
  16.487 +			throw AsmException_SyntaxError_NoNestedMacros( line, column );
  16.488 +		}
  16.489 +	}
  16.490 +
  16.491 +	AddIfLevel( line, column );
  16.492 +}
  16.493 +
  16.494 +
  16.495 +
  16.496 +/*************************************************************************************************/
  16.497 +/**
  16.498 +	SourceCode::EndMacro()
  16.499 +*/
  16.500 +/*************************************************************************************************/
  16.501 +void SourceCode::EndMacro( const string& line, int column )
  16.502 +{
  16.503 +	if ( GlobalData::Instance().IsFirstPass() &&
  16.504 +		 m_currentMacro == NULL )
  16.505 +	{
  16.506 +		throw AsmException_SyntaxError_EndMacroUnexpected( line, column - 8 );
  16.507 +	}
  16.508 +
  16.509 +	RemoveIfLevel( line, column );
  16.510 +
  16.511 +	if ( GlobalData::Instance().IsFirstPass() )
  16.512 +	{
  16.513 +//		cout << "Macro: '" << m_currentMacro->GetBody() << "'" << endl;
  16.514 +		MacroTable::Instance().Add( m_currentMacro );
  16.515 +		m_currentMacro = NULL;
  16.516 +	}
  16.517 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/sourcecode.h	Mon Apr 25 01:14:59 2011 +0200
    17.3 @@ -0,0 +1,138 @@
    17.4 +/*************************************************************************************************/
    17.5 +/**
    17.6 +	sourcecode.h
    17.7 +
    17.8 +
    17.9 +	Copyright (C) Rich Talbot-Watkins 2007, 2008
   17.10 +
   17.11 +	This file is part of BeebAsm.
   17.12 +
   17.13 +	BeebAsm is free software: you can redistribute it and/or modify it under the terms of the GNU
   17.14 +	General Public License as published by the Free Software Foundation, either version 3 of the
   17.15 +	License, or (at your option) any later version.
   17.16 +
   17.17 +	BeebAsm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
   17.18 +	even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.19 +	GNU General Public License for more details.
   17.20 +
   17.21 +	You should have received a copy of the GNU General Public License along with BeebAsm, as
   17.22 +	COPYING.txt.  If not, see <http://www.gnu.org/licenses/>.
   17.23 +*/
   17.24 +/*************************************************************************************************/
   17.25 +
   17.26 +#ifndef SOURCECODE_H_
   17.27 +#define SOURCECODE_H_
   17.28 +
   17.29 +#include <fstream>
   17.30 +#include <string>
   17.31 +#include <vector>
   17.32 +
   17.33 +class Macro;
   17.34 +
   17.35 +class SourceCode
   17.36 +{
   17.37 +public:
   17.38 +
   17.39 +	// Constructor/destructor
   17.40 +
   17.41 +	SourceCode( const std::string& filename, int lineNumber );
   17.42 +	~SourceCode();
   17.43 +
   17.44 +	// Process the file
   17.45 +
   17.46 +	virtual void Process();
   17.47 +
   17.48 +	// Accessors
   17.49 +
   17.50 +	inline const std::string&	GetFilename() const				{ return m_filename; }
   17.51 +	inline int				GetLineNumber() const			{ return m_lineNumber; }
   17.52 +	inline int				GetLineStartPointer() const		{ return m_lineStartPointer; }
   17.53 +
   17.54 +	virtual std::istream&	GetLine( std::string& lineFromFile ) = 0;
   17.55 +	virtual int				GetFilePointer() = 0;
   17.56 +	virtual void			SetFilePointer( int i ) = 0;
   17.57 +	virtual bool			IsAtEnd() = 0;
   17.58 +
   17.59 +
   17.60 +	// For loop / if related stuff
   17.61 +
   17.62 +	#define MAX_FOR_LEVELS	32
   17.63 +	#define MAX_IF_LEVELS	32
   17.64 +
   17.65 +protected:
   17.66 +
   17.67 +	struct For
   17.68 +	{
   17.69 +		std::string			m_varName;
   17.70 +		double				m_current;
   17.71 +		double				m_end;
   17.72 +		double				m_step;
   17.73 +		int					m_filePtr;
   17.74 +		int					m_id;
   17.75 +		int					m_count;
   17.76 +		std::string			m_line;
   17.77 +		int					m_column;
   17.78 +		int					m_lineNumber;
   17.79 +	};
   17.80 +
   17.81 +	For						m_forStack[ MAX_FOR_LEVELS ];
   17.82 +	int						m_forStackPtr;
   17.83 +
   17.84 +	struct If
   17.85 +	{
   17.86 +		bool				m_condition;
   17.87 +		bool                m_hadElse;
   17.88 +		bool				m_passed;
   17.89 +		std::string			m_line;
   17.90 +		int					m_column;
   17.91 +		int					m_lineNumber;
   17.92 +	};
   17.93 +
   17.94 +	int						m_ifStackPtr;
   17.95 +	If						m_ifStack[ MAX_IF_LEVELS ];
   17.96 +
   17.97 +	Macro*					m_currentMacro;
   17.98 +
   17.99 +
  17.100 +public:
  17.101 +
  17.102 +	void					OpenBrace( const std::string& line, int column );
  17.103 +	void					CloseBrace( const std::string& line, int column );
  17.104 +
  17.105 +	void					AddFor( const std::string& varName,
  17.106 +									double start,
  17.107 +									double end,
  17.108 +									double step,
  17.109 +									int filePtr,
  17.110 +									const std::string& line,
  17.111 +									int column );
  17.112 +
  17.113 +	void					UpdateFor( const std::string& line, int column );
  17.114 +
  17.115 +	void					CopyForStack( const SourceCode* copyFrom );
  17.116 +
  17.117 +	inline int 				GetForLevel() const { return m_forStackPtr; }
  17.118 +	inline Macro*			GetCurrentMacro() { return m_currentMacro; }
  17.119 +
  17.120 +	std::string				GetSymbolNameSuffix( int level = -1 ) const;
  17.121 +
  17.122 +	bool					IsIfConditionTrue() const;
  17.123 +	void					AddIfLevel( const std::string& line, int column );
  17.124 +	void					SetCurrentIfCondition( bool b );
  17.125 +	void					StartElse( const std::string& line, int column );
  17.126 +	void					StartElif( const std::string& line, int column );
  17.127 +	void					ToggleCurrentIfCondition( const std::string& line, int column );
  17.128 +	void					RemoveIfLevel( const std::string& line, int column );
  17.129 +	void					StartMacro( const std::string& line, int column );
  17.130 +	void					EndMacro( const std::string& line, int column );
  17.131 +
  17.132 +
  17.133 +protected:
  17.134 +
  17.135 +	std::string				m_filename;
  17.136 +	int						m_lineNumber;
  17.137 +	int						m_lineStartPointer;
  17.138 +};
  17.139 +
  17.140 +
  17.141 +#endif // SOURCECODE_H_
    18.1 --- a/src/sourcefile.cpp	Sun Mar 06 18:19:27 2011 +0100
    18.2 +++ b/src/sourcefile.cpp	Mon Apr 25 01:14:59 2011 +0200
    18.3 @@ -49,20 +49,17 @@
    18.4  	The supplied file will be opened.  If there is a problem, an AsmException will be thrown.
    18.5  */
    18.6  /*************************************************************************************************/
    18.7 -SourceFile::SourceFile( const char* pFilename )
    18.8 -	:	m_currentMacro( NULL ),
    18.9 -		m_pFilename( pFilename ),
   18.10 -		m_lineNumber( 1 ),
   18.11 -		m_filePointer( 0 )
   18.12 +SourceFile::SourceFile( const string& filename )
   18.13 +	:	SourceCode( filename, 1 )
   18.14  {
   18.15  	// we have to open in binary, due to a bug in MinGW which means that calling
   18.16  	// tellg() on a text-mode file ruins the file pointer!
   18.17  	// http://www.mingw.org/MinGWiki/index.php/Known%20Problems
   18.18 -	m_file.open( pFilename, ios_base::binary );
   18.19 +	m_file.open( filename.c_str(), ios_base::binary );
   18.20  
   18.21  	if ( !m_file )
   18.22  	{
   18.23 -		throw AsmException_FileError_OpenSourceFile( pFilename );
   18.24 +		throw AsmException_FileError_OpenSourceFile( filename );
   18.25  	}
   18.26  }
   18.27  
   18.28 @@ -83,7 +80,6 @@
   18.29  }
   18.30  
   18.31  
   18.32 -
   18.33  /*************************************************************************************************/
   18.34  /**
   18.35  	SourceFile::Process()
   18.36 @@ -93,94 +89,13 @@
   18.37  /*************************************************************************************************/
   18.38  void SourceFile::Process()
   18.39  {
   18.40 -	// Initialise for stack
   18.41 -
   18.42 -	m_forStackPtr = 0;
   18.43 -
   18.44 -	// Initialise if
   18.45 -
   18.46 -	m_ifStackPtr = 0;
   18.47 -
   18.48 -	// Iterate through the file line-by-line
   18.49 -
   18.50 -	string lineFromFile;
   18.51 -
   18.52 -	while ( getline( m_file, lineFromFile ) )
   18.53 -	{
   18.54 -		// Convert tabs to spaces
   18.55 -
   18.56 -		StringUtils::ExpandTabsToSpaces( lineFromFile, 8 );
   18.57 -
   18.58 -//		// Display and process
   18.59 -//
   18.60 -//		if ( GlobalData::Instance().IsFirstPass() )
   18.61 -//		{
   18.62 -//			cout << setw( 5 ) << m_lineNumber << ": " << lineFromFile << endl;
   18.63 -//		}
   18.64 -
   18.65 -		try
   18.66 -		{
   18.67 -			LineParser thisLine( this, lineFromFile );
   18.68 -			thisLine.Process();
   18.69 -		}
   18.70 -		catch ( AsmException_SyntaxError& e )
   18.71 -		{
   18.72 -			// Augment exception with more details
   18.73 -			e.SetFilename( m_pFilename );
   18.74 -			e.SetLineNumber( m_lineNumber );
   18.75 -			throw;
   18.76 -		}
   18.77 -
   18.78 -		m_lineNumber++;
   18.79 -		m_filePointer = static_cast< int >( m_file.tellg() );
   18.80 -	}
   18.81 -
   18.82 -	// Check whether we aborted prematurely
   18.83 -
   18.84 -	if ( !m_file.eof() )
   18.85 -	{
   18.86 -		throw AsmException_FileError_ReadSourceFile( m_pFilename );
   18.87 -	}
   18.88 -
   18.89 -	// Check that we have no FOR / braces mismatch
   18.90 -
   18.91 -	if ( m_forStackPtr > 0 )
   18.92 -	{
   18.93 -		For& mismatchedFor = m_forStack[ m_forStackPtr - 1 ];
   18.94 -
   18.95 -		if ( mismatchedFor.m_step == 0.0 )
   18.96 -		{
   18.97 -			AsmException_SyntaxError_MismatchedBraces e( mismatchedFor.m_line, mismatchedFor.m_column );
   18.98 -			e.SetFilename( m_pFilename );
   18.99 -			e.SetLineNumber( mismatchedFor.m_lineNumber );
  18.100 -			throw e;
  18.101 -		}
  18.102 -		else
  18.103 -		{
  18.104 -			AsmException_SyntaxError_ForWithoutNext e( mismatchedFor.m_line, mismatchedFor.m_column );
  18.105 -			e.SetFilename( m_pFilename );
  18.106 -			e.SetLineNumber( mismatchedFor.m_lineNumber );
  18.107 -			throw e;
  18.108 -		}
  18.109 -	}
  18.110 -
  18.111 -	// Check that we have no IF mismatch
  18.112 -
  18.113 -	if ( m_ifStackPtr > 0 )
  18.114 -	{
  18.115 -		If& mismatchedIf = m_ifStack[ m_ifStackPtr - 1 ];
  18.116 -
  18.117 -		AsmException_SyntaxError_IfWithoutEndif e( mismatchedIf.m_line, mismatchedIf.m_column );
  18.118 -		e.SetFilename( m_pFilename );
  18.119 -		e.SetLineNumber( mismatchedIf.m_lineNumber );
  18.120 -		throw e;
  18.121 -	}
  18.122 +	SourceCode::Process();
  18.123  
  18.124  	// Display ok message
  18.125  
  18.126 -	if ( GlobalData::Instance().IsFirstPass() )
  18.127 +	if ( GlobalData::Instance().ShouldOutputAsm() )
  18.128  	{
  18.129 -		cerr << "Processed file '" << m_pFilename << "' ok" << endl;
  18.130 +		cerr << "Processed file '" << m_filename << "' ok" << endl;
  18.131  	}
  18.132  }
  18.133  
  18.134 @@ -188,328 +103,55 @@
  18.135  
  18.136  /*************************************************************************************************/
  18.137  /**
  18.138 -	SourceFile::AddFor()
  18.139 +	SourceFile::GetLine()
  18.140 +
  18.141 +	Reads a line from the source code and returns it into lineFromFile
  18.142  */
  18.143  /*************************************************************************************************/
  18.144 -void SourceFile::AddFor( const string& varName,
  18.145 -						 double start,
  18.146 -						 double end,
  18.147 -						 double step,
  18.148 -						 int filePtr,
  18.149 -						 const string& line,
  18.150 -						 int column )
  18.151 +istream& SourceFile::GetLine( string& lineFromFile ) 
  18.152  {
  18.153 -	if ( m_forStackPtr == MAX_FOR_LEVELS )
  18.154 -	{
  18.155 -		throw AsmException_SyntaxError_TooManyFORs( line, column );
  18.156 -	}
  18.157 -
  18.158 -	// Add symbol to table
  18.159 -
  18.160 -	SymbolTable::Instance().AddSymbol( varName, start );
  18.161 -
  18.162 -	// Fill in FOR block
  18.163 -
  18.164 -	m_forStack[ m_forStackPtr ].m_varName		= varName;
  18.165 -	m_forStack[ m_forStackPtr ].m_current		= start;
  18.166 -	m_forStack[ m_forStackPtr ].m_end			= end;
  18.167 -	m_forStack[ m_forStackPtr ].m_step			= step;
  18.168 -	m_forStack[ m_forStackPtr ].m_filePtr		= filePtr;
  18.169 -	m_forStack[ m_forStackPtr ].m_id			= GlobalData::Instance().GetNextForId();
  18.170 -	m_forStack[ m_forStackPtr ].m_count			= 0;
  18.171 -	m_forStack[ m_forStackPtr ].m_line			= line;
  18.172 -	m_forStack[ m_forStackPtr ].m_column		= column;
  18.173 -	m_forStack[ m_forStackPtr ].m_lineNumber	= m_lineNumber;
  18.174 -
  18.175 -	m_forStackPtr++;
  18.176 +	return getline( m_file, lineFromFile );
  18.177  }
  18.178  
  18.179  
  18.180  
  18.181  /*************************************************************************************************/
  18.182  /**
  18.183 -	SourceFile::OpenBrace()
  18.184 +	SourceFile::GetFilePointer()
  18.185  
  18.186 -	Braces for scoping variables are just FORs in disguise...
  18.187 +	Returns the current file pointer
  18.188  */
  18.189  /*************************************************************************************************/
  18.190 -void SourceFile::OpenBrace( const string& line, int column )
  18.191 +int SourceFile::GetFilePointer()
  18.192  {
  18.193 -	if ( m_forStackPtr == MAX_FOR_LEVELS )
  18.194 -	{
  18.195 -		throw AsmException_SyntaxError_TooManyFORs( line, column );
  18.196 -	}
  18.197 -
  18.198 -	// Fill in FOR block
  18.199 -
  18.200 -	m_forStack[ m_forStackPtr ].m_varName		= "";
  18.201 -	m_forStack[ m_forStackPtr ].m_current		= 1.0;
  18.202 -	m_forStack[ m_forStackPtr ].m_end			= 0.0;
  18.203 -	m_forStack[ m_forStackPtr ].m_step			= 0.0;
  18.204 -	m_forStack[ m_forStackPtr ].m_filePtr		= 0;
  18.205 -	m_forStack[ m_forStackPtr ].m_id			= GlobalData::Instance().GetNextForId();
  18.206 -	m_forStack[ m_forStackPtr ].m_count			= 0;
  18.207 -	m_forStack[ m_forStackPtr ].m_line			= line;
  18.208 -	m_forStack[ m_forStackPtr ].m_column		= column;
  18.209 -	m_forStack[ m_forStackPtr ].m_lineNumber	= m_lineNumber;
  18.210 -
  18.211 -	m_forStackPtr++;
  18.212 +	return static_cast< int >( m_file.tellg() );
  18.213  }
  18.214  
  18.215  
  18.216  
  18.217  /*************************************************************************************************/
  18.218  /**
  18.219 -	SourceFile::UpdateFor()
  18.220 +	SourceFile::SetFilePointer()
  18.221 +
  18.222 +	Sets the current file pointer
  18.223  */
  18.224  /*************************************************************************************************/
  18.225 -void SourceFile::UpdateFor( const string& line, int column )
  18.226 +void SourceFile::SetFilePointer( int i )
  18.227  {
  18.228 -	if ( m_forStackPtr == 0 )
  18.229 -	{
  18.230 -		throw AsmException_SyntaxError_NextWithoutFor( line, column );
  18.231 -	}
  18.232 -
  18.233 -	For& thisFor = m_forStack[ m_forStackPtr - 1 ];
  18.234 -
  18.235 -	// step of 0.0 here means that the 'for' is in fact an open brace, so throw an error
  18.236 -
  18.237 -	if ( thisFor.m_step == 0.0 )
  18.238 -	{
  18.239 -		throw AsmException_SyntaxError_NextWithoutFor( line, column );
  18.240 -	}
  18.241 -
  18.242 -	thisFor.m_current += thisFor.m_step;
  18.243 -
  18.244 -	if ( ( thisFor.m_step > 0.0 && thisFor.m_current > thisFor.m_end ) ||
  18.245 -		 ( thisFor.m_step < 0.0 && thisFor.m_current < thisFor.m_end ) )
  18.246 -	{
  18.247 -		// we have reached the end of the FOR
  18.248 -		SymbolTable::Instance().RemoveSymbol( thisFor.m_varName );
  18.249 -		m_forStackPtr--;
  18.250 -	}
  18.251 -	else
  18.252 -	{
  18.253 -		// reloop
  18.254 -		SymbolTable::Instance().ChangeSymbol( thisFor.m_varName, thisFor.m_current );
  18.255 -		SetFilePointer( thisFor.m_filePtr );
  18.256 -		thisFor.m_count++;
  18.257 -		m_lineNumber = thisFor.m_lineNumber - 1;
  18.258 -	}
  18.259 +	m_lineStartPointer = i;
  18.260 +	m_file.seekg( i );
  18.261  }
  18.262  
  18.263  
  18.264  
  18.265  /*************************************************************************************************/
  18.266  /**
  18.267 -	SourceFile::CloseBrace()
  18.268 +	SourceFile::IsAtEnd()
  18.269  
  18.270 -	Braces for scoping variables are just FORs in disguise...
  18.271 +	Returns whether the current stream is in an end-of-file state
  18.272  */
  18.273  /*************************************************************************************************/
  18.274 -void SourceFile::CloseBrace( const string& line, int column )
  18.275 +bool SourceFile::IsAtEnd()
  18.276  {
  18.277 -	if ( m_forStackPtr == 0 )
  18.278 -	{
  18.279 -		throw AsmException_SyntaxError_MismatchedBraces( line, column );
  18.280 -	}
  18.281 -
  18.282 -	For& thisFor = m_forStack[ m_forStackPtr - 1 ];
  18.283 -
  18.284 -	// step of non-0.0 here means that this a real 'for', so throw an error
  18.285 -
  18.286 -	if ( thisFor.m_step != 0.0 )
  18.287 -	{
  18.288 -		throw AsmException_SyntaxError_MismatchedBraces( line, column );
  18.289 -	}
  18.290 -
  18.291 -	m_forStackPtr--;
  18.292 +	return m_file.eof();
  18.293  }
  18.294 -
  18.295 -
  18.296 -
  18.297 -/*************************************************************************************************/
  18.298 -/**
  18.299 -	SourceFile::GetSymbolNameSuffix()
  18.300 -*/
  18.301 -/*************************************************************************************************/
  18.302 -string SourceFile::GetSymbolNameSuffix( int level ) const
  18.303 -{
  18.304 -	if ( level == -1 )
  18.305 -	{
  18.306 -		level = m_forStackPtr;
  18.307 -	}
  18.308 -
  18.309 -	ostringstream suffix;
  18.310 -
  18.311 -	for ( int i = 0; i < level; i++ )
  18.312 -	{
  18.313 -		suffix << "@";
  18.314 -		suffix << m_forStack[ i ].m_id;
  18.315 -		suffix << "_";
  18.316 -		suffix << m_forStack[ i ].m_count;
  18.317 -	}
  18.318 -
  18.319 -	return suffix.str();
  18.320 -}
  18.321 -
  18.322 -
  18.323 -
  18.324 -/*************************************************************************************************/
  18.325 -/**
  18.326 -	SourceFile::IsIfConditionTrue()
  18.327 -*/
  18.328 -/*************************************************************************************************/
  18.329 -bool SourceFile::IsIfConditionTrue() const
  18.330 -{
  18.331 -	for ( int i = 0; i < m_ifStackPtr; i++ )
  18.332 -	{
  18.333 -		if ( !m_ifStack[ i ].m_condition )
  18.334 -		{
  18.335 -			return false;
  18.336 -		}
  18.337 -	}
  18.338 -
  18.339 -	return true;
  18.340 -}
  18.341 -
  18.342 -
  18.343 -
  18.344 -/*************************************************************************************************/
  18.345 -/**
  18.346 -	SourceFile::AddIfLevel()
  18.347 -*/
  18.348 -/*************************************************************************************************/
  18.349 -void SourceFile::AddIfLevel( const string& line, int column )
  18.350 -{
  18.351 -	if ( m_ifStackPtr == MAX_IF_LEVELS )
  18.352 -	{
  18.353 -		throw AsmException_SyntaxError_TooManyIFs( line, column );
  18.354 -	}
  18.355 -
  18.356 -	m_ifStack[ m_ifStackPtr ].m_condition	= true;
  18.357 -	m_ifStack[ m_ifStackPtr ].m_passed		= false;
  18.358 -	m_ifStack[ m_ifStackPtr ].m_hadElse		= false;
  18.359 -	m_ifStack[ m_ifStackPtr ].m_line		= line;
  18.360 -	m_ifStack[ m_ifStackPtr ].m_column		= column;
  18.361 -	m_ifStack[ m_ifStackPtr ].m_lineNumber	= m_lineNumber;
  18.362 -	m_ifStackPtr++;
  18.363 -}
  18.364 -
  18.365 -
  18.366 -
  18.367 -/*************************************************************************************************/
  18.368 -/**
  18.369 -	SourceFile::SetCurrentIfCondition()
  18.370 -*/
  18.371 -/*************************************************************************************************/
  18.372 -void SourceFile::SetCurrentIfCondition( bool b )
  18.373 -{
  18.374 -	assert( m_ifStackPtr > 0 );
  18.375 -	m_ifStack[ m_ifStackPtr - 1 ].m_condition = b;
  18.376 -	if ( b )
  18.377 -	{
  18.378 -		m_ifStack[ m_ifStackPtr - 1 ].m_passed = true;
  18.379 -	}
  18.380 -}
  18.381 -
  18.382 -
  18.383 -
  18.384 -/*************************************************************************************************/
  18.385 -/**
  18.386 -	SourceFile::StartElse()
  18.387 -*/
  18.388 -/*************************************************************************************************/
  18.389 -void SourceFile::StartElse( const string& line, int column )
  18.390 -{
  18.391 -	if ( m_ifStack[ m_ifStackPtr - 1 ].m_hadElse )
  18.392 -	{
  18.393 -		throw AsmException_SyntaxError_ElseWithoutIf( line, column );
  18.394 -	}
  18.395 -
  18.396 -	m_ifStack[ m_ifStackPtr - 1 ].m_hadElse = true;
  18.397 -
  18.398 -	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_passed;
  18.399 -}
  18.400 -
  18.401 -
  18.402 -
  18.403 -/*************************************************************************************************/
  18.404 -/**
  18.405 -	SourceFile::StartElif()
  18.406 -*/
  18.407 -/*************************************************************************************************/
  18.408 -void SourceFile::StartElif( const string& line, int column )
  18.409 -{
  18.410 -	if ( m_ifStack[ m_ifStackPtr - 1 ].m_hadElse )
  18.411 -	{
  18.412 -		throw AsmException_SyntaxError_ElifWithoutIf( line, column );
  18.413 -	}
  18.414 -
  18.415 -	m_ifStack[ m_ifStackPtr - 1 ].m_condition = !m_ifStack[ m_ifStackPtr - 1 ].m_passed;
  18.416 -}
  18.417 -
  18.418 -
  18.419 -
  18.420 -/*************************************************************************************************/
  18.421 -/**
  18.422 -	SourceFile::RemoveIfLevel()
  18.423 -*/
  18.424 -/*************************************************************************************************/
  18.425 -void SourceFile::RemoveIfLevel( const string& line, int column )
  18.426 -{
  18.427 -	if ( m_ifStackPtr == 0 )
  18.428 -	{
  18.429 -		throw AsmException_SyntaxError_EndifWithoutIf( line, column );
  18.430 -	}
  18.431 -
  18.432 -	m_ifStackPtr--;
  18.433 -}
  18.434 -
  18.435 -
  18.436 -
  18.437 -/*************************************************************************************************/
  18.438 -/**
  18.439 -	SourceFile::StartMacro()
  18.440 -*/
  18.441 -/*************************************************************************************************/
  18.442 -void SourceFile::StartMacro( const string& line, int column )
  18.443 -{
  18.444 -	if ( GlobalData::Instance().IsFirstPass() )
  18.445 -	{
  18.446 -		if ( m_currentMacro == NULL )
  18.447 -		{
  18.448 -			m_currentMacro = new Macro();
  18.449 -		}
  18.450 -		else
  18.451 -		{
  18.452 -			throw AsmException_SyntaxError_NoNestedMacros( line, column );
  18.453 -		}
  18.454 -	}
  18.455 -
  18.456 -	AddIfLevel( line, column );
  18.457 -}
  18.458 -
  18.459 -
  18.460 -
  18.461 -/*************************************************************************************************/
  18.462 -/**
  18.463 -	SourceFile::EndMacro()
  18.464 -*/
  18.465 -/*************************************************************************************************/
  18.466 -void SourceFile::EndMacro( const string& line, int column )
  18.467 -{
  18.468 -	if ( GlobalData::Instance().IsFirstPass() &&
  18.469 -		 m_currentMacro == NULL )
  18.470 -	{
  18.471 -		throw AsmException_SyntaxError_EndMacroUnexpected( line, column - 8 );
  18.472 -	}
  18.473 -
  18.474 -	RemoveIfLevel( line, column );
  18.475 -
  18.476 -	if ( GlobalData::Instance().IsFirstPass() )
  18.477 -	{
  18.478 -		MacroTable::Instance().Add( m_currentMacro );
  18.479 -		m_currentMacro = NULL;
  18.480 -	}
  18.481 -}
    19.1 --- a/src/sourcefile.h	Sun Mar 06 18:19:27 2011 +0100
    19.2 +++ b/src/sourcefile.h	Mon Apr 25 01:14:59 2011 +0200
    19.3 @@ -26,106 +26,33 @@
    19.4  #include <fstream>
    19.5  #include <string>
    19.6  #include <vector>
    19.7 +#include "sourcecode.h"
    19.8  #include "macro.h"
    19.9  
   19.10  
   19.11 -class SourceFile
   19.12 +class SourceFile : public SourceCode
   19.13  {
   19.14  public:
   19.15  
   19.16  	// Constructor/destructor (RAII class)
   19.17  
   19.18 -	explicit SourceFile( const char* pFilename );
   19.19 -	~SourceFile();
   19.20 +	explicit SourceFile( const std::string& filename );
   19.21 +	virtual ~SourceFile();
   19.22  
   19.23 -	// Process the file
   19.24 +	virtual void Process();
   19.25  
   19.26 -	void Process();
   19.27  
   19.28  	// Accessors
   19.29  
   19.30 -	inline const char*		GetFilename() const				{ return m_pFilename; }
   19.31 -	inline int				GetLineNumber() const			{ return m_lineNumber; }
   19.32 -	inline int				GetFilePointer() const			{ return m_filePointer; }
   19.33 -	inline void				SetFilePointer( int i )			{ m_filePointer = i; m_file.seekg( i ); }
   19.34 -
   19.35 -	// For loop / if related stuff
   19.36 -
   19.37 -	#define MAX_FOR_LEVELS	32
   19.38 -	#define MAX_IF_LEVELS	32
   19.39 -
   19.40 -private:
   19.41 -
   19.42 -	struct For
   19.43 -	{
   19.44 -		std::string			m_varName;
   19.45 -		double				m_current;
   19.46 -		double				m_end;
   19.47 -		double				m_step;
   19.48 -		int					m_filePtr;
   19.49 -		int					m_id;
   19.50 -		int					m_count;
   19.51 -		std::string			m_line;
   19.52 -		int					m_column;
   19.53 -		int					m_lineNumber;
   19.54 -	};
   19.55 -
   19.56 -	For						m_forStack[ MAX_FOR_LEVELS ];
   19.57 -	int						m_forStackPtr;
   19.58 -
   19.59 -	struct If
   19.60 -	{
   19.61 -		bool				m_condition;
   19.62 -		bool                m_hadElse;
   19.63 -		bool				m_passed;
   19.64 -		std::string			m_line;
   19.65 -		int					m_column;
   19.66 -		int					m_lineNumber;
   19.67 -	};
   19.68 -
   19.69 -	int						m_ifStackPtr;
   19.70 -	If						m_ifStack[ MAX_IF_LEVELS ];
   19.71 -
   19.72 -	Macro*					m_currentMacro;
   19.73 -
   19.74 -
   19.75 -public:
   19.76 -
   19.77 -	void					OpenBrace( const std::string& line, int column );
   19.78 -	void					CloseBrace( const std::string& line, int column );
   19.79 -
   19.80 -	void					AddFor( const std::string& varName,
   19.81 -									double start,
   19.82 -									double end,
   19.83 -									double step,
   19.84 -									int filePtr,
   19.85 -									const std::string& line,
   19.86 -									int column );
   19.87 -
   19.88 -	void					UpdateFor( const std::string& line, int column );
   19.89 -
   19.90 -	inline int 				GetForLevel() const { return m_forStackPtr; }
   19.91 -	inline Macro*			GetCurrentMacro() { return m_currentMacro; }
   19.92 -
   19.93 -	std::string				GetSymbolNameSuffix( int level = -1 ) const;
   19.94 -
   19.95 -	bool					IsIfConditionTrue() const;
   19.96 -	void					AddIfLevel( const std::string& line, int column );
   19.97 -	void					SetCurrentIfCondition( bool b );
   19.98 -	void					StartElse( const std::string& line, int column );
   19.99 -	void					StartElif( const std::string& line, int column );
  19.100 -	void					ToggleCurrentIfCondition( const std::string& line, int column );
  19.101 -	void					RemoveIfLevel( const std::string& line, int column );
  19.102 -	void					StartMacro( const std::string& line, int column );
  19.103 -	void					EndMacro( const std::string& line, int column );
  19.104 +	virtual int				GetFilePointer();
  19.105 +	virtual void			SetFilePointer( int i );
  19.106 +	virtual std::istream&	GetLine( std::string& lineFromFile );
  19.107 +	virtual bool			IsAtEnd();
  19.108  
  19.109  
  19.110  private:
  19.111  
  19.112  	std::ifstream			m_file;
  19.113 -	const char*				m_pFilename;
  19.114 -	int						m_lineNumber;
  19.115 -	int						m_filePointer;
  19.116  };
  19.117  
  19.118