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
