#include "options.h"
#include "version.h"
#include "game.h"
#include "smlnode.h"
#include
#include
#include
#include
using namespace Bu;
Options::Options()
{
}
Options::~Options()
{
}
void Options::parse( int argc, char *argv[] )
{
Bu::OptParser opt;
opt.addHelpBanner("STAGE v" VERSION
" - Simple, Textual, Adventure Game Environment");
opt.addHelpBanner("usage: " + Bu::String(argv[0]) +
" [options] \n");
opt.addOption( Bu::slot( this, &Options::smlTest ), "sml-test",
"Test SML parser." );
opt.addOption( Bu::slot( this, &Options::version ), "version",
"Show full version info." );
opt.addOption( Bu::slot( this, &Options::builtins ), "builtins",
"List available builtins." );
opt.addHelpOption('h', "help");
opt.setNonOption( Bu::slot( this, &Options::nonOption ) );
opt.parse( argc, argv );
}
int Options::version( Bu::StrArray aArgs )
{
sio << "STAGE v" VERSION " - Simple, Textual, Adventure Game Environment."
<< sio.nl << sio.nl;
sio << "Full version: " FULLVER << sio.nl;
sio << "Build date: " TIMEVER << sio.nl;
sio << "Build id: " SHAVER << sio.nl;
sio << sio.nl;
exit( 0 );
return 0;
}
int Options::builtins( Bu::StrArray aArgs )
{
sio << "Current builtin functions:" << sio.nl;
Game g;
const Game::FunctionHash &hFnc = g.getFunctionHash();
for( Game::FunctionHash::const_iterator i = hFnc.begin(); i; i++ )
{
sio << " - " << i.getKey() << sio.nl;
}
sio << sio.nl;
exit( 0 );
return 0;
}
void smlToHtml( const SmlNode *pNode )
{
switch( pNode->getType() )
{
case SmlNode::typeRoot:
sio << "";
for( SmlNode::SmlNodeList::const_iterator i =
pNode->getChildren().begin(); i; i++ )
{
smlToHtml( *i );
}
sio << "
";
break;
case SmlNode::typeText:
sio << pNode->getText();
break;
case SmlNode::typeTag:
if( pNode->getChildren().isEmpty() )
{
if( pNode->getText() == "break" )
sio << "
";
}
else
{
if( pNode->getText() == "red" )
{
sio << "";
for( SmlNode::SmlNodeList::const_iterator i =
pNode->getChildren().begin(); i; i++ )
{
smlToHtml( *i );
}
sio << "";
}
else if( pNode->getText() == "green" )
{
sio << "";
for( SmlNode::SmlNodeList::const_iterator i =
pNode->getChildren().begin(); i; i++ )
{
smlToHtml( *i );
}
sio << "";
}
}
break;
}
}
void appendToken( Bu::String &sCurLine, Bu::String &sNextToken, int &iLineLen,
int &iNextLen )
{
if( iLineLen + iNextLen + 1 >= 78 )
{
sio << sCurLine << sio.nl;
iLineLen = 0;
sCurLine = sNextToken;
}
else
{
sCurLine += sNextToken;
}
iLineLen += iNextLen + 1;
sCurLine += " ";
iNextLen = 0;
sNextToken.clear();
}
void smlToConsole( const SmlNode *pNode )
{
Bu::String sCurLine;
Bu::String sNextToken;
int iLineLen = 0;
int iNextLen = 0;
int iState = 0;
typedef Bu::List NodeStack;
NodeStack sNode;
sNode.push( pNode->getChildren().begin() );
for(;;)
{
if( !sNode.peek() )
{
sNode.pop();
if( sNode.isEmpty() )
break;
if( sNode.peek() )
{
// sio << "Pop'd: " << (*sNode.peek())->getText() << sio.nl;
Bu::String sTag = (*sNode.peek())->getText();
if( sTag == "green" || sTag == "red" )
{
sNextToken += "\x1B[0m";
}
sNode.peek()++;
continue;
}
}
if( sNode.isEmpty() )
{
break;
}
const SmlNode *pNode = (*sNode.peek());
switch( pNode->getType() )
{
case SmlNode::typeRoot:
throw Bu::ExceptionBase("Invalid root.");
case SmlNode::typeText:
{
// sio << "Process text node: " << pNode->getText() <<
// sio.nl;
Bu::String::const_iterator iBgn = pNode->getText().begin();
Bu::String::const_iterator iEnd = iBgn;
int iTmpLen = 0;
for(;iBgn;)
{
switch( iState )
{
case 0: // begining of paragraph
if( iBgn && ( *iBgn == ' ' || *iBgn == '\n' ||
*iBgn == '\r' || *iBgn == '\t' ) )
{
iBgn++;
}
else
{
// Here is where you would indent paragraphs
iEnd = iBgn;
iState = 1;
}
break;
case 1: // non-whitespace
if( !iEnd )
{
sNextToken.append( iBgn, iEnd );
iBgn = iEnd;
iNextLen += iTmpLen;
iTmpLen = 0;
}
else if( *iEnd == ' ' || *iEnd == '\n' ||
*iEnd == '\r' || *iEnd == '\t' )
{
sNextToken.append( iBgn, iEnd );
iNextLen += iTmpLen;
iTmpLen = 0;
iState = 2;
iBgn = iEnd;
}
else
{
iEnd++;
iTmpLen++;
}
break;
case 2: // Whitespace
if( iBgn && (*iBgn == ' ' || *iBgn == '\n' ||
*iBgn == '\r' || *iBgn == '\t') )
{
iBgn++;
}
else
{
iEnd = iBgn;
iState = 1;
appendToken( sCurLine, sNextToken,
iLineLen, iNextLen );
}
break;
}
}
}
break;
case SmlNode::typeTag:
if( pNode->getChildren().isEmpty() )
{
if( pNode->getText() == "break" )
{
appendToken( sCurLine, sNextToken, iLineLen, iNextLen );
if( !sCurLine.isEmpty() )
sio << sCurLine << sio.nl;
sCurLine.clear();
iLineLen = 0;
iState = 0;
}
}
else
{
// sio << "Push'd: " << pNode->getText() << sio.nl;
Bu::String sTag = pNode->getText();
if( sTag == "green" )
{
sNextToken += "\x1B[1;32m";
}
else if( sTag == "red" )
{
sNextToken += "\x1B[1;31m";
}
sNode.push( pNode->getChildren().begin() );
continue;
/* for( SmlNode::SmlNodeList::const_iterator i =
pNode->getChildren().begin(); i; i++ )
{
s
smlToConsole( *i, sCurLine, sNextToken, iLineLen, iState );
}
*/
}
break;
}
sNode.peek()++;
}
if( !sNextToken.isEmpty() )
appendToken( sCurLine, sNextToken, iLineLen, iNextLen );
sio << sCurLine << sio.nl;
}
/*
void smlToConsole( const SmlNode *pNode )
{
Bu::String sBuf, sBuf2;
int i1 = 0, i2 = 0;
smlToConsole( pNode, sBuf, sBuf2, i1, i2 );
appendToken( sBuf, sBuf2, i1 );
sio << sBuf << sBuf2 << sio.nl;
}*/
int Options::smlTest( Bu::Array aArgs )
{
Bu::String sContent;
Bu::File fIn( aArgs[1], Bu::File::Read );
while( !fIn.isEos() )
{
char buf[4096];
sContent.append( buf, fIn.read( buf, 4096 ) );
}
fIn.close();
SmlNode *pRoot = SmlNode::parse( sContent );
sio << *pRoot << sio.nl;
smlToConsole( pRoot );
delete pRoot;
exit( 0 );
return 0;
}
int Options::nonOption( Bu::Array aArgs )
{
sFile = aArgs[0];
return 0;
}