diff --git a/NEWS b/NEWS index a1ff0dca04..6fec41925f 100644 --- a/NEWS +++ b/NEWS @@ -47,6 +47,11 @@ Removed Functionality Deprecated Functionality ------------------------ +- The ``Func::Call(val_list*, ...)`` method is now deprecated. The alternate + overload taking a ``zeek::Args`` (``std::vector>``) should + be used instead. There's also now a variadic template that forwards all + arguments. + Zeek 3.1.0 ========== diff --git a/src/Discard.cc b/src/Discard.cc index 7ba0d2e7a5..b08d454bed 100644 --- a/src/Discard.cc +++ b/src/Discard.cc @@ -39,11 +39,11 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) if ( check_ip ) { - val_list args{ip->BuildPktHdrVal()}; + zeek::Args args{{AdoptRef{}, ip->BuildPktHdrVal()}}; try { - discard_packet = check_ip->Call(&args)->AsBool(); + discard_packet = check_ip->Call(args)->AsBool(); } catch ( InterpreterException& e ) @@ -91,14 +91,14 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) const struct tcphdr* tp = (const struct tcphdr*) data; int th_len = tp->th_off * 4; - val_list args{ - ip->BuildPktHdrVal(), - BuildData(data, th_len, len, caplen), + zeek::Args args{ + {AdoptRef{}, ip->BuildPktHdrVal()}, + {AdoptRef{}, BuildData(data, th_len, len, caplen)}, }; try { - discard_packet = check_tcp->Call(&args)->AsBool(); + discard_packet = check_tcp->Call(args)->AsBool(); } catch ( InterpreterException& e ) @@ -115,14 +115,14 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) const struct udphdr* up = (const struct udphdr*) data; int uh_len = sizeof (struct udphdr); - val_list args{ - ip->BuildPktHdrVal(), - BuildData(data, uh_len, len, caplen), + zeek::Args args{ + {AdoptRef{}, ip->BuildPktHdrVal()}, + {AdoptRef{}, BuildData(data, uh_len, len, caplen)}, }; try { - discard_packet = check_udp->Call(&args)->AsBool(); + discard_packet = check_udp->Call(args)->AsBool(); } catch ( InterpreterException& e ) @@ -138,11 +138,11 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) { const struct icmp* ih = (const struct icmp*) data; - val_list args{ip->BuildPktHdrVal()}; + zeek::Args args{{AdoptRef{}, ip->BuildPktHdrVal()}}; try { - discard_packet = check_icmp->Call(&args)->AsBool(); + discard_packet = check_icmp->Call(args)->AsBool(); } catch ( InterpreterException& e ) diff --git a/src/Func.h b/src/Func.h index a5ac9f3454..e790f71cdf 100644 --- a/src/Func.h +++ b/src/Func.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -50,10 +52,28 @@ public: const vector& GetBodies() const { return bodies; } bool HasBodies() const { return bodies.size(); } - // TODO: deprecate + [[deprecated("Remove in v4.1. Use zeek::Args overload instead.")]] virtual IntrusivePtr Call(val_list* args, Frame* parent = nullptr) const; + + /** + * Calls a Zeek function. + * @param args the list of arguments to the function call. + * @param parent the frame from which the function is being called. + * @return the return value of the function call. + */ virtual IntrusivePtr Call(const zeek::Args& args, Frame* parent = nullptr) const = 0; + /** + * A version of Call() taking a variable number of individual arguments. + */ + template + std::enable_if_t< + std::is_convertible_v>, + IntrusivePtr>, + IntrusivePtr> + Call(Args&&... args) const + { return Call(zeek::Args{std::forward(args)...}); } + // Add a new event handler to an existing function (event). virtual void AddBody(IntrusivePtr new_body, id_list* new_inits, size_t new_frame_size, int priority = 0); diff --git a/src/RuleCondition.cc b/src/RuleCondition.cc index 656d4d5cf7..b5331d5be1 100644 --- a/src/RuleCondition.cc +++ b/src/RuleCondition.cc @@ -167,19 +167,20 @@ bool RuleConditionEval::DoMatch(Rule* rule, RuleEndpointState* state, return id->ID_Val()->AsBool(); // Call function with a signature_state value as argument. - val_list args(2); - args.push_back(rule_matcher->BuildRuleStateValue(rule, state)); + zeek::Args args; + args.reserve(2); + args.emplace_back(AdoptRef{}, rule_matcher->BuildRuleStateValue(rule, state)); if ( data ) - args.push_back(new StringVal(len, (const char*) data)); + args.emplace_back(make_intrusive(len, (const char*) data)); else - args.push_back(val_mgr->GetEmptyString()); + args.emplace_back(AdoptRef{}, val_mgr->GetEmptyString()); bool result = false; try { - auto val = id->ID_Val()->AsFunc()->Call(&args); + auto val = id->ID_Val()->AsFunc()->Call(args); result = val && val->AsBool(); } diff --git a/src/Val.cc b/src/Val.cc index a366b8bcd7..4b5e7db313 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1835,25 +1835,24 @@ IntrusivePtr TableVal::Default(Val* index) } const Func* f = def_val->AsFunc(); - val_list vl; + zeek::Args vl; if ( index->Type()->Tag() == TYPE_LIST ) { const val_list* vl0 = index->AsListVal()->Vals(); - vl = val_list(vl0->length()); + vl.reserve(vl0->length()); + for ( const auto& v : *vl0 ) - vl.push_back(v->Ref()); + vl.emplace_back(NewRef{}, v); } else - { - vl = val_list{index->Ref()}; - } + vl.emplace_back(NewRef{}, index); IntrusivePtr result; try { - result = f->Call(&vl); + result = f->Call(vl); } catch ( InterpreterException& e ) @@ -2011,34 +2010,35 @@ void TableVal::CallChangeFunc(const Val* index, Val* old_value, OnChangeType tpe } const Func* f = thefunc->AsFunc(); - val_list vl { Ref() }; - IntrusivePtr type; + const auto& index_list = *index->AsListVal()->Vals(); + + zeek::Args vl; + vl.reserve(2 + index_list.length() + table_type->IsTable()); + vl.emplace_back(NewRef{}, this); switch ( tpe ) { case ELEMENT_NEW: - type = BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_NEW); + vl.emplace_back(BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_NEW)); break; case ELEMENT_CHANGED: - type = BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_CHANGED); + vl.emplace_back(BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_CHANGED)); break; case ELEMENT_REMOVED: - type = BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_REMOVED); + vl.emplace_back(BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_REMOVED)); break; case ELEMENT_EXPIRED: - type = BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_EXPIRED); + vl.emplace_back(BifType::Enum::TableChange->GetVal(BifEnum::TableChange::TABLE_ELEMENT_EXPIRED)); } - vl.append(type.release()); - for ( const auto& v : *index->AsListVal()->Vals() ) - vl.append(v->Ref()); + vl.emplace_back(NewRef{}, v); - if ( ! table_type->IsSet() ) - vl.append(old_value->Ref()); + if ( table_type->IsTable() ) + vl.emplace_back(NewRef{}, old_value); in_change_func = true; - f->Call(&vl); + f->Call(vl); } catch ( InterpreterException& e ) { @@ -2451,7 +2451,7 @@ double TableVal::CallExpireFunc(IntrusivePtr idx) } const Func* f = vf->AsFunc(); - val_list vl { Ref() }; + zeek::Args vl; const auto func_args = f->FType()->ArgTypes()->Types(); @@ -2460,20 +2460,27 @@ double TableVal::CallExpireFunc(IntrusivePtr idx) if ( ! any_idiom ) { - for ( const auto& v : *idx->AsListVal()->Vals() ) - vl.append(v->Ref()); + const auto& index_list = *idx->AsListVal()->Vals(); + vl.reserve(1 + index_list.length()); + vl.emplace_back(NewRef{}, this); + + for ( const auto& v : index_list ) + vl.emplace_back(NewRef{}, v); } else { + vl.reserve(2); + vl.emplace_back(NewRef{}, this); + ListVal* idx_list = idx->AsListVal(); // Flatten if only one element if ( idx_list->Length() == 1 ) - vl.append(idx_list->Index(0)->Ref()); + vl.emplace_back(NewRef{}, idx_list->Index(0)); else - vl.append(idx.release()); + vl.emplace_back(std::move(idx)); } - auto result = f->Call(&vl); + auto result = f->Call(vl); if ( result ) secs = result->AsInterval(); diff --git a/src/broker/Manager.cc b/src/broker/Manager.cc index 6fbf0f06f4..f99e35a445 100644 --- a/src/broker/Manager.cc +++ b/src/broker/Manager.cc @@ -545,12 +545,8 @@ bool Manager::PublishLogWrite(EnumVal* stream, EnumVal* writer, string path, int std::string serial_data(data, len); free(data); - val_list vl{ - stream->Ref(), - new StringVal(path), - }; - - auto v = log_topic_func->Call(&vl); + auto v = log_topic_func->Call(IntrusivePtr{NewRef{}, stream}, + make_intrusive(path)); if ( ! v ) { diff --git a/src/broker/messaging.bif b/src/broker/messaging.bif index 6217facb41..125710865a 100644 --- a/src/broker/messaging.bif +++ b/src/broker/messaging.bif @@ -188,8 +188,8 @@ function Cluster::publish_rr%(pool: Pool, key: string, ...%): bool if ( ! topic_func ) topic_func = global_scope()->Lookup("Cluster::rr_topic")->ID_Val()->AsFunc(); - val_list vl{pool->Ref(), key->Ref()}; - auto topic = topic_func->Call(&vl); + zeek::Args vl{{NewRef{}, pool}, {NewRef{}, key}}; + auto topic = topic_func->Call(vl); if ( ! topic->AsString()->Len() ) return val_mgr->GetFalse(); @@ -225,8 +225,8 @@ function Cluster::publish_hrw%(pool: Pool, key: any, ...%): bool if ( ! topic_func ) topic_func = global_scope()->Lookup("Cluster::hrw_topic")->ID_Val()->AsFunc(); - val_list vl{pool->Ref(), key->Ref()}; - auto topic = topic_func->Call(&vl); + zeek::Args vl{{NewRef{}, pool}, {NewRef{}, key}}; + auto topic = topic_func->Call(vl); if ( ! topic->AsString()->Len() ) return val_mgr->GetFalse(); diff --git a/src/file_analysis/analyzer/x509/X509.cc b/src/file_analysis/analyzer/x509/X509.cc index f25ea7c177..30ddee9042 100644 --- a/src/file_analysis/analyzer/x509/X509.cc +++ b/src/file_analysis/analyzer/x509/X509.cc @@ -60,11 +60,9 @@ bool file_analysis::X509::EndOfFile() return false; // yup, let's call the callback. - val_list vl(3); - vl.push_back(GetFile()->GetVal()->Ref()); - vl.push_back(entry.release()); - vl.push_back(new StringVal(cert_sha256)); - cache_hit_callback->Call(&vl); + cache_hit_callback->Call(IntrusivePtr{NewRef{}, GetFile()->GetVal()}, + std::move(entry), + make_intrusive(cert_sha256)); return false; } } diff --git a/src/input/Manager.cc b/src/input/Manager.cc index 5408a51d85..f20c9a3bae 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -1782,16 +1782,18 @@ bool Manager::Delete(ReaderFrontend* reader, Value* *vals) bool Manager::CallPred(Func* pred_func, const int numvals, ...) const { bool result = false; - val_list vl(numvals); + zeek::Args vl; + vl.reserve(numvals); va_list lP; va_start(lP, numvals); for ( int i = 0; i < numvals; i++ ) - vl.push_back( va_arg(lP, Val*) ); + vl.emplace_back(AdoptRef{}, va_arg(lP, Val*)); va_end(lP); - auto v = pred_func->Call(&vl); + auto v = pred_func->Call(vl); + if ( v ) result = v->AsBool(); diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 87eac0e066..1a2125585b 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -723,11 +723,9 @@ bool Manager::Write(EnumVal* id, RecordVal* columns_arg) { // See whether the predicates indicates that we want // to log this record. - val_list vl{columns->Ref()}; - int result = 1; + auto v = filter->pred->Call(columns); - auto v = filter->pred->Call(&vl); if ( v ) result = v->AsBool(); @@ -737,23 +735,25 @@ bool Manager::Write(EnumVal* id, RecordVal* columns_arg) if ( filter->path_func ) { - Val* path_arg; - if ( filter->path_val ) - path_arg = filter->path_val->Ref(); - else - path_arg = val_mgr->GetEmptyString(); + IntrusivePtr path_arg; - Val* rec_arg; + if ( filter->path_val ) + path_arg = {NewRef{}, filter->path_val}; + else + path_arg = {AdoptRef{}, val_mgr->GetEmptyString()}; + + IntrusivePtr rec_arg; BroType* rt = filter->path_func->FType()->Args()->FieldType("rec"); if ( rt->Tag() == TYPE_RECORD ) - rec_arg = columns->CoerceTo(rt->AsRecordType(), true).release(); + rec_arg = columns->CoerceTo(rt->AsRecordType(), true); else // Can be TYPE_ANY here. - rec_arg = columns->Ref(); + rec_arg = columns; - val_list vl{id->Ref(), path_arg, rec_arg}; - auto v = filter->path_func->Call(&vl); + auto v = filter->path_func->Call(IntrusivePtr{NewRef{}, id}, + std::move(path_arg), + std::move(rec_arg)); if ( ! v ) return false; @@ -1058,8 +1058,7 @@ threading::Value** Manager::RecordToFilterVals(Stream* stream, Filter* filter, if ( filter->num_ext_fields > 0 ) { - val_list vl{filter->path_val->Ref()}; - auto res = filter->ext_func->Call(&vl); + auto res = filter->ext_func->Call(IntrusivePtr{NewRef{}, filter->path_val}); if ( res ) ext_rec = {AdoptRef{}, res.release()->AsRecordVal()}; @@ -1515,7 +1514,7 @@ bool Manager::FinishedRotation(WriterFrontend* writer, const char* new_name, con return true; // Create the RotationInfo record. - RecordVal* info = new RecordVal(BifType::Record::Log::RotationInfo); + auto info = make_intrusive(BifType::Record::Log::RotationInfo); info->Assign(0, winfo->type->Ref()); info->Assign(1, make_intrusive(new_name)); info->Assign(2, make_intrusive(winfo->writer->Info().path)); @@ -1534,11 +1533,9 @@ bool Manager::FinishedRotation(WriterFrontend* writer, const char* new_name, con assert(func); // Call the postprocessor function. - val_list vl{info}; - int result = 0; - auto v = func->Call(&vl); + auto v = func->Call(std::move(info)); if ( v ) result = v->AsBool(); diff --git a/src/option.bif b/src/option.bif index 13b2215923..a897618483 100644 --- a/src/option.bif +++ b/src/option.bif @@ -16,14 +16,15 @@ static bool call_option_handlers_and_set_value(StringVal* name, ID* i, for ( auto handler_function : i->GetOptionHandlers() ) { bool add_loc = handler_function->FType()->AsFuncType()->ArgTypes()->Types()->length() == 3; - val_list vl(2 + add_loc); - vl.push_back(name->Ref()); - vl.push_back(val->Ref()); + zeek::Args vl; + vl.reserve(2 + add_loc); + vl.emplace_back(NewRef{}, name); + vl.emplace_back(val); if ( add_loc ) - vl.push_back(location->Ref()); + vl.emplace_back(NewRef{}, location); - val = handler_function->Call(&vl); // consumed by next call. + val = handler_function->Call(vl); // consumed by next call. if ( ! val ) { diff --git a/src/zeek.bif b/src/zeek.bif index 9b41b98397..8a957165a4 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -1335,11 +1335,8 @@ bool sort_function(Val* a, Val* b) if ( ! b ) return 1; - val_list sort_func_args; - sort_func_args.push_back(a->Ref()); - sort_func_args.push_back(b->Ref()); - - auto result = sort_function_comp->Call(&sort_func_args); + auto result = sort_function_comp->Call(IntrusivePtr{NewRef{}, a}, + IntrusivePtr{NewRef{}, b}); int int_result = result->CoerceToInt(); return int_result < 0;