// // The developer of the original code and/or files is Tripwire, Inc. // Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, // Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights // reserved. // // This program is free software. The contents of this file are subject // to the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. You may redistribute it and/or modify it // only in compliance with the GNU General Public License. // // This program is distributed in the hope that it will be useful. // However, this program is distributed AS-IS WITHOUT ANY // WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS // FOR A PARTICULAR PURPOSE. Please see the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, // USA. // // Nothing in the GNU General Public License or any other license to use // the code or files shall permit you to use Tripwire's trademarks, // service marks, or other intellectual property without Tripwire's // prior written consent. // // If you have any questions, please contact Tripwire, Inc. at either // info@tripwire.org or www.tripwire.org. // /////////////////////////////////////////////////////////////////////////////// // genreparseinfo.cpp -- helper classes that are called by yacc parser // #include "stdtwparser.h" //========================================================================= // INCLUDES //========================================================================= #include "parserhelper.h" #include "fco/twfactory.h" #include "fco/fconameinfo.h" #include "fco/genreswitcher.h" #include "fco/parsergenreutil.h" //========================================================================= // STANDARD LIBRARY INCLUDES //========================================================================= //========================================================================= // DEFINES AND MACROS //========================================================================= //========================================================================= // OTHER DIRECTIVES //========================================================================= //========================================================================= // GLOBALS //========================================================================= //========================================================================= // UTIL FUNCTION PROTOTYES //========================================================================= //========================================================================= // METHOD CODE //========================================================================= cGenreParseInfo::cGenreParseInfo() { InitPredefinedVariables(); } /////////////////////////////////////////////////////////////////////////////// // AddStopPoint // NOTE: the list copies the string, so it is safe for the parser to // free the lexeme /////////////////////////////////////////////////////////////////////////////// void cGenreParseInfo::AddStopPoint( const cFCOName& name ) { mStopList.push_back( name ); } /////////////////////////////////////////////////////////////////////////////// // AddRule -- adds the specified rule to our list. we will eventually call // MakeFCOSpecs(), which will use this list as its source. // // NOTE: the list is responsible for freeing the pointers /////////////////////////////////////////////////////////////////////////////// void cGenreParseInfo::AddRule(const cParseRule *pnode) { mRuleList.push_back(pnode); } /////////////////////////////////////////////////////////////////////////////// // RulePointAlreadyDefined -- returns true if the given name was already used // as a start or stop point /////////////////////////////////////////////////////////////////////////////// bool cGenreParseInfo::RulePointAlreadyDefined( const cFCOName& fcoName ) { bool fFound = false; // check start points for( RuleListType::iterator i = mRuleList.begin(); i != mRuleList.end(); i++ ) { if( (*i)->GetName() == fcoName ) fFound = true; } // check stop points if( ! fFound ) { for( StopListType::iterator j = mStopList.begin(); j != mStopList.end(); j++ ) { if( *j == fcoName ) fFound = true; } } return( fFound ); } /////////////////////////////////////////////////////////////////////////////// // InitPredefinedVariables -- /////////////////////////////////////////////////////////////////////////////// void cGenreParseInfo::InitPredefinedVariables() { iParserGenreUtil* pGU = iTWFactory::GetInstance()->CreateParserGenreUtil(); TSTRING sVarName, sValue; int index = 0; while( pGU->EnumPredefinedVariables( index++, sVarName, sValue ) ) { mLocalPredefVarTable.Insert( sVarName, sValue ); } } /////////////////////////////////////////////////////////////////////////////// // DoVarSubstitution() // replaces any $(VAR) in string with it's value, unless the $ is escaped with // a backslash. Fails if symbol isn't found /////////////////////////////////////////////////////////////////////////////// bool cGenreParseInfo::DoVarSubstitution( TSTRING &rval ) //throw( eParserHelper ) { cDebug d("cConfigFile::DoVarSubst()"); d.TraceDebug("ORIG: %s\n", rval.c_str()); // walk through string // look for $( // find matching ) // pick out subset // look up in symbol table // substitute subset // continue iterating // step through string // iterate to (slen-1), because we are looking for a two-character sentinel "$(" bool fEscaping = false; for (TSTRING::size_type i = 0; i < rval.size(); i++) { TCHAR c = rval[i]; // is it the "$(" sentinel? (an escaped '$' is not a variable) if (c == '$' && ! fEscaping ) { c = rval[i+1]; if (c == '(') { // ooh, wow! it's a variable! find the end bool found = false; TSTRING::size_type j; for (j = i+1; j < rval.size(); j++) { if (rval[j] == ')') { found = true; break; } } // did we find it? if (!found) { // TODO: throw error return false; } // otherwise, cut out the variable name TSTRING::size_type begin = i + 2; TSTRING::size_type size = j - i - 2; TSTRING varname; varname = rval.substr(begin, size); d.TraceDebug("symbol = %s\n", varname.c_str()); // look up in symbol table TSTRING varvalue; if ( ! LookupVariable( varname, varvalue ) ) throw eParserUseUndefVar( varname ); // replace varname with varvalue rval.replace(begin-2, size+3, varvalue); d.TraceDebug("POST: %s\n", rval.c_str()); // no no no // we should exit function, and get called again // update counters // we should bump the cursor over by the length of the // varvalue (minus one, to compensate for post-increment of index) i += varvalue.size() - 1; goto nextchar; } } else if (c == '\\') { fEscaping = ! fEscaping; } else { fEscaping = false; } nextchar: ; } d.TraceDebug("DONE: %s\n", rval.c_str()); // switch around return true; } /////////////////////////////////////////////////////////////////////////////// // Insert -- add definition to symbol table /////////////////////////////////////////////////////////////////////////////// bool cGenreParseInfo::InsertVariable( const TSTRING& var, const TSTRING& val ) //throw( eParserHelper ) { TSTRING dummy; // don't let them redefine predefined vars if( mLocalPredefVarTable.Lookup(var, dummy) ) throw eParserRedefineVar( var ); return mLocalVarTable.Insert( var, val ); } /////////////////////////////////////////////////////////////////////////////// // Lookup -- returns value, or returns false // This method will return false only if the given variable is not defined // in any of the three symbol tables. /////////////////////////////////////////////////////////////////////////////// bool cGenreParseInfo::LookupVariable( const TSTRING& var, TSTRING& val ) { if( mLocalPredefVarTable.Lookup( var, val ) || mLocalVarTable.Lookup( var, val ) ) return true; else return ( cParserHelper::GetGlobalVarTable().Lookup( var, val ) ); }