tripwire-open-source/src/twparser/genreparseinfo.cpp

273 lines
8.5 KiB
C++

//
// 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 ) );
}