// See the file "COPYING" in the main distribution directory for copyright. #include "zeek/script_opt/CPP/RunTimeInits.h" #include "zeek/Desc.h" #include "zeek/File.h" #include "zeek/RE.h" #include "zeek/ZeekString.h" #include "zeek/script_opt/CPP/RunTimeInitSupport.h" using namespace std; namespace zeek::detail { template void CPP_IndexedInits::InitializeCohortWithOffsets(InitsManager* im, int cohort, const std::vector& cohort_offsets) { auto& co = this->inits[cohort]; for ( auto i = 0U; i < co.size(); ++i ) Generate(im, this->inits_vec, cohort_offsets[i], co[i]); } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) { auto& e_type = im->Types(init_vals[0]); int val = init_vals[1]; ivec[offset] = make_enum__CPP(e_type, val); } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) { auto chars = im->Strings(init_vals[0]); int len = init_vals[1]; ivec[offset] = make_intrusive(len, chars); } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) { auto re = new RE_Matcher(im->Strings(init_vals[0])); if ( init_vals[1] ) re->MakeCaseInsensitive(); re->Compile(); ivec[offset] = make_intrusive(re); } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; auto l = make_intrusive(TYPE_ANY); while ( i < n ) l->Append(im->ConstVals(init_vals[i++])); ivec[offset] = l; } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; auto t = init_vals[i++]; auto vt = cast_intrusive(im->Types(t)); auto vv = make_intrusive(vt); while ( i < n ) vv->Append(im->ConstVals(init_vals[i++])); ivec[offset] = vv; } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; auto t = init_vals[i++]; auto rt = cast_intrusive(im->Types(t)); auto rv = make_intrusive(rt); while ( i < n ) { auto v = init_vals[i]; if ( v >= 0 ) rv->Assign(i - 1, im->ConstVals(v)); ++i; } ivec[offset] = rv; } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; auto t = init_vals[i++]; auto tt = cast_intrusive(im->Types(t)); auto tv = make_intrusive(tt); while ( i < n ) { auto index = im->ConstVals(init_vals[i++]); auto v = init_vals[i++]; auto value = v >= 0 ? im->ConstVals(v) : nullptr; tv->Assign(index, value); } ivec[offset] = tv; } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; auto t = init_vals[i++]; // not used auto fn = im->Strings(init_vals[i++]); auto fv = make_intrusive(make_intrusive(fn, "w")); ivec[offset] = fv; } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; auto t = init_vals[i++]; auto fn = im->Strings(init_vals[i++]); std::vector hashes; while ( i < n ) hashes.push_back(im->Hashes(init_vals[i++])); ivec[offset] = lookup_func__CPP(fn, hashes, im->Types(t)); } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto tag = static_cast(init_vals[0]); auto ae_tag = static_cast(init_vals[1]); ExprPtr e; auto e_arg = init_vals[2]; switch ( ae_tag ) { case AE_NONE: break; case AE_CONST: e = make_intrusive(im->ConstVals(e_arg)); break; case AE_NAME: { auto name = im->Strings(e_arg); auto gl = lookup_ID(name, GLOBAL_MODULE_NAME, false, false, false); ASSERT(gl); e = make_intrusive(gl); break; } case AE_RECORD: { auto t = im->Types(e_arg); auto rt = cast_intrusive(t); auto empty_vals = make_intrusive(); auto construct = make_intrusive(empty_vals); e = make_intrusive(construct, rt); break; } case AE_CALL: e = im->CallExprs(e_arg); break; } ivec[offset] = make_intrusive(tag, e); } template void CPP_IndexedInits::Generate(InitsManager* im, std::vector& ivec, int offset, ValElemVec& init_vals) const { auto n = init_vals.size(); auto i = 0U; std::vector a_list; while ( i < n ) a_list.emplace_back(im->Attrs(init_vals[i++])); ivec[offset] = make_intrusive(a_list, nullptr, false, false); } // Instantiate the templates we'll need. template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; template class CPP_IndexedInits; void CPP_TypeInits::DoPreInits(InitsManager* im, const std::vector& offsets_vec) { for ( auto cohort = 0U; cohort < offsets_vec.size(); ++cohort ) { auto& co = inits[cohort]; auto& cohort_offsets = im->Indices(offsets_vec[cohort]); for ( auto i = 0U; i < co.size(); ++i ) PreInit(im, cohort_offsets[i], co[i]); } } void CPP_TypeInits::PreInit(InitsManager* im, int offset, ValElemVec& init_vals) { auto tag = static_cast(init_vals[0]); if ( tag == TYPE_LIST ) inits_vec[offset] = make_intrusive(); else if ( tag == TYPE_RECORD ) { auto name = im->Strings(init_vals[1]); if ( name[0] ) inits_vec[offset] = get_record_type__CPP(name); else inits_vec[offset] = get_record_type__CPP(nullptr); } // else no pre-initialization needed } void CPP_TypeInits::Generate(InitsManager* im, vector& ivec, int offset, ValElemVec& init_vals) const { auto tag = static_cast(init_vals[0]); TypePtr t; switch ( tag ) { case TYPE_ADDR: case TYPE_ANY: case TYPE_BOOL: case TYPE_COUNT: case TYPE_DOUBLE: case TYPE_ERROR: case TYPE_INT: case TYPE_INTERVAL: case TYPE_PATTERN: case TYPE_PORT: case TYPE_STRING: case TYPE_TIME: case TYPE_TIMER: case TYPE_VOID: case TYPE_SUBNET: case TYPE_FILE: t = base_type(tag); break; case TYPE_ENUM: t = BuildEnumType(im, init_vals); break; case TYPE_OPAQUE: t = BuildOpaqueType(im, init_vals); break; case TYPE_TYPE: t = BuildTypeType(im, init_vals); break; case TYPE_VECTOR: t = BuildVectorType(im, init_vals); break; case TYPE_LIST: t = BuildTypeList(im, init_vals, offset); break; case TYPE_TABLE: t = BuildTableType(im, init_vals); break; case TYPE_FUNC: t = BuildFuncType(im, init_vals); break; case TYPE_RECORD: t = BuildRecordType(im, init_vals, offset); break; default: ASSERT(0); } ivec[offset] = t; } TypePtr CPP_TypeInits::BuildEnumType(InitsManager* im, ValElemVec& init_vals) const { auto name = im->Strings(init_vals[1]); auto et = get_enum_type__CPP(name); if ( et->Names().empty() ) { auto n = init_vals.size(); auto i = 2U; while ( i < n ) { auto e_name = im->Strings(init_vals[i++]); auto e_val = init_vals[i++]; et->AddNameInternal(e_name, e_val); } } return et; } TypePtr CPP_TypeInits::BuildOpaqueType(InitsManager* im, ValElemVec& init_vals) const { auto name = im->Strings(init_vals[1]); return make_intrusive(name); } TypePtr CPP_TypeInits::BuildTypeType(InitsManager* im, ValElemVec& init_vals) const { auto& t = im->Types(init_vals[1]); return make_intrusive(t); } TypePtr CPP_TypeInits::BuildVectorType(InitsManager* im, ValElemVec& init_vals) const { auto& t = im->Types(init_vals[1]); return make_intrusive(t); } TypePtr CPP_TypeInits::BuildTypeList(InitsManager* im, ValElemVec& init_vals, int offset) const { const auto& tl = cast_intrusive(inits_vec[offset]); auto n = init_vals.size(); auto i = 1U; while ( i < n ) tl->Append(im->Types(init_vals[i++])); return tl; } TypePtr CPP_TypeInits::BuildTableType(InitsManager* im, ValElemVec& init_vals) const { auto index = cast_intrusive(im->Types(init_vals[1])); auto yield_i = init_vals[2]; auto yield = yield_i >= 0 ? im->Types(yield_i) : nullptr; return make_intrusive(index, yield); } TypePtr CPP_TypeInits::BuildFuncType(InitsManager* im, ValElemVec& init_vals) const { auto p = cast_intrusive(im->Types(init_vals[1])); auto yield_i = init_vals[2]; auto flavor = static_cast(init_vals[3]); TypePtr y; if ( yield_i >= 0 ) y = im->Types(yield_i); else if ( flavor == FUNC_FLAVOR_FUNCTION || flavor == FUNC_FLAVOR_HOOK ) y = base_type(TYPE_VOID); return make_intrusive(p, y, flavor); } TypePtr CPP_TypeInits::BuildRecordType(InitsManager* im, ValElemVec& init_vals, int offset) const { auto r = cast_intrusive(inits_vec[offset]); ASSERT(r); if ( r->NumFields() == 0 ) { type_decl_list tl; auto n = init_vals.size(); auto i = 2U; while ( i < n ) { auto s = im->Strings(init_vals[i++]); auto id = util::copy_string(s); auto type = im->Types(init_vals[i++]); auto attrs_i = init_vals[i++]; AttributesPtr attrs; if ( attrs_i >= 0 ) attrs = im->Attributes(attrs_i); tl.append(new TypeDecl(id, type, attrs)); } r->AddFieldsDirectly(tl); } return r; } int CPP_FieldMapping::ComputeOffset(InitsManager* im) const { auto r = im->Types(rec)->AsRecordType(); auto fm_offset = r->FieldOffset(field_name.c_str()); if ( fm_offset < 0 ) { // field does not exist, create it fm_offset = r->NumFields(); auto id = util::copy_string(field_name.c_str()); auto type = im->Types(field_type); AttributesPtr attrs; if ( field_attrs >= 0 ) attrs = im->Attributes(field_attrs); type_decl_list tl; tl.append(new TypeDecl(id, type, attrs)); r->AddFieldsDirectly(tl); } return fm_offset; } int CPP_EnumMapping::ComputeOffset(InitsManager* im) const { auto e = im->Types(e_type)->AsEnumType(); auto em_offset = e->Lookup(e_name); if ( em_offset < 0 ) { // enum constant does not exist, create it em_offset = e->Names().size(); if ( e->Lookup(em_offset) ) reporter->InternalError("enum inconsistency while initializing compiled scripts"); e->AddNameInternal(e_name, em_offset); } return em_offset; } void CPP_GlobalInit::Generate(InitsManager* im, std::vector& /* inits_vec */, int /* offset */) const { global = lookup_global__CPP(name, im->Types(type), exported); if ( ! global->HasVal() && val >= 0 ) { global->SetVal(im->ConstVals(val)); if ( attrs >= 0 ) global->SetAttrs(im->Attributes(attrs)); } } void generate_indices_set(int* inits, std::vector>& indices_set) { // First figure out how many groups of indices there are, so we // can pre-allocate the outer vector. auto i_ptr = inits; int num_inits = 0; while ( *i_ptr >= 0 ) { ++num_inits; int n = *i_ptr; i_ptr += n + 1; // skip over vector elements } indices_set.reserve(num_inits); i_ptr = inits; while ( *i_ptr >= 0 ) { int n = *i_ptr; ++i_ptr; std::vector indices; indices.reserve(n); for ( int i = 0; i < n; ++i ) indices.push_back(i_ptr[i]); i_ptr += n; indices_set.emplace_back(move(indices)); } } } // zeek::detail