#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; }