Skip to content

Commit

Permalink
Turn includes into AST expressions
Browse files Browse the repository at this point in the history
fixes #10008
  • Loading branch information
gunnarbeutner committed Oct 22, 2015
1 parent fd5d6de commit 74ef3e3
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 44 deletions.
31 changes: 11 additions & 20 deletions lib/config/config_parser.yy
Expand Up @@ -443,39 +443,30 @@ lterm: T_LIBRARY rterm
{
$$ = new SetExpression($1, $2, $3, @$);
}
| T_INCLUDE T_STRING
| T_INCLUDE rterm
{
$$ = context->HandleInclude(*$2, false, @$);
delete $2;
$$ = new IncludeExpression(Utility::DirName(context->GetPath()), $2, NULL, NULL, IncludeRegular, false, context->GetZone(), context->GetPackage(), @$);
}
| T_INCLUDE T_STRING_ANGLE
{
$$ = context->HandleInclude(*$2, true, @$);
$$ = new IncludeExpression(Utility::DirName(context->GetPath()), MakeLiteral(*$2), NULL, NULL, IncludeRegular, true, context->GetZone(), context->GetPackage(), @$);
delete $2;
}
| T_INCLUDE_RECURSIVE T_STRING
| T_INCLUDE_RECURSIVE rterm
{
$$ = context->HandleIncludeRecursive(*$2, "*.conf", @$);
delete $2;
$$ = new IncludeExpression(Utility::DirName(context->GetPath()), $2, MakeLiteral("*.conf"), NULL, IncludeRecursive, false, context->GetZone(), context->GetPackage(), @$);
}
| T_INCLUDE_RECURSIVE T_STRING ',' T_STRING
| T_INCLUDE_RECURSIVE rterm ',' rterm
{
$$ = context->HandleIncludeRecursive(*$2, *$4, @$);
delete $2;
delete $4;
$$ = new IncludeExpression(Utility::DirName(context->GetPath()), $2, $4, NULL, IncludeRecursive, false, context->GetZone(), context->GetPackage(), @$);
}
| T_INCLUDE_ZONES T_STRING ',' T_STRING
| T_INCLUDE_ZONES rterm ',' rterm
{
$$ = context->HandleIncludeZones(*$2, *$4, "*.conf", @$);
delete $2;
delete $4;
$$ = new IncludeExpression(Utility::DirName(context->GetPath()), $4, MakeLiteral("*.conf"), $2, IncludeZones, false, context->GetZone(), context->GetPackage(), @$);
}
| T_INCLUDE_ZONES T_STRING ',' T_STRING ',' T_STRING
| T_INCLUDE_ZONES rterm ',' rterm ',' rterm
{
$$ = context->HandleIncludeZones(*$2, *$4, *$6, @$);
delete $2;
delete $4;
delete $6;
$$ = new IncludeExpression(Utility::DirName(context->GetPath()), $4, $6, $2, IncludeZones, false, context->GetZone(), context->GetPackage(), @$);
}
| T_IMPORT rterm
{
Expand Down
44 changes: 25 additions & 19 deletions lib/config/configcompiler.cpp
Expand Up @@ -119,24 +119,26 @@ void ConfigCompiler::CollectIncludes(std::vector<Expression *>& expressions,
/**
* Handles an include directive.
*
* @param include The path from the include directive.
* @param relativeBath The path this include is relative to.
* @param path The path from the include directive.
* @param search Whether to search global include dirs.
* @param debuginfo Debug information.
*/
Expression *ConfigCompiler::HandleInclude(const String& include, bool search, const DebugInfo& debuginfo)
Expression *ConfigCompiler::HandleInclude(const String& relativeBase, const String& path,
bool search, const String& zone, const String& package, const DebugInfo& debuginfo)
{
String path;
String upath;

if (search || (include.GetLength() > 0 && include[0] == '/'))
path = include;
if (search || (path.GetLength() > 0 && path[0] == '/'))
upath = path;
else
path = Utility::DirName(GetPath()) + "/" + include;
upath = relativeBase + "/" + path;

String includePath = path;
String includePath = upath;

if (search) {
BOOST_FOREACH(const String& dir, m_IncludeSearchDirs) {
String spath = dir + "/" + include;
String spath = dir + "/" + path;

if (Utility::PathExists(spath)) {
includePath = spath;
Expand All @@ -147,9 +149,9 @@ Expression *ConfigCompiler::HandleInclude(const String& include, bool search, co

std::vector<Expression *> expressions;

if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, m_Zone, m_Package), GlobFile) && includePath.FindFirstOf("*?") == String::NPos) {
if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zone, package), GlobFile) && includePath.FindFirstOf("*?") == String::NPos) {
std::ostringstream msgbuf;
msgbuf << "Include file '" + include + "' does not exist";
msgbuf << "Include file '" + path + "' does not exist";
BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), debuginfo));
}

Expand All @@ -161,25 +163,27 @@ Expression *ConfigCompiler::HandleInclude(const String& include, bool search, co
/**
* Handles recursive includes.
*
* @param relativeBase The path this include is relative to.
* @param path The directory path.
* @param pattern The file pattern.
* @param debuginfo Debug information.
*/
Expression *ConfigCompiler::HandleIncludeRecursive(const String& path, const String& pattern, const DebugInfo&)
Expression *ConfigCompiler::HandleIncludeRecursive(const String& relativeBase, const String& path,
const String& pattern, const String& zone, const String& package, const DebugInfo&)
{
String ppath;

if (path.GetLength() > 0 && path[0] == '/')
ppath = path;
else
ppath = Utility::DirName(GetPath()) + "/" + path;
ppath = relativeBase + "/" + path;

std::vector<Expression *> expressions;
Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, m_Zone, m_Package), GlobFile);
Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zone, package), GlobFile);
return new DictExpression(expressions);
}

void ConfigCompiler::HandleIncludeZone(const String& tag, const String& path, const String& pattern, std::vector<Expression *>& expressions)
void ConfigCompiler::HandleIncludeZone(const String& relativeBase, const String& tag, const String& path, const String& pattern, const String& package, std::vector<Expression *>& expressions)
{
String zoneName = Utility::BaseName(path);

Expand All @@ -188,32 +192,34 @@ void ConfigCompiler::HandleIncludeZone(const String& tag, const String& path, co
if (path.GetLength() > 0 && path[0] == '/')
ppath = path;
else
ppath = Utility::DirName(GetPath()) + "/" + path;
ppath = relativeBase + "/" + path;

RegisterZoneDir(tag, ppath, zoneName);

Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zoneName, m_Package), GlobFile);
Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zoneName, package), GlobFile);
}

/**
* Handles zone includes.
*
* @param relativeBase The path this include is relative to.
* @param tag The tag name.
* @param path The directory path.
* @param pattern The file pattern.
* @param debuginfo Debug information.
*/
Expression *ConfigCompiler::HandleIncludeZones(const String& tag, const String& path, const String& pattern, const DebugInfo&)
Expression *ConfigCompiler::HandleIncludeZones(const String& relativeBase, const String& tag,
const String& path, const String& pattern, const String& package, const DebugInfo&)
{
String ppath;

if (path.GetLength() > 0 && path[0] == '/')
ppath = path;
else
ppath = Utility::DirName(GetPath()) + "/" + path;
ppath = relativeBase + "/" + path;

std::vector<Expression *> expressions;
Utility::Glob(ppath + "/*", boost::bind(&ConfigCompiler::HandleIncludeZone, this, tag, _1, pattern, boost::ref(expressions)), GlobDirectory);
Utility::Glob(ppath + "/*", boost::bind(&ConfigCompiler::HandleIncludeZone, relativeBase, tag, _1, pattern, package, boost::ref(expressions)), GlobDirectory);
return new DictExpression(expressions);
}

Expand Down
12 changes: 7 additions & 5 deletions lib/config/configcompiler.hpp
Expand Up @@ -105,10 +105,12 @@ class I2_CONFIG_API ConfigCompiler
static void CollectIncludes(std::vector<Expression *>& expressions,
const String& file, const String& zone, const String& package);

/* internally used methods */
Expression *HandleInclude(const String& include, bool search, const DebugInfo& debuginfo = DebugInfo());
Expression *HandleIncludeRecursive(const String& path, const String& pattern, const DebugInfo& debuginfo = DebugInfo());
Expression *HandleIncludeZones(const String& tag, const String& path, const String& pattern, const DebugInfo& debuginfo = DebugInfo());
static Expression *HandleInclude(const String& relativeBase, const String& path, bool search,
const String& zone, const String& package, const DebugInfo& debuginfo = DebugInfo());
static Expression *HandleIncludeRecursive(const String& relativeBase, const String& path,
const String& pattern, const String& zone, const String& package, const DebugInfo& debuginfo = DebugInfo());
static Expression *HandleIncludeZones(const String& relativeBase, const String& tag,
const String& path, const String& pattern, const String& package, const DebugInfo& debuginfo = DebugInfo());

size_t ReadInput(char *buffer, size_t max_bytes);
void *GetScanner(void) const;
Expand All @@ -135,7 +137,7 @@ class I2_CONFIG_API ConfigCompiler
void InitializeScanner(void);
void DestroyScanner(void);

void HandleIncludeZone(const String& tag, const String& path, const String& pattern, std::vector<Expression *>& expressions);
static void HandleIncludeZone(const String& relativeBase, const String& tag, const String& path, const String& pattern, const String& package, std::vector<Expression *>& expressions);

public:
bool m_Eof;
Expand Down
72 changes: 72 additions & 0 deletions lib/config/expression.cpp
Expand Up @@ -19,6 +19,7 @@

#include "config/expression.hpp"
#include "config/configitem.hpp"
#include "config/configcompiler.hpp"
#include "config/vmops.hpp"
#include "base/array.hpp"
#include "base/json.hpp"
Expand Down Expand Up @@ -783,3 +784,74 @@ ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dh
return Empty;
}

ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
if (frame.Sandboxed)
BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));

Expression *expr;
String name, path, pattern;

switch (m_Type) {
case IncludeRegular:
{
ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
CHECK_RESULT(pathres);
path = pathres.GetValue();
}

expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
break;

case IncludeRecursive:
{
ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
CHECK_RESULT(pathres);
path = pathres.GetValue();
}

{
ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
CHECK_RESULT(patternres);
pattern = patternres.GetValue();
}

expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
break;

case IncludeZones:
{
ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
CHECK_RESULT(nameres);
name = nameres.GetValue();
}

{
ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
CHECK_RESULT(pathres);
path = pathres.GetValue();
}

{
ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
CHECK_RESULT(patternres);
pattern = patternres.GetValue();
}

expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
break;
}

ExpressionResult res(Empty);

try {
res = expr->Evaluate(frame, dhint);
} catch (const std::exception&) {
delete expr;
throw;
}

delete expr;

return res;
}
37 changes: 37 additions & 0 deletions lib/config/expression.hpp
Expand Up @@ -899,6 +899,43 @@ class I2_CONFIG_API LibraryExpression : public UnaryExpression
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
};

enum IncludeType
{
IncludeRegular,
IncludeRecursive,
IncludeZones
};

class I2_CONFIG_API IncludeExpression : public DebuggableExpression
{
public:
IncludeExpression(const String& relativeBase, Expression *path, Expression *pattern, Expression *name,
IncludeType type, bool searchIncludes, const String& zone, const String& package, const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo), m_RelativeBase(relativeBase), m_Path(path), m_Pattern(pattern),
m_Name(name), m_Type(type), m_SearchIncludes(searchIncludes), m_Zone(zone), m_Package(package)
{ }

~IncludeExpression(void)
{
delete m_Path;
delete m_Pattern;
delete m_Name;
}

protected:
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;

private:
String m_RelativeBase;
Expression *m_Path;
Expression *m_Pattern;
Expression *m_Name;
IncludeType m_Type;
bool m_SearchIncludes;
String m_Zone;
String m_Package;
};

}

#endif /* EXPRESSION_H */

0 comments on commit 74ef3e3

Please sign in to comment.