mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
classes for tracking "@if (...) &analyze" notion of code being/not being "activated"
This commit is contained in:
parent
9aff0287f0
commit
052cda9df0
3 changed files with 511 additions and 0 deletions
199
src/ActivationManager.cc
Normal file
199
src/ActivationManager.cc
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
#include "zeek/ActivationManager.h"
|
||||||
|
|
||||||
|
#include "zeek/Desc.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace zeek::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
void ActivationEvent::Dump(int indent_level) const
|
||||||
|
{
|
||||||
|
Indent(indent_level);
|
||||||
|
|
||||||
|
switch ( et )
|
||||||
|
{
|
||||||
|
case ActivationEvent::COND:
|
||||||
|
printf("Cond");
|
||||||
|
break;
|
||||||
|
case ActivationEvent::CREATE_GLOBAL:
|
||||||
|
printf("Create Global");
|
||||||
|
break;
|
||||||
|
case ActivationEvent::ADDING_GLOBAL_VAL:
|
||||||
|
printf("Add Global Val");
|
||||||
|
break;
|
||||||
|
case ActivationEvent::REDEF:
|
||||||
|
printf("Redef");
|
||||||
|
break;
|
||||||
|
case ActivationEvent::HANDLER_REDEF:
|
||||||
|
printf("Handler Redef");
|
||||||
|
break;
|
||||||
|
case ActivationEvent::BODY:
|
||||||
|
printf("Body");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( id )
|
||||||
|
printf(" ID=%s", obj_desc(id.get()).c_str());
|
||||||
|
|
||||||
|
if ( expr )
|
||||||
|
printf(" expr=%s", obj_desc(expr.get()).c_str());
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if ( et != ActivationEvent::COND )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Indent(indent_level);
|
||||||
|
printf("TRUE:\n");
|
||||||
|
for ( auto& s : T_sub_events )
|
||||||
|
s->Dump(indent_level + 1);
|
||||||
|
|
||||||
|
if ( ! in_true_branch )
|
||||||
|
{
|
||||||
|
Indent(indent_level);
|
||||||
|
printf("FALSE:\n");
|
||||||
|
for ( auto& s : F_sub_events )
|
||||||
|
s->Dump(indent_level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Indent(indent_level);
|
||||||
|
printf("END\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationEvent::Indent(int indent_level) const
|
||||||
|
{
|
||||||
|
while ( indent_level-- > 0 )
|
||||||
|
printf("\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
Activation::Activation(ExprPtr cond, bool _is_activated, bool _parent_activated, int _cond_depth)
|
||||||
|
{
|
||||||
|
is_activated = _is_activated;
|
||||||
|
parent_activated = _parent_activated;
|
||||||
|
cond_depth = _cond_depth;
|
||||||
|
|
||||||
|
cond_event = std::make_shared<ActivationEvent>(ActivationEvent::COND);
|
||||||
|
cond_event->AddExpr(cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
Activation::~Activation()
|
||||||
|
{
|
||||||
|
ResetGlobals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Activation::ResetGlobals()
|
||||||
|
{
|
||||||
|
if ( ! is_activated )
|
||||||
|
{ // undo changes we temporarily introduced
|
||||||
|
for ( auto& gv : global_vals )
|
||||||
|
gv->SetVal(nullptr);
|
||||||
|
|
||||||
|
auto gs = global_scope();
|
||||||
|
|
||||||
|
if ( gs )
|
||||||
|
for ( auto& gid : global_IDs )
|
||||||
|
gs->RemoveGlobal(gid->Name(), gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
global_vals.clear();
|
||||||
|
global_IDs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivationManager::~ActivationManager()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
for ( auto& ae : activation_events )
|
||||||
|
ae->Dump(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::Start(ExprPtr cond, bool activate, int cond_depth)
|
||||||
|
{
|
||||||
|
activate = activate && IsActivated();
|
||||||
|
auto a = std::make_unique<Activation>(cond, activate, IsActivated(), cond_depth);
|
||||||
|
|
||||||
|
auto ce = a->CondEvent();
|
||||||
|
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
activation_events.push_back(ce);
|
||||||
|
else
|
||||||
|
activation_stack.back()->CondEvent()->AddSubEvent(std::move(ce));
|
||||||
|
|
||||||
|
activation_stack.push_back(std::move(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::SwitchToElse()
|
||||||
|
{
|
||||||
|
ASSERT(! activation_stack.empty());
|
||||||
|
activation_stack.back()->SwitchToElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::End()
|
||||||
|
{
|
||||||
|
ASSERT(! activation_stack.empty());
|
||||||
|
activation_stack.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::CreatingGlobalID(IDPtr gid)
|
||||||
|
{
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto cg = std::make_shared<ActivationEvent>(ActivationEvent::CREATE_GLOBAL);
|
||||||
|
cg->AddID(gid);
|
||||||
|
|
||||||
|
activation_stack.back()->CondEvent()->AddSubEvent(std::move(cg));
|
||||||
|
activation_stack.back()->AddGlobalID(std::move(gid));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::AddingGlobalVal(IDPtr gid)
|
||||||
|
{
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto gv = std::make_shared<ActivationEvent>(ActivationEvent::ADDING_GLOBAL_VAL);
|
||||||
|
gv->AddID(gid);
|
||||||
|
|
||||||
|
activation_stack.back()->CondEvent()->AddSubEvent(std::move(gv));
|
||||||
|
activation_stack.back()->AddGlobalVal(std::move(gid));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::AddingRedef(const IDPtr& id, InitClass c, ExprPtr init, AttrVec& attrs)
|
||||||
|
{
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto r = std::make_shared<ActivationEvent>(ActivationEvent::REDEF);
|
||||||
|
r->AddID(id);
|
||||||
|
r->AddInitClass(c);
|
||||||
|
r->AddExpr(init);
|
||||||
|
r->AddAttrs(attrs);
|
||||||
|
|
||||||
|
activation_stack.back()->CondEvent()->AddSubEvent(std::move(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::RedefingHandler(const IDPtr& id)
|
||||||
|
{
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto hr = std::make_shared<ActivationEvent>(ActivationEvent::HANDLER_REDEF);
|
||||||
|
hr->AddID(id);
|
||||||
|
|
||||||
|
activation_stack.back()->CondEvent()->AddSubEvent(std::move(hr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivationManager::AddingBody(IDPtr func, std::shared_ptr<FunctionIngredients> ingr)
|
||||||
|
{
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto b = std::make_shared<ActivationEvent>(ActivationEvent::BODY);
|
||||||
|
b->AddID(func);
|
||||||
|
b->AddIngredients(std::move(ingr));
|
||||||
|
|
||||||
|
activation_stack.back()->CondEvent()->AddSubEvent(std::move(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace zeek::detail
|
311
src/ActivationManager.h
Normal file
311
src/ActivationManager.h
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
// Classes for supporting @if &analyze constructs.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "zeek/Expr.h"
|
||||||
|
#include "zeek/Func.h"
|
||||||
|
|
||||||
|
namespace zeek::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
using ScriptFuncPtr = IntrusivePtr<ScriptFunc>;
|
||||||
|
using AttrVec = std::unique_ptr<std::vector<AttrPtr>>;
|
||||||
|
|
||||||
|
class ActivationManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expresses an event (with one of the above types) occurring during an
|
||||||
|
* @if &analyze. Events reflect what *could* have happened rather than
|
||||||
|
* what *did* happen, so events will be present even for @if &analyze blocks
|
||||||
|
* that were skipped due to their condition evaluating to false.
|
||||||
|
*
|
||||||
|
* The current use for these events is to enable the CPP script compiler
|
||||||
|
* to generate run-time execution of @if &analyze conditionals. To do that,
|
||||||
|
* it needs a record of their associated effects.
|
||||||
|
*
|
||||||
|
* We use a "flat" class that encompasses all of the possibilities, rather
|
||||||
|
* than subclassing on the different types. This is because ActivationEvent's
|
||||||
|
* are a record for *reading* rather than conducting further processing
|
||||||
|
* directly; hence there aren't apt active methods to virtualize. If we
|
||||||
|
* used subclasses, we'd wind up having to cast to get to the specifics
|
||||||
|
* elements of a given event, which is clunky enough that it's not clear
|
||||||
|
* we gain anything useful.
|
||||||
|
*/
|
||||||
|
class ActivationEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* The different types of ActivationEvent's.
|
||||||
|
*/
|
||||||
|
enum AE_Type
|
||||||
|
{
|
||||||
|
// Represents an @if &analyze conditional, with a corresponding
|
||||||
|
// condition expression, and sub-events (i.e., other
|
||||||
|
// ActivationEvent's) for what occurs in the "true" and
|
||||||
|
// "false" branches.
|
||||||
|
COND,
|
||||||
|
|
||||||
|
// Represents the introduction of a new global identifier.
|
||||||
|
CREATE_GLOBAL,
|
||||||
|
|
||||||
|
// Represents adding a value (in particular, a ScriptFunc) to
|
||||||
|
// a particular global.
|
||||||
|
ADDING_GLOBAL_VAL,
|
||||||
|
|
||||||
|
// Represents a global having its initialization value and/or
|
||||||
|
// attributes redef'd.
|
||||||
|
REDEF,
|
||||||
|
|
||||||
|
// Represents an event handler being redef'd (which discards
|
||||||
|
// its current value).
|
||||||
|
HANDLER_REDEF,
|
||||||
|
|
||||||
|
// Represents adding a body to a function/hook/event handler.
|
||||||
|
BODY,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ActivationEvent's always have a type. All the other fields
|
||||||
|
// are optional, and are populated depending on the type.
|
||||||
|
ActivationEvent(AE_Type _et) : et(_et) { }
|
||||||
|
|
||||||
|
// Type of the activation event.
|
||||||
|
AE_Type Type() const { return et; }
|
||||||
|
|
||||||
|
// An associated expression associated.
|
||||||
|
void AddExpr(ExprPtr _expr) { expr = std::move(_expr); }
|
||||||
|
ExprPtr GetExpr() const { return expr; }
|
||||||
|
|
||||||
|
// An associated identifier.
|
||||||
|
void AddID(IDPtr _id) { id = std::move(_id); }
|
||||||
|
IDPtr GetID() const { return id; }
|
||||||
|
|
||||||
|
// An associated initialization class (equivalent to =/+=/-=).
|
||||||
|
void AddInitClass(InitClass _c) { c = _c; }
|
||||||
|
InitClass GetInitClass() const { return c; }
|
||||||
|
|
||||||
|
// A set of associated attributes, or none if a nil pointer.
|
||||||
|
void AddAttrs(AttrVec& _attrs)
|
||||||
|
{
|
||||||
|
// It's a pity that the code base has settled on unique_ptr's
|
||||||
|
// for collections of attributes rather than shared_ptr's ...
|
||||||
|
if ( _attrs )
|
||||||
|
{
|
||||||
|
attrs = std::make_unique<std::vector<AttrPtr>>();
|
||||||
|
*attrs = *_attrs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& GetAttrs() const { return attrs; }
|
||||||
|
|
||||||
|
// A set of associated "ingredients" for building a function.
|
||||||
|
void AddIngredients(std::shared_ptr<FunctionIngredients> _ingr) { ingr = std::move(_ingr); }
|
||||||
|
const auto& GetIngredients() const { return ingr; }
|
||||||
|
|
||||||
|
// Adds a "subevent" to this event, only valid for events that are
|
||||||
|
// themselves conditionals. Note that the subevent might itself
|
||||||
|
// be a (nested) conditional.
|
||||||
|
void AddSubEvent(std::shared_ptr<ActivationEvent> ae)
|
||||||
|
{
|
||||||
|
ASSERT(et == COND);
|
||||||
|
CurrSubEvents().push_back(std::move(ae));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes this events accrural of subevents to correspond to its
|
||||||
|
// "else" branch rather than its main/true branch.
|
||||||
|
void SwitchToElse()
|
||||||
|
{
|
||||||
|
ASSERT(et == COND);
|
||||||
|
ASSERT(in_true_branch);
|
||||||
|
in_true_branch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints out the event (and any subevents) for debug purposes.
|
||||||
|
void Dump(int indent_level) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Manages indentation when dumping events.
|
||||||
|
void Indent(int indent_level) const;
|
||||||
|
|
||||||
|
using SubEvents = std::vector<std::shared_ptr<ActivationEvent>>;
|
||||||
|
|
||||||
|
SubEvents& CurrSubEvents() { return in_true_branch ? T_sub_events : F_sub_events; }
|
||||||
|
|
||||||
|
AE_Type et;
|
||||||
|
ExprPtr expr;
|
||||||
|
IDPtr id;
|
||||||
|
InitClass c = INIT_NONE;
|
||||||
|
AttrVec attrs;
|
||||||
|
std::shared_ptr<FunctionIngredients> ingr;
|
||||||
|
|
||||||
|
// For events corresponding to conditionals, we track two sets
|
||||||
|
// of sub_events, one for the main (true) branch of the conditional,
|
||||||
|
// and one for the else (false) branch, if any, with in_true_branch
|
||||||
|
// reflecting which one we're working on (per CurrSubEvents()).
|
||||||
|
bool in_true_branch = true; // tells us which one to use
|
||||||
|
SubEvents T_sub_events;
|
||||||
|
SubEvents F_sub_events;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An "Activation" object tracks the status of a current @if &analyze
|
||||||
|
* conditional as it's being parsed. Its role is to keep track of what's
|
||||||
|
* up with the conditional for the live parsing, as opposed to what *could*
|
||||||
|
* have happened (which is instead reflected in a set of ActivationEvent's).
|
||||||
|
*/
|
||||||
|
class Activation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Activation(ExprPtr cond, bool _is_activated, bool _parent_activated, int _cond_depth);
|
||||||
|
~Activation();
|
||||||
|
|
||||||
|
// True if we're in the part of the @activiate-if conditional for
|
||||||
|
// which we should be incorporating statements (making changes to
|
||||||
|
// globals, adding function bodies, etc.).
|
||||||
|
bool IsActivated() const { return is_activated; }
|
||||||
|
|
||||||
|
// Returns the @if (not @if &analyze) conditional depth associated
|
||||||
|
// with this activation. Used to tell whether a given @else or @endif
|
||||||
|
// corresponds to this @if &analyze, or something nested within it.
|
||||||
|
int CondDepth() const { return cond_depth; }
|
||||||
|
|
||||||
|
// Returns the ActivationEvent associated with this @if &analyze.
|
||||||
|
auto CondEvent() const { return cond_event; }
|
||||||
|
|
||||||
|
// Tells the Activation to switch from its main (conditinal-is-true)
|
||||||
|
// processing to its "else" (conditional-is-false) processing.
|
||||||
|
void SwitchToElse()
|
||||||
|
{
|
||||||
|
// We're done tracking globals for the current body.
|
||||||
|
ResetGlobals();
|
||||||
|
|
||||||
|
// Toggle our activation status *unless* our parent (another
|
||||||
|
// @if &analyze) was itself not active, in which case we
|
||||||
|
// stay inactive.
|
||||||
|
if ( parent_activated )
|
||||||
|
is_activated = ! is_activated;
|
||||||
|
|
||||||
|
// Keep the ActivationEvent in synch.
|
||||||
|
cond_event->SwitchToElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddGlobalID(IDPtr gid) { global_IDs.push_back(std::move(gid)); }
|
||||||
|
void AddGlobalVal(IDPtr gid) { global_vals.push_back(std::move(gid)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// If we weren't active, then undo the effects that the parser had
|
||||||
|
// to make (installing new globals and event handlers) in order
|
||||||
|
// to assess the correctness of the code within the block.
|
||||||
|
void ResetGlobals();
|
||||||
|
|
||||||
|
std::shared_ptr<ActivationEvent> cond_event;
|
||||||
|
|
||||||
|
// True if our parent was itself activated. Always true if there
|
||||||
|
// wasn't an outer @if &analyze.
|
||||||
|
bool parent_activated;
|
||||||
|
|
||||||
|
// Whether we're currently activated.
|
||||||
|
bool is_activated;
|
||||||
|
|
||||||
|
// Depth of @if conditionals when this activation began.
|
||||||
|
int cond_depth;
|
||||||
|
|
||||||
|
// Set of globals that were added during processing of the current body.
|
||||||
|
std::vector<IDPtr> global_IDs;
|
||||||
|
|
||||||
|
// Similar: set of globals for which we added values. We track
|
||||||
|
// this only for function/hook/event handler bodies.
|
||||||
|
std::vector<IDPtr> global_vals;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for managing the processing of @if &analyze's. Deals with
|
||||||
|
* potential nesting, and with constructing a trace of the associated
|
||||||
|
* ActivationEvents.
|
||||||
|
*/
|
||||||
|
class ActivationManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActivationManager() = default;
|
||||||
|
~ActivationManager();
|
||||||
|
|
||||||
|
// True if we are currently inside an @if &analyze.
|
||||||
|
bool InsideConditional() const { return ! activation_stack.empty(); }
|
||||||
|
|
||||||
|
// True if the current @if &analyze corresponds to the given
|
||||||
|
// @if conditional-depth. Needed to disambiguate @else and @endif
|
||||||
|
// tokens in the presence of possible inter-nesting of @if and
|
||||||
|
// @if &analyze constructs.
|
||||||
|
bool InsideConditional(int cond_depth) const
|
||||||
|
{
|
||||||
|
if ( activation_stack.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return activation_stack.back()->CondDepth() == cond_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if processing of the current script is "activated". This
|
||||||
|
// is the usual state of things, other than when inside the branch
|
||||||
|
// of an @if &analyze that doesn't correspond to its condition.
|
||||||
|
bool IsActivated() const
|
||||||
|
{
|
||||||
|
return activation_stack.empty() || activation_stack.back()->IsActivated();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the nesting level of @if &analyze's. Used by the scanner
|
||||||
|
// to find dangling conditionals at the end of files. Typed as an
|
||||||
|
// integer to match similar other structures in the scanner.
|
||||||
|
int ActivationDepth() const { return static_cast<int>(activation_stack.size()); }
|
||||||
|
|
||||||
|
// Tells the manager to being a new @if &analyze conditional.
|
||||||
|
// "cond" is the associated condition, "activate" reflects whether
|
||||||
|
// the condition is true, and "cond_depth" is the depth of any
|
||||||
|
// parent @if constructs.
|
||||||
|
void Start(ExprPtr cond, bool activate, int cond_depth);
|
||||||
|
|
||||||
|
// Tells the manager that an @else has been seen for its innermost
|
||||||
|
// @if &analyze.
|
||||||
|
void SwitchToElse();
|
||||||
|
|
||||||
|
// Tells the manager that an @endif has been seen for its innermost
|
||||||
|
// @if &analyze.
|
||||||
|
void End();
|
||||||
|
|
||||||
|
// Tells the manager that the parser is creating a new global
|
||||||
|
// identifier.
|
||||||
|
void CreatingGlobalID(IDPtr gid);
|
||||||
|
|
||||||
|
// Tells the manager that the parser is adding a value to a global.
|
||||||
|
void AddingGlobalVal(IDPtr gid);
|
||||||
|
|
||||||
|
// Tells the manager that the parser is redef'ing an identifier using
|
||||||
|
// the associated values.
|
||||||
|
void AddingRedef(const IDPtr& id, InitClass c, ExprPtr init, AttrVec& attrs);
|
||||||
|
|
||||||
|
// Tells the manger that the given identifier's event handler is
|
||||||
|
// being redef'd.
|
||||||
|
void RedefingHandler(const IDPtr& id);
|
||||||
|
|
||||||
|
// Tells the manager that the parser is adding a function body to
|
||||||
|
// the given function.
|
||||||
|
void AddingBody(IDPtr func, std::shared_ptr<FunctionIngredients> ingr);
|
||||||
|
|
||||||
|
// Returns a list of top-level ActivationEvent's. These will all
|
||||||
|
// be COND events, which in general should be traversed recursively
|
||||||
|
// to extract what happened inside the conditionals, including
|
||||||
|
// additional conditionals potentially nested inside.
|
||||||
|
const auto& ActivationEvents() const { return activation_events; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Currently live @if &analyze information.
|
||||||
|
std::vector<std::unique_ptr<Activation>> activation_stack;
|
||||||
|
|
||||||
|
// A trace of all of the top-level @if &analyze events. Any
|
||||||
|
// nested @if &analyze's are available from the top-level events
|
||||||
|
// as sub-events.
|
||||||
|
std::vector<std::shared_ptr<ActivationEvent>> activation_events;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ActivationManager* activation_mgr;
|
||||||
|
|
||||||
|
} // namespace zeek::detail
|
|
@ -282,6 +282,7 @@ set(MAIN_SRCS
|
||||||
module_util.cc
|
module_util.cc
|
||||||
zeek-affinity.cc
|
zeek-affinity.cc
|
||||||
zeek-setup.cc
|
zeek-setup.cc
|
||||||
|
ActivationManager.cc
|
||||||
Anon.cc
|
Anon.cc
|
||||||
Attr.cc
|
Attr.cc
|
||||||
Base64.cc
|
Base64.cc
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue