2007-01-24 21:01:55 +01:00
|
|
|
/*
|
2007-01-26 20:29:36 +01:00
|
|
|
* This file is a part of EZC -- Easy templating in C++
|
|
|
|
* and is distributed under the (new) BSD licence.
|
|
|
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
2007-01-24 21:01:55 +01:00
|
|
|
*/
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
/*
|
2008-12-10 02:46:10 +01:00
|
|
|
* Copyright (c) 2007-2008, Tomasz Sowa
|
2007-01-26 20:29:36 +01:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
|
|
|
* project may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
#include "ezc.h"
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
namespace Ezc
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void CreateMsg(std::ostringstream & o, const char * type, const char * arg)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
o << "<!-- ezc: " << type << " ";
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
if( arg )
|
2008-12-10 02:46:10 +01:00
|
|
|
o << arg << " ";
|
|
|
|
|
|
|
|
o << "-->";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string CreateMsg(const char * type, const char * arg)
|
|
|
|
{
|
|
|
|
std::ostringstream buffer;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
CreateMsg(buffer, type, arg);
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
return buffer.str();
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
2007-01-27 14:52:18 +01:00
|
|
|
/*
|
|
|
|
this method splits the input file name into a directory and a file name
|
|
|
|
e.g
|
|
|
|
if 'name' is "/this/is/dummy/file.ezc"
|
|
|
|
the result will be:
|
|
|
|
dir = "/this/is/dummy"
|
|
|
|
file = "file.ezc"
|
|
|
|
*/
|
2008-12-10 02:46:10 +01:00
|
|
|
void SplitUnixDirectory(const char * name, std::string & dir, std::string & file)
|
|
|
|
{
|
|
|
|
dir.clear();
|
|
|
|
file.clear();
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for( i=0 ; name[i] != 0 ; ++i );
|
|
|
|
|
|
|
|
if( i == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
for( --i ; i>=0 && name[i]!='\\' && name[i]!='/' ; --i );
|
|
|
|
|
|
|
|
if( i < 0 )
|
|
|
|
{
|
|
|
|
file.assign(name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( i == 0 )
|
|
|
|
// we're leaving one '/' in the directory
|
|
|
|
// (we have only the root directory)
|
|
|
|
dir.assign(name, 1);
|
|
|
|
else
|
|
|
|
dir.assign(name, i);
|
|
|
|
|
|
|
|
file.assign(name + i + 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2007-01-27 14:52:18 +01:00
|
|
|
|
|
|
|
void SplitUnixDirectory(const std::string & name, std::string & dir, std::string & file)
|
|
|
|
{
|
|
|
|
SplitUnixDirectory(name.c_str(), dir, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
2007-01-26 20:29:36 +01:00
|
|
|
* Pattern
|
2007-01-24 21:01:55 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-01-27 14:52:18 +01:00
|
|
|
void Pattern::ParseFile(const std::string & file_name)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-27 14:52:18 +01:00
|
|
|
ParseFile( file_name.c_str() );
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::ParseFile(const char * file_name)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-27 14:52:18 +01:00
|
|
|
std::string file;
|
|
|
|
|
|
|
|
if( directory.empty() )
|
|
|
|
SplitUnixDirectory(file_name, directory, file);
|
|
|
|
else
|
|
|
|
file = file_name;
|
|
|
|
|
|
|
|
file.insert(file.begin(), '\"');
|
|
|
|
|
|
|
|
item_root.directives.clear();
|
|
|
|
item_root.directives.push_back( file );
|
|
|
|
|
|
|
|
CreateTreeReadInclude(item_root);
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
void Pattern::Directory(const char * d)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
directory = d;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::Directory(const std::string & d)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
directory = d;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
bool Pattern::CheckFileName(const char * name)
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
// very simple testing -- this path 'some..name' is incorrect as well
|
|
|
|
// (in the future it can be changed)
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
for( ; *name ; ++name )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
if( *name=='.' && *(name+1)=='.' )
|
|
|
|
return false;
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
return true;
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-27 14:52:18 +01:00
|
|
|
/*
|
|
|
|
'name' must be a relative path
|
|
|
|
*/
|
2007-01-26 20:29:36 +01:00
|
|
|
std::string Pattern::ReadFile(const char * name)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
// for security reason we can't open a file which has two dots
|
|
|
|
// somewhere in its name '..'
|
|
|
|
if( !CheckFileName(name) )
|
|
|
|
return CreateMsg("incorrect file name:", name);
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-27 14:52:18 +01:00
|
|
|
std::string file_name(directory);
|
|
|
|
|
|
|
|
if( !file_name.empty() )
|
|
|
|
file_name += '/';
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
file_name += name;
|
|
|
|
|
|
|
|
std::ifstream file(file_name.c_str());
|
|
|
|
|
|
|
|
if( !file )
|
|
|
|
return CreateMsg("can't open:", name);
|
|
|
|
// or we can give the whole path here (file_name)
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string result;
|
|
|
|
std::getline(file, result, '\0');
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
int Pattern::ReadCharInText()
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
if( *itext==0 || *itext=='[' )
|
|
|
|
return -1;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
if( *itext == '\\' )
|
|
|
|
{
|
|
|
|
if( *(itext+1)=='\\' || *(itext+1)=='[' || *(itext+1)==']' )
|
|
|
|
++itext;
|
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
return *(itext++);
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::SkipWhiteCharacters()
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
|
|
|
while( *itext==' ' || *itext=='\t' )
|
|
|
|
++itext;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
std::string Pattern::ReadDirective()
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
std::string directive;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
SkipWhiteCharacters();
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
while( (*itext>='a' && *itext<='z') ||
|
|
|
|
(*itext>='A' && *itext<='Z') ||
|
|
|
|
(*itext>='0' && *itext<='9') ||
|
2007-01-27 14:52:18 +01:00
|
|
|
*itext=='_' || *itext=='-' || *itext=='.' || *itext=='#' )
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
|
|
|
directive += *itext;
|
|
|
|
|
|
|
|
++itext;
|
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
return directive;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
std::string Pattern::ReadString(bool skip_first_quote)
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
std::string directive;
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
SkipWhiteCharacters();
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
if( *itext != '\"' )
|
2007-01-26 20:29:36 +01:00
|
|
|
return directive;
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
// string is signed by its first character equal (")
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !skip_first_quote )
|
|
|
|
directive += '\"';
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
for( ++itext ; *itext && *itext!='\"' && *itext!='\n' ; ++itext )
|
2007-01-25 22:42:54 +01:00
|
|
|
directive += *itext;
|
|
|
|
|
|
|
|
if( *itext != '\"' )
|
|
|
|
// the second quotation mark (") is missing
|
|
|
|
directive.clear();
|
|
|
|
else
|
|
|
|
++itext;
|
|
|
|
|
|
|
|
// the second quotation mark (") we don't add into the 'directive'
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
return directive;
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
std::string Pattern::ReadDirectiveOrString()
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
SkipWhiteCharacters();
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
if( *itext == '\"' )
|
|
|
|
{
|
|
|
|
// we've got string
|
2007-01-26 20:29:36 +01:00
|
|
|
return ReadString();
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
return ReadDirective();
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
SkipWhiteCharacters();
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
if( *itext != ']' )
|
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
item.type = Item::item_err;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
while( *itext!=0 && *itext!=']' )
|
|
|
|
++itext;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( *itext == ']' )
|
|
|
|
++itext;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::ReadDirectiveIfany(Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
item.type = Item::item_ifany;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
while( true )
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
std::string directive = ReadDirective();
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( directive.empty() )
|
|
|
|
break;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
item.directives.push_back(directive);
|
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.empty() )
|
|
|
|
item.type = Item::item_err;
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
2008-12-23 21:08:11 +01:00
|
|
|
|
|
|
|
void Pattern::ReadDirectiveIfno(Item & item)
|
|
|
|
{
|
|
|
|
ReadDirectiveIfany(item);
|
|
|
|
|
|
|
|
if( item.type == Item::item_ifany )
|
|
|
|
item.type = Item::item_ifno;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::ReadDirectiveIfone(Item & item)
|
|
|
|
{
|
|
|
|
ReadDirectiveIfany(item);
|
|
|
|
|
|
|
|
if( item.type == Item::item_ifany )
|
|
|
|
item.type = Item::item_ifone;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Pattern::ReadDirectiveIs(Item & item)
|
|
|
|
{
|
|
|
|
item.type = Item::item_is;
|
|
|
|
std::string directive = ReadDirective();
|
|
|
|
|
|
|
|
if( !directive.empty() )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
item.directives.push_back(directive);
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
directive = ReadDirectiveOrString();
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
if( !directive.empty() )
|
2007-01-26 20:29:36 +01:00
|
|
|
item.directives.push_back(directive);
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.size() != 2 )
|
|
|
|
item.type = Item::item_err;
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::ReadDirectiveIfindex(Item & item)
|
|
|
|
{
|
|
|
|
item.type = Item::item_ifindex;
|
|
|
|
std::string directive = ReadDirective();
|
|
|
|
|
|
|
|
if( !directive.empty() )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
item.directives.push_back(directive);
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
directive = ReadDirective();
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
if( !directive.empty() )
|
2007-01-26 20:29:36 +01:00
|
|
|
item.directives.push_back(directive);
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.size() != 2 )
|
|
|
|
item.type = Item::item_err;
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
void Pattern::ReadDirectiveFor(Item & item)
|
|
|
|
{
|
|
|
|
item.type = Item::item_for;
|
|
|
|
std::string directive = ReadDirective();
|
|
|
|
|
|
|
|
if( !directive.empty() )
|
|
|
|
item.directives.push_back(directive);
|
|
|
|
else
|
|
|
|
item.type = Item::item_err;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-27 14:52:18 +01:00
|
|
|
void Pattern::ReadDirectiveComment(Item & item)
|
|
|
|
{
|
|
|
|
item.type = Item::item_comment;
|
|
|
|
|
|
|
|
while( *itext && *itext!=']' && *itext!='\n' )
|
|
|
|
++itext;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::ReadDirectiveInclude(Item & item)
|
|
|
|
{
|
|
|
|
item.type = Item::item_include;
|
|
|
|
std::string directive = ReadString();
|
|
|
|
|
|
|
|
if( !directive.empty() )
|
|
|
|
item.directives.push_back(directive);
|
|
|
|
else
|
|
|
|
item.type = Item::item_err;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Pattern::ReadDirectiveDef(Item & item)
|
|
|
|
{
|
|
|
|
item.type = Item::item_def;
|
|
|
|
std::string directive = ReadDirective();
|
|
|
|
|
|
|
|
if( !directive.empty() )
|
|
|
|
{
|
|
|
|
item.directives.push_back(directive);
|
|
|
|
|
|
|
|
directive = ReadDirectiveOrString();
|
|
|
|
|
|
|
|
if( !directive.empty() )
|
|
|
|
item.directives.push_back(directive);
|
|
|
|
}
|
|
|
|
|
|
|
|
if( item.directives.size() != 2 )
|
|
|
|
item.type = Item::item_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::CreateTreeReadItemDirective(Item & item)
|
|
|
|
{
|
|
|
|
++itext;
|
|
|
|
|
|
|
|
std::string directive = ReadDirective();
|
|
|
|
|
|
|
|
if( directive == "if-any" )
|
|
|
|
ReadDirectiveIfany(item);
|
|
|
|
else
|
2008-12-23 21:08:11 +01:00
|
|
|
if( directive == "if-no" )
|
|
|
|
ReadDirectiveIfno(item);
|
|
|
|
else
|
2007-01-26 20:29:36 +01:00
|
|
|
if( directive == "if-one" )
|
|
|
|
ReadDirectiveIfone(item);
|
|
|
|
else
|
|
|
|
if( directive == "is" )
|
|
|
|
ReadDirectiveIs(item);
|
|
|
|
else
|
|
|
|
if( directive == "if-index" )
|
|
|
|
ReadDirectiveIfindex(item);
|
2007-01-24 21:01:55 +01:00
|
|
|
else
|
|
|
|
if( directive == "end" )
|
2007-01-26 20:29:36 +01:00
|
|
|
item.type = Item::item_end;
|
2007-01-24 21:01:55 +01:00
|
|
|
else
|
|
|
|
if( directive == "else" )
|
2007-01-26 20:29:36 +01:00
|
|
|
item.type = Item::item_else;
|
2007-01-24 21:01:55 +01:00
|
|
|
else
|
2007-01-25 09:25:40 +01:00
|
|
|
if( directive == "for" )
|
2007-01-26 20:29:36 +01:00
|
|
|
ReadDirectiveFor(item);
|
2007-01-25 22:42:54 +01:00
|
|
|
else
|
|
|
|
if( directive == "include" )
|
2007-01-26 20:29:36 +01:00
|
|
|
ReadDirectiveInclude(item);
|
2007-01-25 09:25:40 +01:00
|
|
|
else
|
2008-12-10 02:46:10 +01:00
|
|
|
if( directive == "def" )
|
|
|
|
ReadDirectiveDef(item);
|
|
|
|
else
|
2007-01-27 14:52:18 +01:00
|
|
|
if( directive == "#" )
|
|
|
|
ReadDirectiveComment(item);
|
|
|
|
else
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
// user defined
|
|
|
|
item.directives.push_back(directive);
|
|
|
|
item.type = Item::item_normal;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
CreateTreeReadItemDirectiveCheckEnding(item);
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::CreateTreeReadItemText(Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
int c;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
while( (c = ReadCharInText()) != -1 )
|
|
|
|
item.text += c;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
item.type = Item::item_text;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
bool Pattern::CreateTreeReadItem(Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
item.Clear();
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
if( *itext == '[' )
|
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
CreateTreeReadItemDirective(item);
|
2007-01-24 21:01:55 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( *itext )
|
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
CreateTreeReadItemText(item);
|
2007-01-24 21:01:55 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the end of the string
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
void Pattern::CreateTreeReadInclude(Item & item)
|
2007-01-25 09:25:40 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.empty() || item.directives[0].empty() || item.directives[0][0]!='\"' )
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::string file_text = ReadFile( item.directives[0].c_str()+1 );
|
|
|
|
|
|
|
|
const char * itext_copy = itext;
|
|
|
|
itext = file_text.c_str();
|
|
|
|
CreateTree(item);
|
|
|
|
itext = itext_copy;
|
|
|
|
}
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
void Pattern::CreateTreeReadIf(Item & item)
|
|
|
|
{
|
|
|
|
Item * pitem = item.AddItem();
|
|
|
|
CreateTree(*pitem);
|
|
|
|
|
|
|
|
if( pitem->LastItemType() == Item::item_else )
|
2007-01-25 09:25:40 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
pitem->DeleteLastItem();
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
pitem = item.AddItem();
|
|
|
|
CreateTree(*pitem);
|
2007-01-25 09:25:40 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
pitem->DeleteLastItem(); // it deletes [end] from the tree
|
2007-01-25 09:25:40 +01:00
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
void Pattern::CreateTreeReadFor(Item & item)
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
Item * pitem = item.AddItem();
|
|
|
|
CreateTree(*pitem);
|
|
|
|
|
|
|
|
pitem->DeleteLastItem(); // it deletes [end] from the tree
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::CreateTree(Item & item)
|
|
|
|
{
|
|
|
|
item.Clear();
|
|
|
|
item.type = Item::item_container;
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Item item_temp;
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
while( CreateTreeReadItem(item_temp) )
|
|
|
|
{
|
2007-01-27 14:52:18 +01:00
|
|
|
if( item_temp.type == Item::item_comment )
|
|
|
|
continue;
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Item * pitem = item.AddItem(item_temp);
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item_temp.type==Item::item_end || item_temp.type==Item::item_else )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( pitem->type == Item::item_ifany ||
|
2008-12-23 21:08:11 +01:00
|
|
|
pitem->type == Item::item_ifno ||
|
2007-01-26 20:29:36 +01:00
|
|
|
pitem->type == Item::item_ifone ||
|
|
|
|
pitem->type == Item::item_ifindex ||
|
|
|
|
pitem->type == Item::item_is )
|
|
|
|
CreateTreeReadIf(*pitem);
|
|
|
|
|
|
|
|
if( pitem->type == Item::item_for )
|
|
|
|
CreateTreeReadFor(*pitem);
|
|
|
|
|
|
|
|
if( pitem->type == Item::item_include )
|
|
|
|
CreateTreeReadInclude(*pitem);
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Pattern::Item
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Pattern::Item * Pattern::Item::AddItem(const Pattern::Item * porg)
|
|
|
|
{
|
|
|
|
Item * pitem;
|
|
|
|
|
|
|
|
if( porg )
|
|
|
|
pitem = new Item(*porg);
|
|
|
|
else
|
|
|
|
pitem = new Item();
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
item_table.push_back(pitem);
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
return pitem;
|
2007-01-25 09:25:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Pattern::Item * Pattern::Item::AddItem(const Pattern::Item & porg)
|
2007-01-25 09:25:40 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
return AddItem(&porg);
|
|
|
|
}
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::Item::ClearItems()
|
|
|
|
{
|
|
|
|
std::vector<Item*>::iterator i = item_table.begin();
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
for( ; i != item_table.end() ; ++i )
|
|
|
|
delete *i;
|
|
|
|
|
|
|
|
item_table.clear();
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::Item::Clear()
|
|
|
|
{
|
|
|
|
ClearItems();
|
|
|
|
type = item_none;
|
|
|
|
text.clear();
|
|
|
|
directives.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Pattern::Item::ItemType Pattern::Item::LastItemType()
|
|
|
|
{
|
|
|
|
if( item_table.empty() )
|
|
|
|
return item_none;
|
|
|
|
|
|
|
|
return item_table.back()->type;
|
|
|
|
}
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::Item::DeleteLastItem()
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item_table.empty() )
|
2007-01-25 22:42:54 +01:00
|
|
|
return;
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
delete item_table.back();
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
item_table.erase( item_table.end() - 1 );
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Pattern::Item::Item()
|
|
|
|
{
|
|
|
|
type = item_none;
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Pattern::Item::Item(const Pattern::Item & i) : type(i.type), text(i.text), directives(i.directives)
|
|
|
|
{
|
|
|
|
CopyItemTable(i);
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
Pattern::Item & Pattern::Item::operator=(const Pattern::Item & i)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
type = i.type;
|
|
|
|
text = i.text;
|
|
|
|
directives = i.directives;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
CopyItemTable(i);
|
|
|
|
|
|
|
|
return *this;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Pattern::Item::CopyItemTable(const Pattern::Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
std::vector<Item*>::const_iterator i = item.item_table.begin();
|
|
|
|
|
|
|
|
for( ; i != item.item_table.end() ; ++i)
|
|
|
|
AddItem( *i );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Pattern::Item::~Item()
|
|
|
|
{
|
|
|
|
ClearItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Info
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Info::Clear()
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
// default settings indicate 'false'
|
2007-01-26 20:29:36 +01:00
|
|
|
result = false;
|
2008-12-10 02:46:10 +01:00
|
|
|
out_string.clear();
|
|
|
|
|
|
|
|
iter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Info::Info(std::ostringstream & o) : out(o)
|
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Info::IsTrue() const
|
|
|
|
{
|
|
|
|
if( result || !out_string.empty() )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Info::IsFalse() const
|
|
|
|
{
|
|
|
|
return !IsTrue();
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
2008-12-10 02:46:10 +01:00
|
|
|
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
/*
|
|
|
|
*
|
2008-12-10 02:46:10 +01:00
|
|
|
* Functions
|
2007-01-26 20:29:36 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
Functions::Function::Function()
|
|
|
|
{
|
|
|
|
type = Functions::variable;
|
|
|
|
user_function = 0;
|
|
|
|
iter = 0;
|
|
|
|
is_for = false;
|
|
|
|
is_running = false;
|
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Functions::Insert(const std::string & key, UserFunction ufunction)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
Function f;
|
|
|
|
f.type = function;
|
|
|
|
f.user_function = ufunction;
|
|
|
|
|
|
|
|
functions_table[key] = f;
|
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
void Functions::Insert(const std::string & key, const char * var)
|
|
|
|
{
|
|
|
|
Function f;
|
|
|
|
f.type = variable;
|
|
|
|
f.variable = var;
|
|
|
|
|
|
|
|
functions_table[key] = f;
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
void Functions::Insert(const std::string & key, const std::string & var)
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
Function f;
|
|
|
|
f.type = variable;
|
|
|
|
f.variable = var;
|
|
|
|
|
|
|
|
functions_table[key] = f;
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
bool Functions::Find(const std::string & key, Function ** fun)
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
FunctionsTable::iterator i = functions_table.find( key );
|
|
|
|
|
|
|
|
if( i == functions_table.end() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*fun = &(i->second);
|
2007-01-26 20:29:36 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
return true;
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Functions::Clear()
|
|
|
|
{
|
|
|
|
functions_table.clear();
|
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Generator
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Generator::Find(const std::string & key, Functions::Function ** function)
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !functions.Find(key, function) )
|
|
|
|
{
|
|
|
|
CreateMsg(output_stream, "can't find", key.c_str() );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
void Generator::CallUserFunction(Functions::Function * function, Info & info)
|
|
|
|
{
|
|
|
|
// przetestowac to jeszcze !!!! (wczesniej sprawdzenie bylo w Find) !!
|
|
|
|
if( function->is_running )
|
|
|
|
{
|
|
|
|
// recurrences are not allowed
|
|
|
|
CreateMsg(output_stream, "the function is currently running" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
function->is_running = true;
|
|
|
|
(function->user_function)(info);
|
|
|
|
function->is_running = false;
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Generator::CallVariable(Functions::Function * function, Info & info)
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
info.out_string = function->variable;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Generator::Call(Functions::Function * function, Info & info)
|
|
|
|
{
|
|
|
|
info.Clear();
|
|
|
|
info.iter = function->iter;
|
|
|
|
|
|
|
|
if( function->type == Functions::function )
|
|
|
|
CallUserFunction(function, info);
|
|
|
|
else
|
|
|
|
CallVariable(function, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// return: true if a function or variable was found and called
|
|
|
|
bool Generator::Call(const std::string & name, Info & info, Functions::Function ** pfun)
|
|
|
|
{
|
|
|
|
Functions::Function * function;
|
2007-01-26 20:29:36 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( Find(name, &function) )
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
Call(function, info);
|
|
|
|
|
|
|
|
if( pfun )
|
|
|
|
*pfun = function;
|
|
|
|
|
|
|
|
return true;
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
Generator::Generator(std::ostringstream & o, Pattern & p, Functions & f) : output_stream(o), pattern(p), functions(f), info1(o), info2(o)
|
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Generator::Generate()
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
loop = 0;
|
|
|
|
|
|
|
|
MakeText( pattern.item_root );
|
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Generator::MakeTextContainer(Pattern::Item & item)
|
|
|
|
{
|
|
|
|
std::vector<Pattern::Item*>::iterator i = item.item_table.begin();
|
|
|
|
|
|
|
|
for( ; i != item.item_table.end() ; ++i )
|
|
|
|
{
|
|
|
|
MakeText(**i);
|
|
|
|
|
|
|
|
if( loop < 0 )
|
|
|
|
break;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
void Generator::MakeTextNormal(Pattern::Item & item)
|
|
|
|
{
|
|
|
|
if( item.directives.size() != 1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
Call(item.directives[0], info1);
|
|
|
|
|
|
|
|
if( !info1.out_string.empty() )
|
|
|
|
output_stream << info1.out_string;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Generator::MakeTextIf_go(Pattern::Item & item, bool result)
|
|
|
|
{
|
|
|
|
if( result )
|
|
|
|
{
|
|
|
|
if( item.item_table.size() > 0 )
|
|
|
|
MakeText( *item.item_table[0] );
|
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
else
|
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
// second element can be (or not -- it's from [else])
|
|
|
|
if( item.item_table.size() > 1 )
|
|
|
|
MakeText( *item.item_table[1] );
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
void Generator::MakeTextIfany(Pattern::Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
std::vector<std::string>::iterator d = item.directives.begin();
|
|
|
|
unsigned how_many_true = 0;
|
2007-01-24 21:01:55 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
for( ; d != item.directives.end() ; ++d )
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !Call(*d, info1) )
|
2008-12-23 21:08:11 +01:00
|
|
|
// maybe it should only be treated as a false? (when there is no such a function/variable)
|
2007-01-26 20:29:36 +01:00
|
|
|
return;
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( info1.IsTrue() )
|
2007-01-26 20:29:36 +01:00
|
|
|
++how_many_true;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
MakeTextIf_go(item, how_many_true == item.directives.size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-23 21:08:11 +01:00
|
|
|
void Generator::MakeTextIfno(Pattern::Item & item)
|
|
|
|
{
|
|
|
|
std::vector<std::string>::iterator d = item.directives.begin();
|
|
|
|
unsigned how_many_true = 0;
|
|
|
|
|
|
|
|
for( ; d != item.directives.end() ; ++d )
|
|
|
|
{
|
|
|
|
if( Call(*d, info1) && info1.IsTrue() )
|
|
|
|
{
|
|
|
|
// there is no sense to go through all functions
|
|
|
|
++how_many_true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MakeTextIf_go(item, how_many_true == 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Generator::MakeTextIfone(Pattern::Item & item)
|
|
|
|
{
|
|
|
|
std::vector<std::string>::iterator d = item.directives.begin();
|
|
|
|
int how_many_true = 0;
|
|
|
|
|
|
|
|
for( ; d != item.directives.end() ; ++d )
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( Call(*d, info1) && info1.IsTrue() )
|
2008-12-23 21:08:11 +01:00
|
|
|
{
|
|
|
|
// there is no sense to go through all functions
|
2007-01-26 20:29:36 +01:00
|
|
|
++how_many_true;
|
2008-12-23 21:08:11 +01:00
|
|
|
break;
|
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
MakeTextIf_go(item, how_many_true > 0 );
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
|
|
|
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Generator::MakeTextIs(Pattern::Item & item)
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.size() != 2 )
|
|
|
|
return;
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !Call(item.directives[0], info1) )
|
2007-01-25 22:42:54 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
bool result = false;
|
2008-12-10 02:46:10 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( !item.directives[1].empty() && item.directives[1][0]=='\"' )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
// second directive is a string
|
|
|
|
if( std::strcmp(info1.out_string.c_str(), item.directives[1].c_str()+1) == 0 )
|
2007-01-26 20:29:36 +01:00
|
|
|
result = true;
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( Call(item.directives[1], info2) )
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( info1.result==info2.result && info1.out_string==info2.out_string )
|
2007-01-26 20:29:36 +01:00
|
|
|
result = true;
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
MakeTextIf_go(item, result);
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
bool Generator::MakeTextIfindexnumber(Pattern::Item & item, Functions::Function * function, bool & result)
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
|
|
|
if( item.directives.size() != 2 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const char * number_text = item.directives[1].c_str();
|
|
|
|
char * last_char;
|
|
|
|
|
|
|
|
int number = (int)strtol(number_text, &last_char, 10);
|
|
|
|
|
|
|
|
if( *last_char == '\0' )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( function->iter == number )
|
2007-01-26 20:29:36 +01:00
|
|
|
result = true;
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
// we don't have to set result as false (false is default)
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
CreateMsg(output_stream, "if-index: syntax error");
|
2007-01-26 20:29:36 +01:00
|
|
|
|
|
|
|
return false;
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
return true;
|
|
|
|
}
|
2007-01-25 22:42:54 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Generator::MakeTextIfindex(Pattern::Item & item)
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.size() != 2 )
|
2007-01-25 22:42:54 +01:00
|
|
|
return;
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
// we actually don't call a function (or variable) here
|
|
|
|
// but only reading an iteration index
|
|
|
|
|
|
|
|
Functions::Function * function;
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !Find(item.directives[0], &function) )
|
2007-01-26 20:29:36 +01:00
|
|
|
return;
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives[1] == "odd" )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( (function->iter & 1) == 1 )
|
2007-01-25 22:42:54 +01:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
else
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives[1] == "even" )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( (function->iter & 1) == 0 )
|
2007-01-25 22:42:54 +01:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
else
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives[1] == "first" )
|
2007-01-25 22:42:54 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( function->iter == 0 )
|
2007-01-25 22:42:54 +01:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !MakeTextIfindexnumber(item, function, result) )
|
2007-01-26 20:29:36 +01:00
|
|
|
return;
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
MakeTextIf_go(item, result);
|
2007-01-25 22:42:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Generator::MakeTextFor(Pattern::Item & item)
|
2007-01-25 09:25:40 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
const int max_loop = 3000;
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.directives.size() != 1 )
|
2007-01-25 09:25:40 +01:00
|
|
|
return;
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
Functions::Function * function;
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( !Find(item.directives[0], &function) )
|
2007-01-26 20:29:36 +01:00
|
|
|
return;
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( function->is_for )
|
|
|
|
{
|
|
|
|
CreateMsg(output_stream, item.directives[0].c_str(), "this function is already used in a [for] statement");
|
|
|
|
return;
|
|
|
|
}
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
for( function->is_for = true, function->iter=0 ; loop != -1 ; ++function->iter )
|
2007-01-26 20:29:36 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
if( function->iter >= max_loop )
|
|
|
|
{
|
|
|
|
CreateMsg(output_stream, item.directives[0].c_str(), "function exceeded a limit for a [for] statement");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Call(function, info1);
|
2007-01-26 20:29:36 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
if( info1.IsFalse() )
|
2007-01-26 20:29:36 +01:00
|
|
|
break;
|
2007-01-25 09:25:40 +01:00
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
if( item.item_table.size() > 0 )
|
|
|
|
MakeText( *item.item_table[0] );
|
2008-12-10 02:46:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function->is_for = false;
|
|
|
|
function->iter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-25 22:42:54 +01:00
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
void Generator::MakeTextDefine(Pattern::Item & item)
|
|
|
|
{
|
|
|
|
if( item.directives.size() != 2 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( !item.directives[1].empty() && item.directives[1][0]=='\"' )
|
|
|
|
{
|
|
|
|
// second directive is a string
|
|
|
|
functions.Insert(item.directives[0], item.directives[1].c_str() + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Functions::Function * function;
|
|
|
|
|
|
|
|
if( Find(item.directives[1], &function) )
|
|
|
|
{
|
|
|
|
if( function->type == Functions::function )
|
|
|
|
functions.Insert(item.directives[0], function->user_function);
|
|
|
|
else
|
|
|
|
functions.Insert(item.directives[0], function->variable);
|
|
|
|
}
|
2007-01-25 09:25:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-10 02:46:10 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
void Generator::MakeText(Pattern::Item & item)
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2008-12-10 02:46:10 +01:00
|
|
|
const int max_loop = 10000;
|
|
|
|
|
|
|
|
if( loop == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( ++loop > max_loop )
|
|
|
|
{
|
|
|
|
loop = -1;
|
|
|
|
CreateMsg(output_stream, "Generator exceeded allowed number of elements");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
switch( item.type )
|
2007-01-24 21:01:55 +01:00
|
|
|
{
|
2007-01-26 20:29:36 +01:00
|
|
|
case Pattern::Item::item_text:
|
2008-12-10 02:46:10 +01:00
|
|
|
output_stream << item.text;
|
2007-01-26 20:29:36 +01:00
|
|
|
break;
|
|
|
|
case Pattern::Item::item_container:
|
|
|
|
MakeTextContainer(item);
|
|
|
|
break;
|
|
|
|
case Pattern::Item::item_normal:
|
|
|
|
MakeTextNormal(item);
|
|
|
|
break;
|
|
|
|
case Pattern::Item::item_ifany:
|
|
|
|
MakeTextIfany(item);
|
|
|
|
break;
|
2008-12-23 21:08:11 +01:00
|
|
|
case Pattern::Item::item_ifno:
|
|
|
|
MakeTextIfno(item);
|
|
|
|
break;
|
2007-01-26 20:29:36 +01:00
|
|
|
case Pattern::Item::item_ifone:
|
|
|
|
MakeTextIfone(item);
|
|
|
|
break;
|
|
|
|
case Pattern::Item::item_ifindex:
|
|
|
|
MakeTextIfindex(item);
|
|
|
|
break;
|
|
|
|
case Pattern::Item::item_is:
|
|
|
|
MakeTextIs(item);
|
|
|
|
break;
|
|
|
|
case Pattern::Item::item_for:
|
|
|
|
MakeTextFor(item);
|
|
|
|
break;
|
2008-12-10 02:46:10 +01:00
|
|
|
case Pattern::Item::item_def:
|
|
|
|
MakeTextDefine(item);
|
|
|
|
break;
|
2007-01-26 20:29:36 +01:00
|
|
|
case Pattern::Item::item_err:
|
2008-12-10 02:46:10 +01:00
|
|
|
CreateMsg(output_stream, "a wrong directive");
|
2007-01-26 20:29:36 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2007-01-24 21:01:55 +01:00
|
|
|
}
|
2007-01-26 20:29:36 +01:00
|
|
|
}
|
2007-01-24 21:01:55 +01:00
|
|
|
|
|
|
|
|
2007-01-26 20:29:36 +01:00
|
|
|
} // namespace Ezc
|
|
|
|
|