262 lines
6.3 KiB
C++
262 lines
6.3 KiB
C++
#include <as68hc11/scan.hpp>
|
|
#include <as68hc11/symbol.hpp>
|
|
#include <as68hc11/table.hpp>
|
|
#include <common/pointer.hpp>
|
|
#include <common/openfile.hpp>
|
|
#include <common/filemap.hpp>
|
|
#include <common/pview.hpp>
|
|
|
|
Scan::Scan(PureViewOfFile &inFile,PureViewOfFile &outFile,Table &symbolTable,Block<String> &includePath)
|
|
: Emit(inFile,outFile), mSymbolTable(symbolTable), mEmitEndText(true), mIncludePath(includePath)
|
|
{
|
|
}
|
|
|
|
Scan::Scan(PureViewOfFile &inFile,PureViewOfFile &outFile,Table &symbolTable,CodePointer &codePointer,Block<String> &includePath)
|
|
: Emit(inFile,outFile,codePointer), mSymbolTable(symbolTable), mEmitEndText(false), mIncludePath(includePath)
|
|
{
|
|
}
|
|
|
|
Scan::~Scan(void)
|
|
{
|
|
}
|
|
|
|
bool Scan::analyze(void)
|
|
{
|
|
readch();
|
|
while((int)mChar!=-1&&mChar!=0x001A)
|
|
{
|
|
skipSeparators();
|
|
if(0xFFFF==mChar||0x001A==mChar)break;
|
|
if(isdigit(mChar))scanNumeral();
|
|
else if('\r'==mChar)scanNewLine();
|
|
else if(','==mChar){emit(comma1);readch();}
|
|
else if('['==mChar){emit(leftbracket1);readch();}
|
|
else if(']'==mChar){emit(rightbracket1);readch();}
|
|
else if('*'==mChar){emit(asterisk1);readch();}
|
|
else if('/'==mChar){emit(divide1);readch();}
|
|
else if('+'==mChar){emit(plus1);readch();}
|
|
else if('-'==mChar){emit(minus1);readch();}
|
|
else if('('==mChar){emit(leftparen1);readch();}
|
|
else if(')'==mChar){emit(rightparen1);readch();}
|
|
else if('\''==mChar)scanCharacter();
|
|
else if(';'==mChar)scanComment();
|
|
else if(isalpha(mChar)){if(!scanWord())return false;}
|
|
else scanUnknown();
|
|
}
|
|
if(mEmitEndText)emit(endtext1);
|
|
return true;
|
|
}
|
|
|
|
void Scan::scanNewLine(void)
|
|
{
|
|
emit(newline1);
|
|
readch();
|
|
if(mChar=='\n')readch();
|
|
}
|
|
|
|
void Scan::skipSeparators(void)
|
|
{
|
|
while(mChar==SpaceChar||mChar==TabChar)readch();
|
|
}
|
|
|
|
void Scan::scanComment(void)
|
|
{
|
|
readch();
|
|
while(mChar!='\r'&&mChar!=0xFFFF)readch();
|
|
}
|
|
|
|
void Scan::scanCharacter(void)
|
|
{
|
|
int character;
|
|
|
|
readch();
|
|
character=mChar;
|
|
readch();
|
|
*((char*)mWordString)=0;
|
|
mWordString+=character;
|
|
while(0xFFFF!=mChar&&'\''!=mChar&&0x0D!=mChar)
|
|
{
|
|
mWordString+=mChar;
|
|
readch();
|
|
}
|
|
readch();
|
|
emit(apostrophe1);
|
|
emit(literal1);
|
|
emit(mWordString);
|
|
emit(apostrophe1);
|
|
}
|
|
|
|
bool Scan::scanNumeral(void)
|
|
{
|
|
char chBuffer[128];
|
|
char chIndex(0);
|
|
int value(0);
|
|
|
|
while(0xFFFF!=mChar&&(isdigit(mChar)||isInHex(mChar)))
|
|
{
|
|
if(chIndex>=sizeof(chBuffer))return FALSE;
|
|
chBuffer[chIndex++]=mChar;
|
|
readch();
|
|
}
|
|
if('h'==mChar||'H'==mChar){hex(chBuffer,chIndex);readch();}
|
|
else if('b'==mChar||'B'==mChar){binary(chBuffer,chIndex);readch();}
|
|
else if(chIndex>0&&('b'==chBuffer[chIndex-1]||'B'==chBuffer[chIndex-1]))binary(chBuffer,chIndex-1);
|
|
else decimal(chBuffer,chIndex);
|
|
return TRUE;
|
|
}
|
|
|
|
void Scan::hex(char chBuffer[],int chIndex)
|
|
{
|
|
int value(0);
|
|
int multiplier(1);
|
|
|
|
for(--chIndex;chIndex>=0;chIndex--)
|
|
{
|
|
switch(chBuffer[chIndex])
|
|
{
|
|
case '0' : break;
|
|
case '1' : {value+=multiplier;break;}
|
|
case '2' : {value+=multiplier*2;break;}
|
|
case '3' : {value+=multiplier*3;break;}
|
|
case '4' : {value+=multiplier*4;break;}
|
|
case '5' : {value+=multiplier*5;break;}
|
|
case '6' : {value+=multiplier*6;break;}
|
|
case '7' : {value+=multiplier*7;break;}
|
|
case '8' : {value+=multiplier*8;break;}
|
|
case '9' : {value+=multiplier*9;break;}
|
|
case 'a' :
|
|
case 'A' : {value+=multiplier*10;break;}
|
|
case 'b' :
|
|
case 'B' : {value+=multiplier*11;break;}
|
|
case 'c' :
|
|
case 'C' : {value+=multiplier*12;break;}
|
|
case 'd' :
|
|
case 'D' : {value+=multiplier*13;break;}
|
|
case 'e' :
|
|
case 'E' : {value+=multiplier*14;break;}
|
|
case 'f' :
|
|
case 'F' : {value+=multiplier*15;break;}
|
|
default : {emit(unknown1);return;}
|
|
}
|
|
multiplier*=16;
|
|
}
|
|
emit(numeral1,value);
|
|
}
|
|
|
|
void Scan::binary(char chBuffer[],int chIndex)
|
|
{
|
|
int value(0);
|
|
int multiplier(1);
|
|
|
|
for(--chIndex;chIndex>=0;chIndex--)
|
|
{
|
|
switch(chBuffer[chIndex])
|
|
{
|
|
case '0' : break;
|
|
case '1' : {value+=multiplier;break;}
|
|
default : {emit(unknown1);return;}
|
|
}
|
|
multiplier*=2;
|
|
}
|
|
emit(numeral1,value);
|
|
}
|
|
|
|
void Scan::decimal(char chBuffer[],int chIndex)
|
|
{
|
|
int value(0);
|
|
int multiplier(1);
|
|
|
|
for(--chIndex;chIndex>=0;chIndex--)
|
|
{
|
|
switch(chBuffer[chIndex])
|
|
{
|
|
case '0' : break;
|
|
case '1' : {value+=multiplier;break;}
|
|
case '2' : {value+=multiplier*2;break;}
|
|
case '3' : {value+=multiplier*3;break;}
|
|
case '4' : {value+=multiplier*4;break;}
|
|
case '5' : {value+=multiplier*5;break;}
|
|
case '6' : {value+=multiplier*6;break;}
|
|
case '7' : {value+=multiplier*7;break;}
|
|
case '8' : {value+=multiplier*8;break;}
|
|
case '9' : {value+=multiplier*9;break;}
|
|
default : {emit(unknown1);return;}
|
|
}
|
|
multiplier*=10;
|
|
}
|
|
emit(numeral1,value);
|
|
}
|
|
|
|
bool Scan::scanWord(void)
|
|
{
|
|
SmartPointer<Symbol> symbol;
|
|
|
|
*((char*)mWordString)=0;
|
|
while(0x0D!=mChar&&!isKeySymbol()&&0xFFFF!=mChar&&SpaceChar!=mChar&&TabChar!=mChar)
|
|
{
|
|
mWordString+=mChar;
|
|
readch();
|
|
}
|
|
if(mWordString.isNull())return true;
|
|
if(mSymbolTable.locateSymbol(mWordString,symbol))
|
|
{
|
|
if(Symbol::DirectiveSymbol==symbol->symbolType())emit(symbol->identifier());
|
|
else emit(name1,int((Symbol*)symbol));
|
|
}
|
|
else if(':'==mChar){emit(label1);emit(mWordString);readch();}
|
|
else if(mWordString=="INCLUDE" || mWordString=="include")
|
|
{
|
|
if(!scanInclude())return false;
|
|
}
|
|
else {emit(literal1);emit(mWordString);}
|
|
return true;
|
|
}
|
|
|
|
bool Scan::scanInclude()
|
|
{
|
|
FileHandle inFile;
|
|
String wordString;
|
|
String pathFileName;
|
|
bool returnCode;
|
|
|
|
*((char*)wordString)=0;
|
|
readch();
|
|
while(0x0D!=mChar&&SpaceChar!=mChar)
|
|
{
|
|
wordString+=mChar;
|
|
readch();
|
|
}
|
|
if(wordString.isNull())return true;
|
|
if(!getIncludeFile(wordString,pathFileName))
|
|
{
|
|
mLastMessage=String("Cannot locate include file '")+wordString+String("'.");
|
|
return false;
|
|
}
|
|
if(!inFile.open(pathFileName,FileHandle::Read,FileHandle::ShareRead))
|
|
{
|
|
mLastMessage=String("Cannot open include file '")+pathFileName+String("'.");
|
|
return false;
|
|
}
|
|
FileMap inMap(inFile);
|
|
PureViewOfFile inView(inMap);
|
|
Scan scan(inView,outputView(),mSymbolTable,codePointer(),mIncludePath);
|
|
returnCode=scan.analyze();
|
|
if(returnCode)codePointer()=scan.codePointer();
|
|
return returnCode;
|
|
}
|
|
|
|
bool Scan::getIncludeFile(const String &fileName,String &pathFileName)
|
|
{
|
|
FileHandle openFile;
|
|
for(int index=0;index<mIncludePath.size();index++)
|
|
{
|
|
pathFileName=mIncludePath[index]+String("\\")+fileName;
|
|
if(openFile.open(pathFileName,FileHandle::Read,FileHandle::ShareRead))
|
|
{
|
|
openFile.close();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|