zeek/tools/binpac/src/pac_context.cc

96 lines
2.9 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
#include "pac_context.h"
#include "pac_analyzer.h"
#include "pac_exception.h"
#include "pac_exttype.h"
#include "pac_flow.h"
#include "pac_id.h"
#include "pac_output.h"
#include "pac_param.h"
#include "pac_paramtype.h"
#include "pac_type.h"
#include "pac_utils.h"
ContextField::ContextField(ID* id, Type* type)
: Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {}
AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = nullptr;
namespace {
ParamList* ContextFieldsToParams(ContextFieldList* context_fields) {
// Convert context fields to parameters
ParamList* params = new ParamList();
foreach (i, ContextFieldList, context_fields) {
ContextField* f = *i;
params->push_back(new Param(f->id()->clone(), f->type()));
}
return params;
}
} // namespace
AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields)
: TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), new DummyType()) {
context_name_id_ = id;
if ( current_analyzer_context_ != nullptr ) {
throw Exception(this, strfmt("multiple declaration of analyzer context; "
"the previous one is `%s'",
current_analyzer_context_->id()->Name()));
}
else
current_analyzer_context_ = this;
context_fields_ = context_fields;
param_type_ = new ParameterizedType(id_->clone(), nullptr);
flow_buffer_added_ = false;
DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str());
}
AnalyzerContextDecl::~AnalyzerContextDecl() {
delete context_name_id_;
delete param_type_;
delete_list(ContextFieldList, context_fields_);
}
void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) {
GenNamespaceBegin(out_h);
TypeDecl::GenForwardDeclaration(out_h);
}
void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc) {
GenNamespaceBegin(out_h);
GenNamespaceBegin(out_cc);
TypeDecl::GenCode(out_h, out_cc);
}
void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const {
out->println("namespace %s {", context_name_id()->Name());
}
void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const {
out->println("} // namespace %s", context_name_id()->Name());
}
void AnalyzerContextDecl::AddFlowBuffer() {
if ( flow_buffer_added_ )
return;
AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone()));
flow_buffer_added_ = true;
}
string AnalyzerContextDecl::mb_buffer(Env* env) {
// A hack. The orthodox way would be to build an Expr of
// context.flow_buffer_var, and then EvalExpr.
return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar);
}
Type* DummyType::DoClone() const {
// Fields will be copied in Type::Clone().
return new DummyType();
}