mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 20:48:21 +00:00
factoring of ZAM operation specifications into separate files
This commit is contained in:
parent
5fc2c601b4
commit
e94764982d
19 changed files with 3139 additions and 3370 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit 610cf8527dad7033b971595a1d556c2c95294f2b
|
Subproject commit cfc0c7b9de63f44419c2a57040ae6b7081a66a33
|
|
@ -162,7 +162,23 @@ list(APPEND BINPAC_OUTPUTS "${BINPAC_OUTPUT_CC}")
|
||||||
include(Gen-ZAM)
|
include(Gen-ZAM)
|
||||||
|
|
||||||
set(GEN_ZAM_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/script_opt/ZAM/OPs)
|
set(GEN_ZAM_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/script_opt/ZAM/OPs)
|
||||||
set(GEN_ZAM_SRC ${GEN_ZAM_SRC_DIR}/ZAM.op)
|
set(ZAM_OP_SRCS
|
||||||
|
${GEN_ZAM_SRC_DIR}/aggr-assignments.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/binary-exprs.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/calls.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/coercions.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/constructors.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/indexing.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/internal.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/iterations.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/macros.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/non-uniform.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/rel-exprs.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/script-idioms.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/stmts.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/unary-exprs.op
|
||||||
|
${GEN_ZAM_SRC_DIR}/ZBI.op)
|
||||||
|
set(GEN_ZAM_SRC ${ZAM_OP_SRCS})
|
||||||
|
|
||||||
gen_zam_target(${GEN_ZAM_SRC_DIR})
|
gen_zam_target(${GEN_ZAM_SRC_DIR})
|
||||||
|
|
||||||
|
|
286
src/script_opt/ZAM/OPs/README.txt
Normal file
286
src/script_opt/ZAM/OPs/README.txt
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
# See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
# This directory contains templates used to generate virtual functions, opcodes,
|
||||||
|
# and evaluation code for compiled code. Each template describes a ZAM
|
||||||
|
# "operation", which generally corresponds to a set of concrete ZAM
|
||||||
|
# "instructions". (See ZInst.h for the layout of ZAM instructions.) Often
|
||||||
|
# a single ZAM operation gives rise to a family of instructions that differ
|
||||||
|
# in either the nature of the instruction's operands (typically, whether
|
||||||
|
# they are variables residing on the ZAM execution frame, or constants)
|
||||||
|
# and/or the Zeek type of the operands (e.g., "count" or "double" or "addr").
|
||||||
|
#
|
||||||
|
# The Gen-ZAM utility processes this file to generate numerous C++ inclusion
|
||||||
|
# files that are then compiled into Zeek. These files span the range of (1)
|
||||||
|
# hooks that enable run-time generation of ZAM code to execute ASTs (which
|
||||||
|
# have first been transformed to "reduced" form), (2) specifications of the
|
||||||
|
# properties of the different instructions, (3) code to evaluate (execute)
|
||||||
|
# each instruction, and (4) macros (C++ #define's) to aid in writing that
|
||||||
|
# code. See Gen-ZAM.h for a list of the different inclusion files.
|
||||||
|
#
|
||||||
|
# Operation templates are declarative, other than the imperative C++ snippets
|
||||||
|
# they include for instruction evaluation/execution. You specify a template
|
||||||
|
# using lines of text for which, for the most part, the first word on the
|
||||||
|
# line designates an "attribute" associated with the template, and the
|
||||||
|
# remainder of the line provides specifiers/arguments for that attribute.
|
||||||
|
# A blank line (or end of file) ends the template. By convention, for
|
||||||
|
# templates that include C++ evaluation snippets, those are specified as the
|
||||||
|
# last attribute. Comments begin with '#' at the start of the line (no
|
||||||
|
# leading whitespace allowed), and can be intermingled with a template's
|
||||||
|
# attributes.
|
||||||
|
#
|
||||||
|
# Each ZAM instruction includes up to 4 integer values and one constant
|
||||||
|
# (specified as a ZVal). Often, the integer values are interpreted as offsets
|
||||||
|
# ("slots") into the ZAM execution "frame", though sometimes they have other
|
||||||
|
# meanings, such as the offset of a particular field in a record, or an index
|
||||||
|
# into the ZAM code for a branch instruction. Most instructions compute
|
||||||
|
# some sort of result (expressed as a ZVal) that is stored into the frame
|
||||||
|
# slot specified by the instruction's first integer value. We refer to this
|
||||||
|
# target as the "assignment slot", and to the other 3 integer values as
|
||||||
|
# "operands". Thus, for example, an instruction with two operands used the
|
||||||
|
# first 3 integer values, the first as the assignment slot and the other two
|
||||||
|
# for computing the result to put in that slot.
|
||||||
|
#
|
||||||
|
# Instruction templates have one or more "type"s associated with them (as
|
||||||
|
# discussed below) specifying the types of operands (variables corresponding
|
||||||
|
# to slots, or constants) associated with the instruction. In the evaluation
|
||||||
|
# code for an instruction, these are referred to with $-parameters, such as
|
||||||
|
# $1 for the first operand. The special parameter $$ refers to the *assignment
|
||||||
|
# target* of the instruction, if applicable. These parameters always come
|
||||||
|
# first when specifying an instruction's type. For example, a type of "VVC"
|
||||||
|
# specifies an instruction with two variables and one constant associated
|
||||||
|
# with it. If the instruction assigns a value, then in the evaluation these
|
||||||
|
# will be specified as $$, $1 and $2, respectively. If it does not (usually
|
||||||
|
# reflected by the template having the "op1-read" attribute) then they
|
||||||
|
# are specified as $1, $2 and $3, respectively. See "eval" below.
|
||||||
|
#
|
||||||
|
# The first attribute of each template states the type of operation specified
|
||||||
|
# in the template, along with the name of the operation. The possible types
|
||||||
|
# are:
|
||||||
|
#
|
||||||
|
# op an operation that generally corresponds to a single ZAM
|
||||||
|
# instruction, and is fully specified
|
||||||
|
#
|
||||||
|
# expr-op an operation corresponding to an AST expression node
|
||||||
|
# (some sort of Expr object). Gen-ZAM generates code for
|
||||||
|
# automatically converting Expr objects to ZAM instructions.
|
||||||
|
# The name of the operation must match that used in the AST
|
||||||
|
# tag, so for example for "expr-op Foo" there must be a
|
||||||
|
# corresponding "EXPR_FOO" tag.
|
||||||
|
#
|
||||||
|
# unary-expr-op an expr-op for a unary Expr object
|
||||||
|
# binary-expr-op an expr-op for a binary Expr object
|
||||||
|
# rel-expr-op an expr-op for a (binary) Expr object that
|
||||||
|
# represents a relational operation
|
||||||
|
#
|
||||||
|
# assign-op directly assigning either a ZVal or a record field
|
||||||
|
# to either a frame slot or a record field
|
||||||
|
#
|
||||||
|
# unary-op an operation with one operand that requires special
|
||||||
|
# treatment that doesn't fit with how unary-expr-op's
|
||||||
|
# are expressed
|
||||||
|
#
|
||||||
|
# direct-unary-op an operation with one operand that corresponds to
|
||||||
|
# a specific ZAMCompiler method for generating its
|
||||||
|
# instruction
|
||||||
|
#
|
||||||
|
# internal-op similar to "op", but for ZAM instructions only used
|
||||||
|
# internally, and thus not having any AST counterpart
|
||||||
|
# internal-assignment-op the same, for operations that assign ZVals
|
||||||
|
# produced by loading interpreter variables
|
||||||
|
# or calling functions
|
||||||
|
#
|
||||||
|
# After specifying the type of operation, you list additional attributes to
|
||||||
|
# fill out the template, ending by convention with the C++ evaluation snippet
|
||||||
|
# (if appropriate). The most significant (and complex) of these are:
|
||||||
|
#
|
||||||
|
# class specifies how to interpret the operation in terms of ZAM
|
||||||
|
# instruction slots (and constant). The specification is
|
||||||
|
# in terms of single-letter mnemonics for the different
|
||||||
|
# possible classes:
|
||||||
|
#
|
||||||
|
# F special value designating a record field being
|
||||||
|
# assigned to
|
||||||
|
# H event handler
|
||||||
|
# L list of values
|
||||||
|
# O opaque value (here, "opaque" refers to ZAM
|
||||||
|
# internals, not OpaqueVal)
|
||||||
|
# R record
|
||||||
|
# V variable (frame slot)
|
||||||
|
# X used to indicate an empty specifier
|
||||||
|
# b branch target
|
||||||
|
# f iteration information associated with table "for" loop
|
||||||
|
# g access to a global
|
||||||
|
# i integer constant, often a record field offset
|
||||||
|
# s iteration information associated with stepping
|
||||||
|
# through a vector or string
|
||||||
|
#
|
||||||
|
# The full specification consists of concatenating mnemonics
|
||||||
|
# with the order left-to-right corresponding to each of the
|
||||||
|
# instruction's 4 integer values (stopping with the last one
|
||||||
|
# used). If the operation includes a constant, then it is
|
||||||
|
# listed at the point reflecting where the constant is used as
|
||||||
|
# an operand. For example, a class of "VVCV" means that the
|
||||||
|
# first integer is used as a frame variable (i.e., the usual
|
||||||
|
# "assignment slot"), the second integer (first "operand") is
|
||||||
|
# also a frame variable, the second operand is the instruction's
|
||||||
|
# constant, and the third operand is the instruction's third
|
||||||
|
# integer value, with the fourth integer value not being used.
|
||||||
|
#
|
||||||
|
# classes specifies a number of "class" values to instantiate over.
|
||||||
|
# Cannot be combined with "class", nor used for expressions.
|
||||||
|
#
|
||||||
|
# op-type for some form of expr-op, specifies to which Zeek scripting
|
||||||
|
# types the expression applies:
|
||||||
|
#
|
||||||
|
# A addr
|
||||||
|
# D double
|
||||||
|
# F file
|
||||||
|
# I int
|
||||||
|
# N subnet
|
||||||
|
# P pattern
|
||||||
|
# R record
|
||||||
|
# S string
|
||||||
|
# T table
|
||||||
|
# U count
|
||||||
|
# V vector
|
||||||
|
#
|
||||||
|
# along with two special types: 'X' indicates that Gen-ZAM
|
||||||
|
# should not iterate over any possible values, and '*'
|
||||||
|
# indicates that Gen-ZAM should additionally iterate over
|
||||||
|
# all of possible values not explicitly listed (used in
|
||||||
|
# conjunction with eval-type - see below)
|
||||||
|
#
|
||||||
|
# op-types similar to op-type, but lists a type for each operand
|
||||||
|
# (including assignment target), so for example "A N A"
|
||||||
|
# would correspond to a 3-operand instruction for which
|
||||||
|
# the first operand (or assignment target) is an "addr",
|
||||||
|
# the second a "subnet", and the third another "addr".
|
||||||
|
#
|
||||||
|
# Note that these types collectively apply to each instance of
|
||||||
|
# an operation, whereas listing multiple "op-type" types
|
||||||
|
# iterates through those one-at-a-time in turn (and generally
|
||||||
|
# the point is that the each type applies to *all* operands,
|
||||||
|
# rather than a per-operand list). Given that, the two are
|
||||||
|
# incompatible.
|
||||||
|
#
|
||||||
|
# For operands corresponding to 'i' or any of the internal types,
|
||||||
|
# such as 'b', 'f', 'g', and 's', the corresponding type to
|
||||||
|
# list is 'I', used for integer access.
|
||||||
|
#
|
||||||
|
# eval specifies a block of C++ code used to evaluation the
|
||||||
|
# execution of the instruction. The block begins with the
|
||||||
|
# remainder of the "eval" line and continues until either a
|
||||||
|
# blank line or a line that starts with non-whitespace.
|
||||||
|
#
|
||||||
|
# Blocks can include special '$' parameters that Gen-ZAM
|
||||||
|
# automatically expands. "$1" refers to an operation's first
|
||||||
|
# operand, "$2" to its second, etc. "$$" refers to the
|
||||||
|
# operation's assignment target.
|
||||||
|
#
|
||||||
|
# For simple expr-op's you can express the block as simply
|
||||||
|
# the C++ expression to compute. For example, for multiplication
|
||||||
|
# (named "Times"), the "eval" block is simply "$1 * $2",
|
||||||
|
# rather than "$$ = $1 * $2"; Gen-ZAM knows to expand it
|
||||||
|
# accordingly.
|
||||||
|
#
|
||||||
|
# Finally, to help with avoiding duplicate code, you can
|
||||||
|
# define macros that expand to code snippets you want to use
|
||||||
|
# in multiple places. You specify these using a "macro"
|
||||||
|
# keyword followed by the name of the macro and an evaluation
|
||||||
|
# block. Macros behave identically to C++ #define's, except
|
||||||
|
# you don't use "\" to continue them across line breaks, but
|
||||||
|
# instead just indent the lines you want included, ending
|
||||||
|
# (as with "eval" blocks) with an empty line or a line that
|
||||||
|
# starts with non-whitespace.
|
||||||
|
#
|
||||||
|
# We list the remaining types of attributes alphabetically. Note that some
|
||||||
|
# only apply to certain types of operations.
|
||||||
|
#
|
||||||
|
# assign-val for an assignment operation, the name of the
|
||||||
|
# C++ variable that holds the value to assign
|
||||||
|
#
|
||||||
|
# custom-method a ZAMCompiler method that Gen-ZAM should use for
|
||||||
|
# this operation, rather than generating one
|
||||||
|
#
|
||||||
|
# eval-mixed an expression "eval" block that applies to two
|
||||||
|
# different op-type's
|
||||||
|
#
|
||||||
|
# eval-type evaluation code associated with one specific op-type
|
||||||
|
#
|
||||||
|
# explicit-result-type the operation's evaluation yields a ZVal
|
||||||
|
# rather than a low-level C++ type
|
||||||
|
#
|
||||||
|
# field-op the operation is a direct assignment to a record field
|
||||||
|
#
|
||||||
|
# includes-field-op the operation should include a version
|
||||||
|
# that assigns to a record field as well as a
|
||||||
|
# version for assigning to a frame variable
|
||||||
|
#
|
||||||
|
# indirect-call the operation represents an indirect call (through
|
||||||
|
# a global variable, rather than directly). Only
|
||||||
|
# meaningful if num-call-args is also specified.
|
||||||
|
#
|
||||||
|
# indirect-local-call same, but via a local variable rather than
|
||||||
|
# global
|
||||||
|
#
|
||||||
|
# method-post C++ code to add to the end of the method that
|
||||||
|
# dynamically generates ZAM code
|
||||||
|
#
|
||||||
|
# no-const do not generate a version of the unary-expr-op
|
||||||
|
# where the operand is a constant
|
||||||
|
#
|
||||||
|
# no-eval this operation does not have an "eval" block
|
||||||
|
# (because it will be translated instead into internal
|
||||||
|
# operations)
|
||||||
|
#
|
||||||
|
# num-call-args indicates that the operation is a function call,
|
||||||
|
# and specifies how many arguments the call takes.
|
||||||
|
# A specification of 'n' means "build a ZAM instruction
|
||||||
|
# for calling with an arbitrary number of arguments".
|
||||||
|
#
|
||||||
|
# op1-internal states that the operation's treatment of the
|
||||||
|
# instruction's first integer value is for internal
|
||||||
|
# purposes; the value does not correspond to a frame
|
||||||
|
# variable
|
||||||
|
#
|
||||||
|
# op1-read the operation treats the instruction's first integer
|
||||||
|
# value as a frame variable, but only reads the value.
|
||||||
|
# (The default is that the frame variable is written
|
||||||
|
# to but not read.)
|
||||||
|
#
|
||||||
|
# op1-read-write the operation treats the instruction's first integer
|
||||||
|
# value as a frame variable, and both reads and
|
||||||
|
# writes the value.
|
||||||
|
#
|
||||||
|
# precheck a test conducted before evaluating an expression,
|
||||||
|
# which is skipped if the test is true. Must be used
|
||||||
|
# in conjunction with precheck-action.
|
||||||
|
#
|
||||||
|
# precheck-action code to execute if a precheck is true, instead
|
||||||
|
# of evaluating the expression. Must be used in
|
||||||
|
# conjunction with precheck.
|
||||||
|
#
|
||||||
|
# set-type the instruction's primary type comes from either the
|
||||||
|
# assignment target ("$$"), the first operand ("$1"),
|
||||||
|
# or the second operand ("$2")
|
||||||
|
#
|
||||||
|
# set-type2 the same as set-type but for the instruction's
|
||||||
|
# secondary type
|
||||||
|
#
|
||||||
|
# side-effects the operation has side-effects, so even if its
|
||||||
|
# assignment target winds up being "dead" (the value is
|
||||||
|
# no longer used), the operation should still occur.
|
||||||
|
# Optionally, this attribute can include two arguments
|
||||||
|
# specifying the ZAM opcode to use if the assignment
|
||||||
|
# is dead, and the internal "type" of that opcode.
|
||||||
|
#
|
||||||
|
# For example, "side-effects OP_CALL1_V OP_V" means
|
||||||
|
# "this operation has side-effects; if eliminating
|
||||||
|
# its assignment, change the ZAM op-code to OP_CALL1_V,
|
||||||
|
# which has an internal type of OP_V".
|
||||||
|
#
|
||||||
|
# vector generate a version of the operation that takes
|
||||||
|
# vectors as operands
|
||||||
|
#
|
||||||
|
# Finally, a note concernning comments: due to internal use of C++ #define
|
||||||
|
# macros, comments in C++ code should use /* ... */ rather than // delimiters.
|
File diff suppressed because it is too large
Load diff
627
src/script_opt/ZAM/OPs/ZBI.op
Normal file
627
src/script_opt/ZAM/OPs/ZBI.op
Normal file
|
@ -0,0 +1,627 @@
|
||||||
|
# Operations corresponding to ZAM BuiltIn Functions.
|
||||||
|
|
||||||
|
internal-op Remove-Teredo
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types R
|
||||||
|
eval auto teredo = zeek::packet_mgr->GetAnalyzer("Teredo");
|
||||||
|
if ( teredo )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key($1);
|
||||||
|
static_cast<zeek::packet_analysis::teredo::TeredoAnalyzer*>(teredo.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Remove-Teredo
|
||||||
|
side-effects OP_REMOVE_TEREDO_V OP_V
|
||||||
|
class VV
|
||||||
|
op-types I R
|
||||||
|
eval auto teredo = zeek::packet_mgr->GetAnalyzer("Teredo");
|
||||||
|
if ( teredo )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key($1);
|
||||||
|
static_cast<zeek::packet_analysis::teredo::TeredoAnalyzer*>(teredo.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
$$ = 1;
|
||||||
|
|
||||||
|
internal-op Remove-GTPv1
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types R
|
||||||
|
eval auto gtpv1 = zeek::packet_mgr->GetAnalyzer("GTPv1");
|
||||||
|
if ( gtpv1 )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key($1);
|
||||||
|
static_cast<zeek::packet_analysis::gtpv1::GTPv1_Analyzer*>(gtpv1.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Remove-GTPv1
|
||||||
|
side-effects OP_REMOVE_GTPV1_V OP_V
|
||||||
|
class VV
|
||||||
|
op-types I R
|
||||||
|
eval auto gtpv1 = zeek::packet_mgr->GetAnalyzer("GTPv1");
|
||||||
|
if ( gtpv1 )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key($1);
|
||||||
|
static_cast<zeek::packet_analysis::gtpv1::GTPv1_Analyzer*>(gtpv1.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
$$ = 1;
|
||||||
|
|
||||||
|
internal-op Set-File-Handle
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types S
|
||||||
|
eval auto handle = $1;
|
||||||
|
auto bytes = reinterpret_cast<const char*>(handle->Bytes());
|
||||||
|
auto h = std::string(bytes, handle->Len());
|
||||||
|
zeek::file_mgr->SetHandle(h);
|
||||||
|
|
||||||
|
internal-op Subnet-To-Addr
|
||||||
|
class VV
|
||||||
|
op-types X N
|
||||||
|
eval auto addr_v = make_intrusive<AddrVal>($1->Prefix());
|
||||||
|
ZVal::DeleteManagedType($$);
|
||||||
|
$$ = ZVal(std::move(addr_v));
|
||||||
|
|
||||||
|
macro EvalSubBytes(lhs, arg1, arg2, arg3)
|
||||||
|
{
|
||||||
|
auto sv = ZAM_sub_bytes(arg1, arg2, arg3);
|
||||||
|
Unref(lhs);
|
||||||
|
lhs = sv;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Sub-Bytes
|
||||||
|
classes VVVV VVVC VVCV VCVV VVCi VCVi
|
||||||
|
op-types S S U I
|
||||||
|
eval EvalSubBytes($$, $1, $2, $3)
|
||||||
|
|
||||||
|
# Use a distinct name because due to the convention when constructing
|
||||||
|
# instructions, frame slots are always positioned earlier than non-frame
|
||||||
|
# slots, i.e. we can't construct "VCiV", which is why the arguments are
|
||||||
|
# in a different order than above.
|
||||||
|
internal-op Sub-Bytes2
|
||||||
|
class VCVi
|
||||||
|
op-types S S I U
|
||||||
|
eval EvalSubBytes($$, $1, $3, $2)
|
||||||
|
|
||||||
|
internal-op Time-To-Double
|
||||||
|
class VV
|
||||||
|
op-types D D
|
||||||
|
eval $$ = $1;
|
||||||
|
|
||||||
|
|
||||||
|
internal-op To-Lower
|
||||||
|
class VV
|
||||||
|
op-types S S
|
||||||
|
eval auto sv = ZAM_to_lower($1);
|
||||||
|
Unref($$);
|
||||||
|
$$ = sv;
|
||||||
|
|
||||||
|
# A ZAM version of Log::__write. In calls to it, the first argument
|
||||||
|
# is generally a constant (enum) *if we inlined*, but otherwise a
|
||||||
|
# parameter, so we support both VVV ad VVC.
|
||||||
|
#
|
||||||
|
# It's actually the case that the return value is pretty much always
|
||||||
|
# ignored ... plus optimization can elide it away. See the second
|
||||||
|
# pair of built-ins for versions that discard the return value.
|
||||||
|
#
|
||||||
|
# Could speed things up further by modifying the Write method to just
|
||||||
|
# take the raw enum value, as it appears that that's all that's ever
|
||||||
|
# actually used.
|
||||||
|
|
||||||
|
macro LogWritePre(id_val, columns_val)
|
||||||
|
auto id = id_val;
|
||||||
|
auto columns = columns_val;
|
||||||
|
|
||||||
|
macro LogWriteResPost(lhs)
|
||||||
|
bool result = log_mgr->Write(id->AsEnumVal(), columns->AsRecordVal());
|
||||||
|
lhs = result;
|
||||||
|
|
||||||
|
internal-op Log-Write
|
||||||
|
side-effects OP_LOG_WRITE_VV OP_VV
|
||||||
|
class VVV
|
||||||
|
op-types I X R
|
||||||
|
eval LogWritePre(LogEnum($1), $2)
|
||||||
|
LogWriteResPost($$)
|
||||||
|
|
||||||
|
### Check that invoked correctly
|
||||||
|
internal-op Log-WriteC
|
||||||
|
side-effects OP_LOG_WRITE_CV OP_VC
|
||||||
|
class VCV
|
||||||
|
op-types I X R
|
||||||
|
eval LogWritePre(LogEnum($1), $2)
|
||||||
|
LogWriteResPost($$)
|
||||||
|
|
||||||
|
# Versions that discard the return value.
|
||||||
|
internal-op Log-Write
|
||||||
|
side-effects
|
||||||
|
op1-read
|
||||||
|
classes VV CV
|
||||||
|
op-types X R
|
||||||
|
eval LogWritePre(LogEnum($1), $2)
|
||||||
|
(void) log_mgr->Write(id->AsEnumVal(), columns->AsRecordVal());
|
||||||
|
|
||||||
|
internal-op Broker-Flush-Logs
|
||||||
|
side-effects OP_BROKER_FLUSH_LOGS_X OP_X
|
||||||
|
class V
|
||||||
|
op-types U
|
||||||
|
eval $$ = broker_mgr->FlushLogBuffers();
|
||||||
|
|
||||||
|
internal-op Broker-Flush-Logs
|
||||||
|
side-effects
|
||||||
|
class X
|
||||||
|
eval (void) broker_mgr->FlushLogBuffers();
|
||||||
|
|
||||||
|
internal-op Get-Port-Transport-Proto
|
||||||
|
class VV
|
||||||
|
op-types U U
|
||||||
|
eval auto mask = $1 & PORT_SPACE_MASK;
|
||||||
|
auto v = 0; /* TRANSPORT_UNKNOWN */
|
||||||
|
if ( mask == TCP_PORT_MASK )
|
||||||
|
v = 1;
|
||||||
|
else if ( mask == UDP_PORT_MASK )
|
||||||
|
v = 2;
|
||||||
|
else if ( mask == ICMP_PORT_MASK )
|
||||||
|
v = 3;
|
||||||
|
$$ = v;
|
||||||
|
|
||||||
|
predicate-op Conn-Exists
|
||||||
|
class V
|
||||||
|
op-types R
|
||||||
|
eval session_mgr->FindConnection($1) != nullptr
|
||||||
|
|
||||||
|
internal-op Lookup-Conn
|
||||||
|
class VV
|
||||||
|
op-types X R
|
||||||
|
eval auto cid = $1;
|
||||||
|
Connection* conn = session_mgr->FindConnection(cid);
|
||||||
|
ValPtr res;
|
||||||
|
if ( conn )
|
||||||
|
res = conn->GetVal();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERROR2("connection ID not a known connection", cid);
|
||||||
|
res = build_dummy_conn_record();
|
||||||
|
}
|
||||||
|
AssignTarget($$, ZVal(res, res->GetType()));
|
||||||
|
|
||||||
|
predicate-op Is-ICMP-Port
|
||||||
|
class V
|
||||||
|
op-types U
|
||||||
|
eval ($1 & PORT_SPACE_MASK) == ICMP_PORT_MASK
|
||||||
|
|
||||||
|
predicate-op Is-TCP-Port
|
||||||
|
class V
|
||||||
|
op-types U
|
||||||
|
eval ($1 & PORT_SPACE_MASK) == TCP_PORT_MASK
|
||||||
|
|
||||||
|
predicate-op Is-UDP-Port
|
||||||
|
class V
|
||||||
|
op-types U
|
||||||
|
eval ($1 & PORT_SPACE_MASK) == UDP_PORT_MASK
|
||||||
|
|
||||||
|
predicate-op Is-V4-Addr
|
||||||
|
class V
|
||||||
|
op-types A
|
||||||
|
eval $1->AsAddr().GetFamily() == IPv4
|
||||||
|
|
||||||
|
predicate-op Is-V6-Addr
|
||||||
|
class V
|
||||||
|
op-types A
|
||||||
|
eval $1->AsAddr().GetFamily() == IPv6
|
||||||
|
|
||||||
|
internal-op Network-Time
|
||||||
|
class V
|
||||||
|
op-types D
|
||||||
|
eval $$ = run_state::network_time;
|
||||||
|
|
||||||
|
internal-op Current-Time
|
||||||
|
class V
|
||||||
|
op-types D
|
||||||
|
eval $$ = util::current_time();
|
||||||
|
|
||||||
|
predicate-op Reading-Live-Traffic
|
||||||
|
class X
|
||||||
|
eval run_state::reading_live
|
||||||
|
|
||||||
|
predicate-op Reading-Traces
|
||||||
|
class X
|
||||||
|
eval run_state::reading_traces
|
||||||
|
|
||||||
|
internal-op Sort
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types V
|
||||||
|
eval if ( $1->Size() > 1 )
|
||||||
|
$1->Sort();
|
||||||
|
|
||||||
|
internal-op Sort
|
||||||
|
class VV
|
||||||
|
op-types V V
|
||||||
|
eval auto vv = $1;
|
||||||
|
if ( vv->Size() > 1 )
|
||||||
|
vv->Sort();
|
||||||
|
zeek::Ref(vv);
|
||||||
|
Unref($$);
|
||||||
|
$$ = vv;
|
||||||
|
|
||||||
|
internal-op Sort-With-Cmp
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
op-types V F
|
||||||
|
eval if ( $1->Size() > 1 )
|
||||||
|
$1->Sort($2);
|
||||||
|
|
||||||
|
internal-op Sort-With-Cmp
|
||||||
|
class VVV
|
||||||
|
op-types V V F
|
||||||
|
eval auto vv = $1;
|
||||||
|
if ( vv->Size() > 1 )
|
||||||
|
vv->Sort($2);
|
||||||
|
zeek::Ref(vv);
|
||||||
|
Unref($$);
|
||||||
|
$$ = vv;
|
||||||
|
|
||||||
|
internal-op Starts-With
|
||||||
|
classes VVV VCV VVC
|
||||||
|
op-types I S S
|
||||||
|
eval auto str = $1;
|
||||||
|
auto sub = $2;
|
||||||
|
auto str_n = str->Len();
|
||||||
|
auto sub_n = sub->Len();
|
||||||
|
if ( str_n < sub_n )
|
||||||
|
$$ = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto str_b = str->Bytes();
|
||||||
|
auto sub_b = sub->Bytes();
|
||||||
|
int i;
|
||||||
|
for ( i = 0; i < sub_n; ++i )
|
||||||
|
if ( str_b[i] != sub_b[i] )
|
||||||
|
break;
|
||||||
|
$$ = i == sub_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op StrCmp
|
||||||
|
classes VVV VCV VVC
|
||||||
|
op-types I S S
|
||||||
|
eval auto s1 = $1;
|
||||||
|
auto s2 = $2;
|
||||||
|
$$ = Bstr_cmp(s1->AsString(), s2->AsString());
|
||||||
|
|
||||||
|
internal-op StrStr
|
||||||
|
classes VVV VCV VVC
|
||||||
|
op-types I S S
|
||||||
|
eval auto big = $1;
|
||||||
|
auto little = $2;
|
||||||
|
$$ = 1 + big->AsString()->FindSubstring(little->AsString());
|
||||||
|
|
||||||
|
macro Cat1Op(lhs, val)
|
||||||
|
auto& v1 = lhs;
|
||||||
|
ZVal::DeleteManagedType(v1);
|
||||||
|
v1 = val;
|
||||||
|
|
||||||
|
internal-op Cat1
|
||||||
|
classes VV VC
|
||||||
|
eval Cat1Op($$, $1)
|
||||||
|
zeek::Ref(v1.AsString());
|
||||||
|
|
||||||
|
internal-op Cat1Full
|
||||||
|
classes VV VC
|
||||||
|
eval auto formatted_val = ZVal(ZAM_val_cat($1.ToVal(Z_TYPE)));
|
||||||
|
Cat1Op($$, formatted_val)
|
||||||
|
|
||||||
|
internal-op CatN
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
int n = aux->n;
|
||||||
|
size_t max_size = 0;
|
||||||
|
for ( int i = 0; i < n; ++i )
|
||||||
|
max_size += ca[i]->MaxSize(aux->elems[i].ToDirectZVal(frame));
|
||||||
|
auto res = new char[max_size + /* slop */ n + 1];
|
||||||
|
auto res_p = res;
|
||||||
|
for ( int i = 0; i < n; ++i )
|
||||||
|
ca[i]->RenderInto(aux->elems[i].ToDirectZVal(frame), res_p);
|
||||||
|
*res_p = '\0';
|
||||||
|
auto s = new String(true, reinterpret_cast<byte_vec>(res), res_p - res);
|
||||||
|
Cat1Op($$, ZVal(new StringVal(s)))
|
||||||
|
|
||||||
|
macro CatNPre()
|
||||||
|
auto aux = Z_AUX;
|
||||||
|
auto& ca = aux->cat_args;
|
||||||
|
|
||||||
|
macro CatNMid()
|
||||||
|
auto res = new char[max_size + /* slop */ 10];
|
||||||
|
auto res_p = res;
|
||||||
|
|
||||||
|
macro CatNPost(lhs)
|
||||||
|
*res_p = '\0';
|
||||||
|
auto s = new String(true, reinterpret_cast<byte_vec>(res), res_p - res);
|
||||||
|
Cat1Op(lhs, ZVal(new StringVal(s)))
|
||||||
|
|
||||||
|
internal-op Cat2
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Cat3
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
max_size += ca[2]->MaxSize(aux->elems[2].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
ca[2]->RenderInto(aux->elems[2].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Cat4
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
max_size += ca[2]->MaxSize(aux->elems[2].ToDirectZVal(frame));
|
||||||
|
max_size += ca[3]->MaxSize(aux->elems[3].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
ca[2]->RenderInto(aux->elems[2].ToDirectZVal(frame), res_p);
|
||||||
|
ca[3]->RenderInto(aux->elems[3].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Cat5
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
max_size += ca[2]->MaxSize(aux->elems[2].ToDirectZVal(frame));
|
||||||
|
max_size += ca[3]->MaxSize(aux->elems[3].ToDirectZVal(frame));
|
||||||
|
max_size += ca[4]->MaxSize(aux->elems[4].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
ca[2]->RenderInto(aux->elems[2].ToDirectZVal(frame), res_p);
|
||||||
|
ca[3]->RenderInto(aux->elems[3].ToDirectZVal(frame), res_p);
|
||||||
|
ca[4]->RenderInto(aux->elems[4].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Cat6
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
max_size += ca[2]->MaxSize(aux->elems[2].ToDirectZVal(frame));
|
||||||
|
max_size += ca[3]->MaxSize(aux->elems[3].ToDirectZVal(frame));
|
||||||
|
max_size += ca[4]->MaxSize(aux->elems[4].ToDirectZVal(frame));
|
||||||
|
max_size += ca[5]->MaxSize(aux->elems[5].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
ca[2]->RenderInto(aux->elems[2].ToDirectZVal(frame), res_p);
|
||||||
|
ca[3]->RenderInto(aux->elems[3].ToDirectZVal(frame), res_p);
|
||||||
|
ca[4]->RenderInto(aux->elems[4].ToDirectZVal(frame), res_p);
|
||||||
|
ca[5]->RenderInto(aux->elems[5].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Cat7
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
max_size += ca[2]->MaxSize(aux->elems[2].ToDirectZVal(frame));
|
||||||
|
max_size += ca[3]->MaxSize(aux->elems[3].ToDirectZVal(frame));
|
||||||
|
max_size += ca[4]->MaxSize(aux->elems[4].ToDirectZVal(frame));
|
||||||
|
max_size += ca[5]->MaxSize(aux->elems[5].ToDirectZVal(frame));
|
||||||
|
max_size += ca[6]->MaxSize(aux->elems[6].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
ca[2]->RenderInto(aux->elems[2].ToDirectZVal(frame), res_p);
|
||||||
|
ca[3]->RenderInto(aux->elems[3].ToDirectZVal(frame), res_p);
|
||||||
|
ca[4]->RenderInto(aux->elems[4].ToDirectZVal(frame), res_p);
|
||||||
|
ca[5]->RenderInto(aux->elems[5].ToDirectZVal(frame), res_p);
|
||||||
|
ca[6]->RenderInto(aux->elems[6].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Cat8
|
||||||
|
class V
|
||||||
|
eval CatNPre()
|
||||||
|
size_t max_size = ca[0]->MaxSize(aux->elems[0].ToDirectZVal(frame));
|
||||||
|
max_size += ca[1]->MaxSize(aux->elems[1].ToDirectZVal(frame));
|
||||||
|
max_size += ca[2]->MaxSize(aux->elems[2].ToDirectZVal(frame));
|
||||||
|
max_size += ca[3]->MaxSize(aux->elems[3].ToDirectZVal(frame));
|
||||||
|
max_size += ca[4]->MaxSize(aux->elems[4].ToDirectZVal(frame));
|
||||||
|
max_size += ca[5]->MaxSize(aux->elems[5].ToDirectZVal(frame));
|
||||||
|
max_size += ca[6]->MaxSize(aux->elems[6].ToDirectZVal(frame));
|
||||||
|
max_size += ca[7]->MaxSize(aux->elems[7].ToDirectZVal(frame));
|
||||||
|
CatNMid()
|
||||||
|
ca[0]->RenderInto(aux->elems[0].ToDirectZVal(frame), res_p);
|
||||||
|
ca[1]->RenderInto(aux->elems[1].ToDirectZVal(frame), res_p);
|
||||||
|
ca[2]->RenderInto(aux->elems[2].ToDirectZVal(frame), res_p);
|
||||||
|
ca[3]->RenderInto(aux->elems[3].ToDirectZVal(frame), res_p);
|
||||||
|
ca[4]->RenderInto(aux->elems[4].ToDirectZVal(frame), res_p);
|
||||||
|
ca[5]->RenderInto(aux->elems[5].ToDirectZVal(frame), res_p);
|
||||||
|
ca[6]->RenderInto(aux->elems[6].ToDirectZVal(frame), res_p);
|
||||||
|
ca[7]->RenderInto(aux->elems[7].ToDirectZVal(frame), res_p);
|
||||||
|
CatNPost($$)
|
||||||
|
|
||||||
|
internal-op Analyzer-Name
|
||||||
|
classes VV VC
|
||||||
|
op-types S X
|
||||||
|
eval auto atype = $1.ToVal(Z_TYPE);
|
||||||
|
auto val = atype->AsEnumVal();
|
||||||
|
Unref($$);
|
||||||
|
plugin::Component* component = zeek::analyzer_mgr->Lookup(val);
|
||||||
|
if ( ! component )
|
||||||
|
component = zeek::packet_mgr->Lookup(val);
|
||||||
|
if ( ! component )
|
||||||
|
component = zeek::file_mgr->Lookup(val);
|
||||||
|
if ( component )
|
||||||
|
$$ = new StringVal(component->CanonicalName());
|
||||||
|
else
|
||||||
|
$$ = new StringVal("<error>");
|
||||||
|
|
||||||
|
macro FilesAddOrRemoveAnalyzer(file_id_val, tag, args_val, METHOD)
|
||||||
|
auto file_id = file_id_val;
|
||||||
|
using zeek::BifType::Record::Files::AnalyzerArgs;
|
||||||
|
auto rv = args_val->CoerceTo(AnalyzerArgs);
|
||||||
|
bool result = zeek::file_mgr->METHOD(
|
||||||
|
file_id->CheckString(),
|
||||||
|
zeek::file_mgr->GetComponentTag(tag.ToVal(Z_TYPE).get()),
|
||||||
|
std::move(rv));
|
||||||
|
|
||||||
|
macro FilesAddAnalyzer(file_id_val, tag, args_val)
|
||||||
|
FilesAddOrRemoveAnalyzer(file_id_val, tag, args_val, AddAnalyzer)
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
op1-read
|
||||||
|
classes VVV VCV
|
||||||
|
op-types S X R
|
||||||
|
eval FilesAddAnalyzer($1, $2, $3)
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
class VVVV
|
||||||
|
side-effects OP_FILES_ADD_ANALYZER_VVV OP_VVV
|
||||||
|
op-types I S X R
|
||||||
|
eval FilesAddAnalyzer($1, $2, $3)
|
||||||
|
$$ = result;
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
class VVCV
|
||||||
|
op-types I S X R
|
||||||
|
side-effects OP_FILES_ADD_ANALYZER_VCV OP_VVC
|
||||||
|
eval FilesAddAnalyzer($1, $2, $3)
|
||||||
|
$$ = result;
|
||||||
|
|
||||||
|
macro FilesRemoveAnalyzer(file_id_val, tag, args_slot)
|
||||||
|
FilesAddOrRemoveAnalyzer(file_id_val, tag, args_slot, RemoveAnalyzer)
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
op1-read
|
||||||
|
classes VVV VCV
|
||||||
|
op-types S X R
|
||||||
|
eval FilesRemoveAnalyzer($1, $2, $3)
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
class VVVV
|
||||||
|
op-types I S X R
|
||||||
|
side-effects OP_FILES_REMOVE_ANALYZER_VVV OP_VVV
|
||||||
|
eval FilesRemoveAnalyzer($1, $2, $3)
|
||||||
|
$$ = result;
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
class VVCV
|
||||||
|
op-types I S X R
|
||||||
|
side-effects OP_FILES_REMOVE_ANALYZER_VCV OP_VVC
|
||||||
|
eval FilesRemoveAnalyzer($1, $2, $3)
|
||||||
|
$$ = result;
|
||||||
|
|
||||||
|
internal-op Analyzer-Enabled
|
||||||
|
classes VV VC
|
||||||
|
op-types I X
|
||||||
|
eval auto atype = $1.ToVal(Z_TYPE);
|
||||||
|
auto c = zeek::file_mgr->Lookup(atype->AsEnumVal());
|
||||||
|
$$ = c && c->Enabled();
|
||||||
|
|
||||||
|
internal-op File-Analyzer-Name
|
||||||
|
classes VV VC
|
||||||
|
eval auto atype = $1.ToVal(Z_TYPE);
|
||||||
|
Unref($$.AsString());
|
||||||
|
$$ = ZVal(file_mgr->GetComponentNameVal({NewRef{}, atype->AsEnumVal()}));
|
||||||
|
|
||||||
|
internal-op Is-Protocol-Analyzer
|
||||||
|
classes VV VC
|
||||||
|
op-types I X
|
||||||
|
eval auto atype = $1.ToVal(Z_TYPE);
|
||||||
|
$$ = analyzer_mgr->Lookup(atype->AsEnumVal()) != nullptr;
|
||||||
|
|
||||||
|
internal-op Clear-Table
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types T
|
||||||
|
eval $1->RemoveAll();
|
||||||
|
|
||||||
|
internal-op Files-Enable-Reassembly
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types S
|
||||||
|
eval auto f = $1->CheckString();
|
||||||
|
file_mgr->EnableReassembly(f);
|
||||||
|
|
||||||
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
|
op1-read
|
||||||
|
classes VV Vi
|
||||||
|
op-types S U
|
||||||
|
eval auto f = $1->CheckString();
|
||||||
|
file_mgr->SetReassemblyBuffer(f, $2);
|
||||||
|
|
||||||
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
|
class VVV
|
||||||
|
op-types I S U
|
||||||
|
side-effects OP_FILES_SET_REASSEMBLY_BUFFER_VV OP_VV
|
||||||
|
eval auto f = $1->CheckString();
|
||||||
|
$$ = file_mgr->SetReassemblyBuffer(f, $2);
|
||||||
|
|
||||||
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
|
class VVi
|
||||||
|
op-types I S U
|
||||||
|
side-effects OP_FILES_SET_REASSEMBLY_BUFFER_Vi OP_VV_I2
|
||||||
|
eval auto f = $1->CheckString();
|
||||||
|
$$ = file_mgr->SetReassemblyBuffer(f, $2);
|
||||||
|
|
||||||
|
internal-op Get-Bytes-Thresh
|
||||||
|
classes VVV VVC
|
||||||
|
op-types U R I
|
||||||
|
eval auto a = analyzer::conn_size::GetConnsizeAnalyzer($1);
|
||||||
|
auto res = 0U;
|
||||||
|
if ( a )
|
||||||
|
res = static_cast<analyzer::conn_size::ConnSize_Analyzer*>(a)->GetByteAndPacketThreshold(true, $2);
|
||||||
|
$$ = res;
|
||||||
|
|
||||||
|
macro SetBytesThresh(cid, threshold, is_orig)
|
||||||
|
bool res = false;
|
||||||
|
auto a = analyzer::conn_size::GetConnsizeAnalyzer(cid);
|
||||||
|
if ( a )
|
||||||
|
{
|
||||||
|
static_cast<analyzer::conn_size::ConnSize_Analyzer*>(a)->SetByteAndPacketThreshold(threshold, true, is_orig);
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
op1-read
|
||||||
|
classes VVV VVC VCV VCi
|
||||||
|
op-types R U I
|
||||||
|
eval SetBytesThresh($1, $2, $3)
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
class VVVV
|
||||||
|
op-types I R U I
|
||||||
|
side-effects OP_SET_BYTES_THRESH_VVV OP_VVV
|
||||||
|
eval SetBytesThresh($1, $2, $3)
|
||||||
|
$$ = res;
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
class VVVC
|
||||||
|
op-types I R U I
|
||||||
|
side-effects OP_SET_BYTES_THRESH_VVC OP_VVC
|
||||||
|
eval SetBytesThresh($1, $2, $3)
|
||||||
|
$$ = res;
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
class VVCV
|
||||||
|
op-types I R U I
|
||||||
|
side-effects OP_SET_BYTES_THRESH_VCV OP_VVC
|
||||||
|
eval SetBytesThresh($1, $2, $3)
|
||||||
|
$$ = res;
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
class VVCi
|
||||||
|
op-types I R U I
|
||||||
|
side-effects OP_SET_BYTES_THRESH_VCi OP_VVC_I2
|
||||||
|
eval SetBytesThresh($1, $2, $3)
|
||||||
|
$$ = res;
|
89
src/script_opt/ZAM/OPs/aggr-assignments.op
Normal file
89
src/script_opt/ZAM/OPs/aggr-assignments.op
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# Operations corresponding to assigning to elements of aggregates.
|
||||||
|
|
||||||
|
macro VectorElemAssignPre(vec, index)
|
||||||
|
auto ind = index.AsCount();
|
||||||
|
auto vv = vec.AsVector();
|
||||||
|
|
||||||
|
macro EvalVectorElemAssign(vec, index, val_setup, assign_op)
|
||||||
|
VectorElemAssignPre(vec, index)
|
||||||
|
val_setup
|
||||||
|
if ( ! assign_op )
|
||||||
|
ERROR("value used but not set");
|
||||||
|
|
||||||
|
op Vector-Elem-Assign
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
class VVV
|
||||||
|
eval EvalVectorElemAssign($1, $2,, copy_vec_elem(vv, ind, $3, Z_TYPE))
|
||||||
|
|
||||||
|
op Any-Vector-Elem-Assign
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
classes VVV VVC
|
||||||
|
eval EvalVectorElemAssign($1, $2,, vv->Assign(ind, $3.ToVal(Z_TYPE)))
|
||||||
|
|
||||||
|
op Vector-Elem-Assign-Any
|
||||||
|
op1-read
|
||||||
|
class VVV
|
||||||
|
op-types X X a
|
||||||
|
eval EvalVectorElemAssign($1, $2, auto any_v = $3;, vv->Assign(ind, {NewRef{}, any_v}))
|
||||||
|
|
||||||
|
op Vector-Elem-Assign
|
||||||
|
op1-read
|
||||||
|
set-type $2
|
||||||
|
class VVC
|
||||||
|
eval VectorElemAssignPre($1, $2)
|
||||||
|
(void) copy_vec_elem(vv, ind, $3, Z_TYPE);
|
||||||
|
|
||||||
|
# These versions are used when the constant is the index, not the new value.
|
||||||
|
op Vector-Elem-Assign
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
class VVi
|
||||||
|
op-types V X U
|
||||||
|
eval auto vv = $1;
|
||||||
|
if ( ! copy_vec_elem(vv, $3, $2, Z_TYPE) )
|
||||||
|
ERROR("value used but not set");
|
||||||
|
|
||||||
|
op Any-Vector-Elem-Assign
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
class VVi
|
||||||
|
op-types V X I
|
||||||
|
eval auto vv = $1;
|
||||||
|
if ( ! vv->Assign($3, $2.ToVal(Z_TYPE)) )
|
||||||
|
ERROR("value used but not set");
|
||||||
|
|
||||||
|
op Vector-Elem-Assign-Any
|
||||||
|
op1-read
|
||||||
|
class VVi
|
||||||
|
op-types V a I
|
||||||
|
eval auto vv = $1;
|
||||||
|
auto any_v = $2;
|
||||||
|
vv->Assign($3, {NewRef{}, any_v});
|
||||||
|
|
||||||
|
internal-op Vector-Slice-Assign
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
op-types V V
|
||||||
|
eval ValPtr vec = {NewRef{}, $1};
|
||||||
|
auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
ValPtr vals = {NewRef{}, $2};
|
||||||
|
bool iterators_invalidated;
|
||||||
|
auto error = assign_to_index(std::move(vec), std::move(indices), std::move(vals), iterators_invalidated);
|
||||||
|
if ( error )
|
||||||
|
ERROR(error);
|
||||||
|
if ( iterators_invalidated )
|
||||||
|
WARN("possible loop/iterator invalidation");
|
||||||
|
|
||||||
|
|
||||||
|
internal-op Table-Elem-Assign
|
||||||
|
op1-read
|
||||||
|
classes VV VC
|
||||||
|
op-types T X
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
auto val = $2.ToVal(Z_TYPE);
|
||||||
|
bool iterators_invalidated = false;
|
||||||
|
$1->Assign(std::move(indices), std::move(val), true, &iterators_invalidated);
|
||||||
|
if ( iterators_invalidated )
|
||||||
|
WARN("possible loop/iterator invalidation");
|
104
src/script_opt/ZAM/OPs/binary-exprs.op
Normal file
104
src/script_opt/ZAM/OPs/binary-exprs.op
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
# Operations corresponding to binary expressions.
|
||||||
|
|
||||||
|
binary-expr-op Add
|
||||||
|
op-type I U D S
|
||||||
|
vector
|
||||||
|
eval $1 + $2
|
||||||
|
eval-type S vector<const String*> strings;
|
||||||
|
strings.push_back($1->AsString());
|
||||||
|
strings.push_back($2->AsString());
|
||||||
|
auto res = new StringVal(concatenate(strings));
|
||||||
|
$$ = res;
|
||||||
|
|
||||||
|
binary-expr-op Sub
|
||||||
|
op-type I U D T
|
||||||
|
vector
|
||||||
|
eval $1 - $2
|
||||||
|
#
|
||||||
|
eval-type T auto v = $1->Clone();
|
||||||
|
auto s = v.release()->AsTableVal();
|
||||||
|
$2->RemoveFrom(s);
|
||||||
|
$$ = s;
|
||||||
|
|
||||||
|
binary-expr-op Times
|
||||||
|
op-type I U D
|
||||||
|
vector
|
||||||
|
eval $1 * $2
|
||||||
|
|
||||||
|
binary-expr-op Divide
|
||||||
|
op-type I U D
|
||||||
|
vector
|
||||||
|
#
|
||||||
|
precheck $2 == 0
|
||||||
|
precheck-action ERROR("division by zero");
|
||||||
|
eval $1 / $2
|
||||||
|
|
||||||
|
binary-expr-op Mask
|
||||||
|
# Signal that this expression only has mixed-type evaluation.
|
||||||
|
op-type X
|
||||||
|
explicit-result-type
|
||||||
|
eval-mixed A I auto mask = static_cast<uint32_t>($2);
|
||||||
|
auto a = $1->AsAddr();
|
||||||
|
if ( a.GetFamily() == IPv4 && mask > 32 )
|
||||||
|
ERROR(util::fmt("bad IPv4 subnet prefix length: %" PRIu32, mask));
|
||||||
|
if ( a.GetFamily() == IPv6 && mask > 128 )
|
||||||
|
ERROR(util::fmt("bad IPv6 subnet prefix length: %" PRIu32, mask));
|
||||||
|
auto v = make_intrusive<SubNetVal>(a, mask);
|
||||||
|
Unref($$.AsSubNet());
|
||||||
|
$$.AsSubNetRef() = v.release();
|
||||||
|
|
||||||
|
binary-expr-op Mod
|
||||||
|
op-type I U
|
||||||
|
vector
|
||||||
|
precheck $2 == 0
|
||||||
|
precheck-action ERROR("modulo by zero");
|
||||||
|
eval $1 % $2
|
||||||
|
|
||||||
|
binary-expr-op And-And
|
||||||
|
op-type I
|
||||||
|
vector
|
||||||
|
eval zeek_int_t($1 && $2)
|
||||||
|
|
||||||
|
binary-expr-op Or-Or
|
||||||
|
op-type I
|
||||||
|
vector
|
||||||
|
eval zeek_int_t($1 || $2)
|
||||||
|
|
||||||
|
binary-expr-op And
|
||||||
|
op-type U P T
|
||||||
|
vector
|
||||||
|
eval $1 & $2
|
||||||
|
#
|
||||||
|
eval-type P $$ = new PatternVal(RE_Matcher_conjunction($1->AsPattern(), $2->AsPattern()));
|
||||||
|
#
|
||||||
|
eval-type T $$ = $1->Intersection(*$2).release();
|
||||||
|
|
||||||
|
binary-expr-op Or
|
||||||
|
op-type U P T
|
||||||
|
vector
|
||||||
|
eval $1 | $2
|
||||||
|
#
|
||||||
|
eval-type P $$ = new PatternVal(RE_Matcher_disjunction($1->AsPattern(), $2->AsPattern()));
|
||||||
|
#
|
||||||
|
eval-type T auto v = $1->Clone();
|
||||||
|
auto s = v.release()->AsTableVal();
|
||||||
|
(void) $2->AddTo(s, false, false);
|
||||||
|
$$ = s;
|
||||||
|
|
||||||
|
binary-expr-op Xor
|
||||||
|
op-type U
|
||||||
|
vector
|
||||||
|
eval $1 ^ $2
|
||||||
|
|
||||||
|
binary-expr-op Lshift
|
||||||
|
op-type I U
|
||||||
|
vector
|
||||||
|
eval-type I if ( $1 < 0 )
|
||||||
|
ERROR("left shifting a negative number is undefined");
|
||||||
|
$$ = $1 << $2;
|
||||||
|
eval $1 << $2
|
||||||
|
|
||||||
|
binary-expr-op Rshift
|
||||||
|
op-type I U
|
||||||
|
vector
|
||||||
|
eval $1 >> $2
|
180
src/script_opt/ZAM/OPs/calls.op
Normal file
180
src/script_opt/ZAM/OPs/calls.op
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
# Operations corresponding to function calls.
|
||||||
|
|
||||||
|
# A call with no arguments and no return value.
|
||||||
|
internal-op Call0
|
||||||
|
op1-read
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
num-call-args 0
|
||||||
|
|
||||||
|
# A call with no arguments and a return value.
|
||||||
|
internal-assignment-op Call0
|
||||||
|
class V
|
||||||
|
side-effects OP_CALL0_X OP_X
|
||||||
|
assign-val v
|
||||||
|
num-call-args 0
|
||||||
|
|
||||||
|
# Calls with 1 argument and no return value.
|
||||||
|
internal-op Call1
|
||||||
|
op1-read
|
||||||
|
classes V C
|
||||||
|
side-effects
|
||||||
|
num-call-args 1
|
||||||
|
|
||||||
|
# Same but with a return value.
|
||||||
|
internal-assignment-op Call1
|
||||||
|
class VV
|
||||||
|
side-effects OP_CALL1_V OP_V
|
||||||
|
assign-val v
|
||||||
|
num-call-args 1
|
||||||
|
|
||||||
|
internal-assignment-op Call1
|
||||||
|
class VC
|
||||||
|
side-effects OP_CALL1_C OP_C
|
||||||
|
assign-val v
|
||||||
|
num-call-args 1
|
||||||
|
|
||||||
|
# Calls with 2-5 arguments and no return value.
|
||||||
|
internal-op Call2
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
num-call-args 2
|
||||||
|
|
||||||
|
# Same with a return value.
|
||||||
|
internal-assignment-op Call2
|
||||||
|
class V
|
||||||
|
side-effects OP_CALL2_X OP_X
|
||||||
|
assign-val v
|
||||||
|
num-call-args 2
|
||||||
|
|
||||||
|
internal-op Call3
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
num-call-args 3
|
||||||
|
|
||||||
|
# Same with a return value.
|
||||||
|
internal-assignment-op Call3
|
||||||
|
class V
|
||||||
|
side-effects OP_CALL3_X OP_X
|
||||||
|
assign-val v
|
||||||
|
num-call-args 3
|
||||||
|
|
||||||
|
internal-op Call4
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
num-call-args 4
|
||||||
|
|
||||||
|
# Same with a return value.
|
||||||
|
internal-assignment-op Call4
|
||||||
|
class V
|
||||||
|
side-effects OP_CALL4_X OP_X
|
||||||
|
assign-val v
|
||||||
|
num-call-args 4
|
||||||
|
|
||||||
|
internal-op Call5
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
num-call-args 5
|
||||||
|
|
||||||
|
# Same with a return value.
|
||||||
|
internal-assignment-op Call5
|
||||||
|
class V
|
||||||
|
side-effects OP_CALL5_X OP_X
|
||||||
|
assign-val v
|
||||||
|
num-call-args 5
|
||||||
|
|
||||||
|
# ... and with an arbitrary number of arguments.
|
||||||
|
|
||||||
|
internal-op CallN
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
num-call-args n
|
||||||
|
|
||||||
|
# Same with a return value.
|
||||||
|
internal-assignment-op CallN
|
||||||
|
class V
|
||||||
|
side-effects OP_CALLN_X OP_X
|
||||||
|
assign-val v
|
||||||
|
num-call-args n
|
||||||
|
|
||||||
|
# Same, but for indirect calls via a global variable.
|
||||||
|
internal-op IndCallN
|
||||||
|
class X
|
||||||
|
side-effects
|
||||||
|
indirect-call
|
||||||
|
num-call-args n
|
||||||
|
|
||||||
|
# Same with a return value.
|
||||||
|
internal-assignment-op IndCallN
|
||||||
|
class V
|
||||||
|
side-effects OP_INDCALLN_X OP_X
|
||||||
|
assign-val v
|
||||||
|
indirect-call
|
||||||
|
num-call-args n
|
||||||
|
|
||||||
|
# And versions with a local variable rather than a global.
|
||||||
|
internal-op Local-IndCallN
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
side-effects
|
||||||
|
indirect-local-call
|
||||||
|
num-call-args n
|
||||||
|
|
||||||
|
internal-assignment-op Local-IndCallN
|
||||||
|
class VV
|
||||||
|
side-effects OP_LOCAL_INDCALLN_V OP_V
|
||||||
|
assign-val v
|
||||||
|
indirect-local-call
|
||||||
|
num-call-args n
|
||||||
|
|
||||||
|
# A call made in a "when" context. These always have assignment targets.
|
||||||
|
# To keep things simple, we just use one generic flavor (for N arguments,
|
||||||
|
# doing a less-streamlined-but-simpler Val-based assignment).
|
||||||
|
macro WhenCall(lhs, func)
|
||||||
|
if ( ! func )
|
||||||
|
throw ZAMDelayedCallException();
|
||||||
|
auto trigger = Z_FRAME->GetTrigger();
|
||||||
|
Val* v = trigger ? trigger->Lookup(Z_AUX->call_expr.get()) : nullptr;
|
||||||
|
ValPtr vp;
|
||||||
|
if ( v )
|
||||||
|
vp = {NewRef{}, v};
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto aux = Z_AUX;
|
||||||
|
auto current_assoc = Z_FRAME->GetTriggerAssoc();
|
||||||
|
auto n = aux->n;
|
||||||
|
std::vector<ValPtr> args;
|
||||||
|
for ( auto i = 0; i < n; ++i )
|
||||||
|
args.push_back(aux->ToVal(frame, i));
|
||||||
|
Z_FRAME->SetCall(Z_AUX->call_expr.get());
|
||||||
|
/* It's possible that this function will call another that
|
||||||
|
* itself returns null because *it* is the actual blocker.
|
||||||
|
* That will set ZAM_error, which we need to ignore.
|
||||||
|
*/
|
||||||
|
auto hold_ZAM_error = ZAM_error;
|
||||||
|
vp = func->Invoke(&args, Z_FRAME);
|
||||||
|
ZAM_error = hold_ZAM_error;
|
||||||
|
Z_FRAME->SetTriggerAssoc(current_assoc);
|
||||||
|
if ( ! vp )
|
||||||
|
throw ZAMDelayedCallException();
|
||||||
|
}
|
||||||
|
if ( Z_IS_MANAGED )
|
||||||
|
ZVal::DeleteManagedType(lhs);
|
||||||
|
lhs = ZVal(vp, Z_TYPE);
|
||||||
|
|
||||||
|
internal-op WhenCallN
|
||||||
|
class V
|
||||||
|
side-effects
|
||||||
|
eval WhenCall($$, Z_AUX_FUNC)
|
||||||
|
|
||||||
|
internal-op WhenIndCallN
|
||||||
|
class VV
|
||||||
|
op-types X F
|
||||||
|
side-effects
|
||||||
|
eval WhenCall($$, $1)
|
||||||
|
|
||||||
|
# Form for when we need to look up the function value at run-time.
|
||||||
|
internal-op When-ID-IndCallN
|
||||||
|
class V
|
||||||
|
side-effects
|
||||||
|
eval WhenCall($$, Z_AUX_ID->GetVal()->AsFunc())
|
151
src/script_opt/ZAM/OPs/coercions.op
Normal file
151
src/script_opt/ZAM/OPs/coercions.op
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# Operations corresponding to type coercions.
|
||||||
|
|
||||||
|
direct-unary-op Arith-Coerce ArithCoerce
|
||||||
|
|
||||||
|
internal-op Coerce-UI
|
||||||
|
class VV
|
||||||
|
op-types U I
|
||||||
|
eval auto v = $1;
|
||||||
|
if ( v < 0 )
|
||||||
|
ERROR("underflow converting int to count");
|
||||||
|
else
|
||||||
|
$$ = zeek_uint_t(v);
|
||||||
|
|
||||||
|
internal-op Coerce-UD
|
||||||
|
class VV
|
||||||
|
op-types U D
|
||||||
|
eval auto v = $1;
|
||||||
|
if ( v < 0.0 )
|
||||||
|
ERROR("underflow converting double to count");
|
||||||
|
else if ( v > static_cast<double>(UINT64_MAX) )
|
||||||
|
ERROR("overflow converting double to count");
|
||||||
|
else
|
||||||
|
$$ = zeek_uint_t(v);
|
||||||
|
|
||||||
|
internal-op Coerce-IU
|
||||||
|
class VV
|
||||||
|
op-types I U
|
||||||
|
eval auto v = $1;
|
||||||
|
if ( v > INT64_MAX )
|
||||||
|
ERROR("overflow converting count to int");
|
||||||
|
else
|
||||||
|
$$ = zeek_int_t(v);
|
||||||
|
|
||||||
|
internal-op Coerce-ID
|
||||||
|
class VV
|
||||||
|
op-types I D
|
||||||
|
eval auto v = $1;
|
||||||
|
if ( v < static_cast<double>(INT64_MIN) )
|
||||||
|
ERROR("underflow converting double to int");
|
||||||
|
else if ( v > static_cast<double>(INT64_MAX) )
|
||||||
|
ERROR("overflow converting double to int");
|
||||||
|
else
|
||||||
|
$$ = zeek_int_t(v);
|
||||||
|
|
||||||
|
internal-op Coerce-DI
|
||||||
|
class VV
|
||||||
|
op-types D I
|
||||||
|
eval $$ = double($1);
|
||||||
|
|
||||||
|
internal-op Coerce-DU
|
||||||
|
class VV
|
||||||
|
op-types D U
|
||||||
|
eval $$ = double($1);
|
||||||
|
|
||||||
|
|
||||||
|
macro EvalCoerceVec(lhs, rhs, coercer)
|
||||||
|
auto old_v1 = lhs.AsVector();
|
||||||
|
lhs.AsVectorRef() = coercer(rhs.AsVector(), Z_LOC);
|
||||||
|
Unref(old_v1); /* delayed to allow for same value on both sides */
|
||||||
|
|
||||||
|
internal-op Coerce-UI-Vec
|
||||||
|
class VV
|
||||||
|
eval EvalCoerceVec($$, $1, vec_coerce_UI)
|
||||||
|
|
||||||
|
internal-op Coerce-UD-Vec
|
||||||
|
class VV
|
||||||
|
eval EvalCoerceVec($$, $1, vec_coerce_UD)
|
||||||
|
|
||||||
|
internal-op Coerce-IU-Vec
|
||||||
|
class VV
|
||||||
|
eval EvalCoerceVec($$, $1, vec_coerce_IU)
|
||||||
|
|
||||||
|
internal-op Coerce-ID-Vec
|
||||||
|
class VV
|
||||||
|
eval EvalCoerceVec($$, $1, vec_coerce_ID)
|
||||||
|
|
||||||
|
internal-op Coerce-DI-Vec
|
||||||
|
class VV
|
||||||
|
eval EvalCoerceVec($$, $1, vec_coerce_DI)
|
||||||
|
|
||||||
|
internal-op Coerce-DU-Vec
|
||||||
|
class VV
|
||||||
|
eval EvalCoerceVec($$, $1, vec_coerce_DU)
|
||||||
|
|
||||||
|
|
||||||
|
direct-unary-op Record-Coerce RecordCoerce
|
||||||
|
|
||||||
|
internal-op Record-Coerce
|
||||||
|
class VV
|
||||||
|
op-types R R
|
||||||
|
eval auto rt = cast_intrusive<RecordType>(Z_TYPE);
|
||||||
|
auto v = $1;
|
||||||
|
auto to_r = coerce_to_record(std::move(rt), v, Z_AUX_MAP);
|
||||||
|
Unref($$);
|
||||||
|
$$ = to_r.release();
|
||||||
|
|
||||||
|
direct-unary-op Table-Coerce TableCoerce
|
||||||
|
|
||||||
|
internal-op Table-Coerce
|
||||||
|
class VV
|
||||||
|
op-types T T
|
||||||
|
eval auto tv = $1;
|
||||||
|
if ( tv->Size() > 0 )
|
||||||
|
ERROR("coercion of non-empty table/set");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tt = cast_intrusive<TableType>(Z_TYPE);
|
||||||
|
AttributesPtr attrs = tv->GetAttrs();
|
||||||
|
auto t = make_intrusive<TableVal>(tt, attrs);
|
||||||
|
Unref($$);
|
||||||
|
$$ = t.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
direct-unary-op Vector-Coerce VectorCoerce
|
||||||
|
|
||||||
|
internal-op Vector-Coerce
|
||||||
|
class VV
|
||||||
|
op-types V V
|
||||||
|
eval if ( $1->Size() > 0 )
|
||||||
|
ERROR("coercion of non-empty vector");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto vv = new VectorVal(cast_intrusive<VectorType>(Z_TYPE));
|
||||||
|
Unref($$);
|
||||||
|
$$ = vv;
|
||||||
|
}
|
||||||
|
|
||||||
|
unary-expr-op To-Any-Coerce
|
||||||
|
op-type X
|
||||||
|
set-type $1
|
||||||
|
eval AssignTarget($$, ZVal($1.ToVal(Z_TYPE), ZAM::any_base_type))
|
||||||
|
|
||||||
|
unary-expr-op From-Any-Coerce
|
||||||
|
no-const
|
||||||
|
op-type X
|
||||||
|
set-type $$
|
||||||
|
eval auto v = $1.AsAny();
|
||||||
|
AssignTarget($$, ZVal({NewRef{}, v}, Z_TYPE))
|
||||||
|
|
||||||
|
unary-expr-op From-Any-Vec-Coerce
|
||||||
|
no-const
|
||||||
|
op-type X
|
||||||
|
set-type $$
|
||||||
|
eval auto vv = $1.AsVector();
|
||||||
|
if ( ! vv->Concretize(Z_TYPE->Yield()) )
|
||||||
|
ERROR("incompatible vector-of-any");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zeek::Ref(vv);
|
||||||
|
AssignTarget($$, ZVal(vv))
|
||||||
|
}
|
251
src/script_opt/ZAM/OPs/constructors.op
Normal file
251
src/script_opt/ZAM/OPs/constructors.op
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
# Operations corresponding to aggregated constructors.
|
||||||
|
|
||||||
|
# Table construction requires atypical evaluation of list elements
|
||||||
|
# using information from their expression specifics.
|
||||||
|
direct-unary-op Table-Constructor ConstructTable
|
||||||
|
|
||||||
|
macro ConstructTableOrSetPre(width)
|
||||||
|
auto tt = cast_intrusive<TableType>(Z_TYPE);
|
||||||
|
auto new_t = new TableVal(tt, Z_AUX_ATTRS);
|
||||||
|
auto aux = Z_AUX;
|
||||||
|
auto n = aux->n;
|
||||||
|
auto ind_width = width;
|
||||||
|
|
||||||
|
macro ConstructTableOrSetPost(lhs)
|
||||||
|
auto& t = lhs.AsTableRef();
|
||||||
|
Unref(t);
|
||||||
|
t = new_t;
|
||||||
|
|
||||||
|
internal-op Construct-Table
|
||||||
|
class Vi
|
||||||
|
eval ConstructTableOrSetPre($1)
|
||||||
|
for ( auto i = 0; i < n; ++i )
|
||||||
|
{
|
||||||
|
auto indices = aux->ToIndices(frame, i, ind_width);
|
||||||
|
auto v = aux->ToVal(frame, i + ind_width);
|
||||||
|
new_t->Assign(indices, v);
|
||||||
|
i += ind_width;
|
||||||
|
}
|
||||||
|
ConstructTableOrSetPost($$)
|
||||||
|
|
||||||
|
# When tables are constructed, if their &default is a lambda with captures
|
||||||
|
# then we need to explicitly set up the default.
|
||||||
|
internal-op Set-Table-Default-Lambda
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
op-types T X
|
||||||
|
eval auto tbl = $1;
|
||||||
|
auto lambda = $2.ToVal(Z_TYPE);
|
||||||
|
tbl->InitDefaultVal(std::move(lambda));
|
||||||
|
|
||||||
|
direct-unary-op Set-Constructor ConstructSet
|
||||||
|
|
||||||
|
internal-op Construct-Set
|
||||||
|
class Vi
|
||||||
|
eval ConstructTableOrSetPre($1)
|
||||||
|
for ( auto i = 0; i < n; i += ind_width )
|
||||||
|
{
|
||||||
|
auto indices = aux->ToIndices(frame, i, ind_width);
|
||||||
|
new_t->Assign(indices, nullptr);
|
||||||
|
}
|
||||||
|
ConstructTableOrSetPost($$)
|
||||||
|
|
||||||
|
direct-unary-op Record-Constructor ConstructRecord
|
||||||
|
|
||||||
|
direct-unary-op Rec-Construct-With-Rec ConstructRecordFromRecord
|
||||||
|
|
||||||
|
macro ConstructRecordPost(lhs)
|
||||||
|
auto& r = lhs.AsRecordRef();
|
||||||
|
Unref(r);
|
||||||
|
r = new RecordVal(cast_intrusive<RecordType>(Z_TYPE), std::move(init_vals));
|
||||||
|
|
||||||
|
op Construct-Direct-Record
|
||||||
|
class V
|
||||||
|
eval auto init_vals = Z_AUX->ToZValVec(frame);
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
op Construct-Known-Record
|
||||||
|
class V
|
||||||
|
eval auto init_vals = Z_AUX->ToZValVecWithMap(frame);
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
macro AssignFromRec(lhs_full, rhs_full)
|
||||||
|
/* The following is defined below, for use by Rec-Assign-Fields */
|
||||||
|
SetUpRecFieldOps(lhs_full, rhs_full, lhs_map)
|
||||||
|
auto is_managed = Z_AUX->is_managed;
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
{
|
||||||
|
auto rhs_i = rhs->RawField(rhs_map[i]);
|
||||||
|
if ( is_managed[i] )
|
||||||
|
zeek::Ref(rhs_i.ManagedVal());
|
||||||
|
init_vals[lhs_map[i]] = rhs_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
op Construct-Known-Record-From
|
||||||
|
class VV
|
||||||
|
eval auto init_vals = Z_AUX->ToZValVecWithMap(frame);
|
||||||
|
AssignFromRec($$, $1)
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
macro DoNetworkTimeInit(slot)
|
||||||
|
init_vals[slot] = ZVal(run_state::network_time);
|
||||||
|
|
||||||
|
op Construct-Known-Record-With-NT
|
||||||
|
class Vi
|
||||||
|
eval auto init_vals = Z_AUX->ToZValVecWithMap(frame);
|
||||||
|
DoNetworkTimeInit($1)
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
op Construct-Known-Record-With-NT-From
|
||||||
|
class VVi
|
||||||
|
eval auto init_vals = Z_AUX->ToZValVecWithMap(frame);
|
||||||
|
DoNetworkTimeInit($2)
|
||||||
|
AssignFromRec($$, $1)
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
macro GenInits()
|
||||||
|
auto init_vals = Z_AUX->ToZValVecWithMap(frame);
|
||||||
|
for ( auto& fi : *z.aux->field_inits )
|
||||||
|
init_vals[fi.first] = fi.second->Generate();
|
||||||
|
|
||||||
|
op Construct-Known-Record-With-Inits
|
||||||
|
class V
|
||||||
|
eval GenInits()
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
op Construct-Known-Record-With-Inits-From
|
||||||
|
class VV
|
||||||
|
eval GenInits()
|
||||||
|
AssignFromRec($$, $1)
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
op Construct-Known-Record-With-Inits-And-NT
|
||||||
|
class Vi
|
||||||
|
eval GenInits()
|
||||||
|
DoNetworkTimeInit($1)
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
op Construct-Known-Record-With-Inits-And-NT-From
|
||||||
|
class VVi
|
||||||
|
eval GenInits()
|
||||||
|
DoNetworkTimeInit($2)
|
||||||
|
AssignFromRec($$, $1)
|
||||||
|
ConstructRecordPost($$)
|
||||||
|
|
||||||
|
macro SetUpRecFieldOps(lhs_full, rhs_full, which_lhs_map)
|
||||||
|
auto lhs = lhs_full.record_val;
|
||||||
|
auto rhs = rhs_full.record_val;
|
||||||
|
auto& lhs_map = Z_AUX->which_lhs_map;
|
||||||
|
auto& rhs_map = Z_AUX->rhs_map;
|
||||||
|
auto n = rhs_map.size();
|
||||||
|
|
||||||
|
op Rec-Assign-Fields
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
eval SetUpRecFieldOps($1, $2, map)
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
lhs->RawOptField(lhs_map[i]) = rhs->RawField(rhs_map[i]);
|
||||||
|
|
||||||
|
macro DoManagedRecAssign()
|
||||||
|
auto is_managed = Z_AUX->is_managed;
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
if ( is_managed[i] )
|
||||||
|
{
|
||||||
|
auto& lhs_i = lhs->RawOptField(lhs_map[i]);
|
||||||
|
auto rhs_i = rhs->RawField(rhs_map[i]);
|
||||||
|
zeek::Ref(rhs_i.ManagedVal());
|
||||||
|
if ( lhs_i )
|
||||||
|
ZVal::DeleteManagedType(*lhs_i);
|
||||||
|
lhs_i = rhs_i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lhs->RawOptField(lhs_map[i]) = rhs->RawField(rhs_map[i]);
|
||||||
|
|
||||||
|
op Rec-Assign-Fields-Managed
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
eval SetUpRecFieldOps($1, $2, map)
|
||||||
|
DoManagedRecAssign()
|
||||||
|
|
||||||
|
op Rec-Assign-Fields-All-Managed
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
eval SetUpRecFieldOps($1, $2, map)
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
{
|
||||||
|
auto& lhs_i = lhs->RawOptField(lhs_map[i]);
|
||||||
|
auto rhs_i = rhs->RawField(rhs_map[i]);
|
||||||
|
zeek::Ref(rhs_i.ManagedVal());
|
||||||
|
if ( lhs_i )
|
||||||
|
ZVal::DeleteManagedType(*lhs_i);
|
||||||
|
lhs_i = rhs_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
op Rec-Add-Int-Fields
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
eval SetUpRecFieldOps($1, $2, map)
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
lhs->RawField(lhs_map[i]).int_val += rhs->RawField(rhs_map[i]).int_val;
|
||||||
|
|
||||||
|
op Rec-Add-Double-Fields
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
eval SetUpRecFieldOps($1, $2, map)
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
lhs->RawField(lhs_map[i]).double_val += rhs->RawField(rhs_map[i]).double_val;
|
||||||
|
|
||||||
|
op Rec-Add-Fields
|
||||||
|
op1-read
|
||||||
|
class VV
|
||||||
|
eval SetUpRecFieldOps($1, $2, map)
|
||||||
|
auto& types = Z_AUX->types;
|
||||||
|
for ( size_t i = 0U; i < n; ++i )
|
||||||
|
{
|
||||||
|
auto& lhs_i = lhs->RawField(lhs_map[i]);
|
||||||
|
auto rhs_i = rhs->RawField(rhs_map[i]);
|
||||||
|
auto tag = types[i]->Tag();
|
||||||
|
if ( tag == TYPE_INT )
|
||||||
|
lhs_i.int_val += rhs_i.int_val;
|
||||||
|
else if ( tag == TYPE_COUNT )
|
||||||
|
lhs_i.uint_val += rhs_i.uint_val;
|
||||||
|
else
|
||||||
|
lhs_i.double_val += rhs_i.double_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Special instruction for concretizing vectors that are fields in a
|
||||||
|
# newly-constructed record. "aux" holds which fields in the record to
|
||||||
|
# inspect.
|
||||||
|
op Concretize-Vector-Fields
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types R
|
||||||
|
eval auto rt = cast_intrusive<RecordType>(Z_TYPE);
|
||||||
|
auto r = $1;
|
||||||
|
auto aux = Z_AUX;
|
||||||
|
auto n = aux->n;
|
||||||
|
for ( auto i = 0; i < n; ++i )
|
||||||
|
{
|
||||||
|
auto ind = aux->elems[i].IntVal();
|
||||||
|
auto v_i = r->GetField(ind);
|
||||||
|
ASSERT(v_i);
|
||||||
|
if ( v_i->GetType<VectorType>()->IsUnspecifiedVector() )
|
||||||
|
{
|
||||||
|
const auto& t_i = rt->GetFieldType(ind);
|
||||||
|
v_i->AsVectorVal()->Concretize(t_i->Yield());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
direct-unary-op Vector-Constructor ConstructVector
|
||||||
|
|
||||||
|
internal-op Construct-Vector
|
||||||
|
class V
|
||||||
|
op-types V
|
||||||
|
eval auto new_vv = new VectorVal(cast_intrusive<VectorType>(Z_TYPE));
|
||||||
|
auto aux = Z_AUX;
|
||||||
|
auto n = aux->n;
|
||||||
|
for ( auto i = 0; i < n; ++i )
|
||||||
|
new_vv->Assign(i, aux->ToVal(frame, i));
|
||||||
|
auto& vv = $$;
|
||||||
|
Unref(vv);
|
||||||
|
vv = new_vv;
|
212
src/script_opt/ZAM/OPs/indexing.op
Normal file
212
src/script_opt/ZAM/OPs/indexing.op
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
# Operations corresponding to indexing of tables, vectors, strings,
|
||||||
|
# and "any" values.
|
||||||
|
|
||||||
|
op IndexVecBoolSelect
|
||||||
|
classes VVV VCV
|
||||||
|
op-types V V V
|
||||||
|
set-type $$
|
||||||
|
eval if ( $1->Size() != $2->Size() )
|
||||||
|
ERROR("size mismatch, boolean index and vector");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto vt = cast_intrusive<VectorType>(Z_TYPE);
|
||||||
|
auto v2 = $1;
|
||||||
|
auto v3 = $2;
|
||||||
|
auto v = vector_bool_select(std::move(vt), v2, v3);
|
||||||
|
Unref($$);
|
||||||
|
$$ = v.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
op IndexVecIntSelect
|
||||||
|
classes VVV VCV
|
||||||
|
op-types V V V
|
||||||
|
set-type $$
|
||||||
|
eval auto vt = cast_intrusive<VectorType>(Z_TYPE);
|
||||||
|
auto v2 = $1;
|
||||||
|
auto v3 = $2;
|
||||||
|
auto v = vector_int_select(std::move(vt), v2, v3);
|
||||||
|
Unref($$);
|
||||||
|
$$ = v.release();
|
||||||
|
|
||||||
|
op Index
|
||||||
|
class VVL
|
||||||
|
custom-method return CompileIndex(n1, n2, l, false);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
op Index
|
||||||
|
class VCL
|
||||||
|
custom-method return CompileIndex(n, c, l, false);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
op WhenIndex
|
||||||
|
class VVL
|
||||||
|
custom-method return CompileIndex(n1, n2, l, true);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
op WhenIndex
|
||||||
|
class VCL
|
||||||
|
custom-method return CompileIndex(n, c, l, true);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
internal-op Index-Vec
|
||||||
|
class VVV
|
||||||
|
op-types X V I
|
||||||
|
eval EvalIndexVec($$, $1, $2)
|
||||||
|
|
||||||
|
macro EvalIndexVec(lhs, rhs_vec, index)
|
||||||
|
auto& vv = rhs_vec->RawVec();
|
||||||
|
zeek_int_t ind = index;
|
||||||
|
if ( ind < 0 )
|
||||||
|
ind += vv.size();
|
||||||
|
if ( ind < 0 || ind >= int(vv.size()) )
|
||||||
|
ERROR("no such index");
|
||||||
|
AssignTarget(lhs, CopyVal(*(vv[ind])))
|
||||||
|
|
||||||
|
internal-op Index-VecC
|
||||||
|
class VVi
|
||||||
|
op-types X V I
|
||||||
|
eval EvalIndexVec($$, $1, $2)
|
||||||
|
|
||||||
|
internal-op Index-Any-Vec
|
||||||
|
class VVV
|
||||||
|
op-types X V I
|
||||||
|
eval EvalIndexAnyVec($$, $1, $2)
|
||||||
|
|
||||||
|
macro EvalIndexAnyVec(lhs, vec, index)
|
||||||
|
auto vv = vec;
|
||||||
|
zeek_int_t ind = index;
|
||||||
|
if ( ind < 0 )
|
||||||
|
ind += vv->Size();
|
||||||
|
if ( ind < 0 || ind >= int(vv->Size()) )
|
||||||
|
ERROR("no such index");
|
||||||
|
AssignTarget(lhs, ZVal(vv->ValAt(ind).release()))
|
||||||
|
|
||||||
|
internal-op Index-Any-VecC
|
||||||
|
class VVi
|
||||||
|
op-types X V I
|
||||||
|
eval EvalIndexAnyVec($$, $1, $2)
|
||||||
|
|
||||||
|
macro WhenIndexResCheck(vec)
|
||||||
|
if ( vec && IndexExprWhen::evaluating > 0 )
|
||||||
|
IndexExprWhen::results.push_back({NewRef{}, vec});
|
||||||
|
|
||||||
|
internal-op When-Index-Vec
|
||||||
|
class VVV
|
||||||
|
op-types X V I
|
||||||
|
eval EvalIndexAnyVec($$, $1, $2)
|
||||||
|
WhenIndexResCheck($$.AsVector())
|
||||||
|
|
||||||
|
internal-op When-Index-VecC
|
||||||
|
class VVi
|
||||||
|
op-types X V I
|
||||||
|
eval EvalIndexAnyVec($$, $1, $2)
|
||||||
|
WhenIndexResCheck($$.AsVector())
|
||||||
|
|
||||||
|
macro EvalVecSlice(lhs, vv)
|
||||||
|
auto vec = vv;
|
||||||
|
auto v = index_slice(vec, indices.get());
|
||||||
|
Unref(lhs);
|
||||||
|
lhs = v.release();
|
||||||
|
|
||||||
|
internal-op Index-Vec-Slice
|
||||||
|
class VV
|
||||||
|
op-types V V
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
EvalVecSlice($$, $1)
|
||||||
|
|
||||||
|
internal-op When-Index-Vec-Slice
|
||||||
|
class VV
|
||||||
|
op-types V V
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
EvalVecSlice($$, $1)
|
||||||
|
WhenIndexResCheck($$)
|
||||||
|
|
||||||
|
internal-op Table-Index
|
||||||
|
class VV
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
EvalTableIndex($1, indices)
|
||||||
|
if ( v )
|
||||||
|
AssignTarget($$, BuildVal(v, Z_TYPE))
|
||||||
|
|
||||||
|
internal-op Table-PatStr-Index
|
||||||
|
classes VVV VVC
|
||||||
|
op-types X T S
|
||||||
|
eval auto vec = ZVal($1->LookupPattern({NewRef{}, $2}));
|
||||||
|
ZVal::DeleteManagedType($$);
|
||||||
|
$$ = vec;
|
||||||
|
|
||||||
|
internal-op When-Table-Index
|
||||||
|
class VV
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
EvalTableIndex($1, indices)
|
||||||
|
if ( v )
|
||||||
|
{
|
||||||
|
if ( IndexExprWhen::evaluating > 0 )
|
||||||
|
IndexExprWhen::results.emplace_back(v);
|
||||||
|
AssignTarget($$, BuildVal(v, Z_TYPE))
|
||||||
|
}
|
||||||
|
|
||||||
|
macro EvalTableIndex(tbl, index)
|
||||||
|
auto v = tbl.AsTable()->FindOrDefault(index);
|
||||||
|
if ( ! v )
|
||||||
|
ERROR("no such index");
|
||||||
|
|
||||||
|
internal-op When-PatStr-Index
|
||||||
|
class VV
|
||||||
|
op-types X T
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
auto arg0 = indices->Idx(0);
|
||||||
|
auto v = $1->LookupPattern({NewRef{}, arg0->AsStringVal()});
|
||||||
|
if ( IndexExprWhen::evaluating > 0 )
|
||||||
|
IndexExprWhen::results.emplace_back(v);
|
||||||
|
AssignTarget($$, BuildVal(v, Z_TYPE))
|
||||||
|
|
||||||
|
internal-assignment-op Table-Index1
|
||||||
|
classes VVV VVC
|
||||||
|
assign-val v
|
||||||
|
eval EvalTableIndex($1, $2.ToVal(Z_TYPE))
|
||||||
|
# No AssignTarget needed, as this is an assignment-op
|
||||||
|
|
||||||
|
# This version is for a variable v3.
|
||||||
|
internal-op Index-String
|
||||||
|
class VVV
|
||||||
|
op-types S S I
|
||||||
|
eval EvalIndexString($$, $1, $2)
|
||||||
|
|
||||||
|
macro EvalIndexString(lhs, s, index)
|
||||||
|
auto str = s->AsString();
|
||||||
|
auto len = str->Len();
|
||||||
|
auto idx = index;
|
||||||
|
if ( idx < 0 )
|
||||||
|
idx += len;
|
||||||
|
auto v = str->GetSubstring(idx, 1);
|
||||||
|
Unref(lhs);
|
||||||
|
lhs = new StringVal(v ? v : new String(""));
|
||||||
|
|
||||||
|
# This version is for a constant v3.
|
||||||
|
internal-op Index-StringC
|
||||||
|
class VVi
|
||||||
|
op-types S S I
|
||||||
|
eval EvalIndexString($$, $1, $2)
|
||||||
|
|
||||||
|
internal-op Index-String-Slice
|
||||||
|
class VV
|
||||||
|
op-types S S
|
||||||
|
eval auto str = $1->AsString();
|
||||||
|
auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
auto slice = index_string(str, indices.get());
|
||||||
|
Unref($$);
|
||||||
|
$$ = new StringVal(slice->ToStdString());
|
||||||
|
|
||||||
|
op AnyIndex
|
||||||
|
class VVi
|
||||||
|
op-types X a I
|
||||||
|
set-type $$
|
||||||
|
eval auto lv = $1->AsListVal();
|
||||||
|
if ( $2 < 0 || $2 >= lv->Length() )
|
||||||
|
reporter->InternalError("bad \"any\" element index");
|
||||||
|
ValPtr elem = lv->Idx($2);
|
||||||
|
if ( CheckAnyType(elem->GetType(), Z_TYPE, Z_LOC) )
|
||||||
|
AssignTarget($$, BuildVal(elem, Z_TYPE))
|
||||||
|
else
|
||||||
|
ZAM_error = true;
|
124
src/script_opt/ZAM/OPs/internal.op
Normal file
124
src/script_opt/ZAM/OPs/internal.op
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# Internal operations not directly driven off of AST elements.
|
||||||
|
|
||||||
|
# These two are only needed for type-based switch statements. Could think
|
||||||
|
# about replacing them using CoerceFromAnyExpr.
|
||||||
|
op Assign-Any
|
||||||
|
classes VV VC
|
||||||
|
set-type $1
|
||||||
|
op-types a X
|
||||||
|
eval auto v = $1.ToVal(Z_TYPE);
|
||||||
|
$$ = v.release();
|
||||||
|
|
||||||
|
# Lazy way to assign without having to track the specific type of
|
||||||
|
# a constant.
|
||||||
|
internal-op Assign-Const
|
||||||
|
class VC
|
||||||
|
eval AssignTarget($$, BuildVal($1.ToVal(Z_TYPE), Z_TYPE))
|
||||||
|
|
||||||
|
internal-assignment-op Load-Val
|
||||||
|
class Vi
|
||||||
|
assign-val v
|
||||||
|
eval auto& v = Z_FRAME->GetElement($1);
|
||||||
|
|
||||||
|
internal-assignment-op Load-Global
|
||||||
|
# We don't use GlobalVal() for the assignment because we want to leverage
|
||||||
|
# the bookkeeping that assign-val gives us in terms of memory management.
|
||||||
|
class Vg
|
||||||
|
assign-val v
|
||||||
|
eval auto& v = GlobalID($1)->GetVal();
|
||||||
|
if ( ! v )
|
||||||
|
ERROR2("value used but not set", Z_AUX_ID.get());
|
||||||
|
|
||||||
|
# We need a special form here for loading global types, as they don't
|
||||||
|
# fit the usual template.
|
||||||
|
internal-op Load-Global-Type
|
||||||
|
class Vg
|
||||||
|
op-types t I
|
||||||
|
eval auto& v = $$;
|
||||||
|
Unref(v);
|
||||||
|
auto& t = GlobalID($1)->GetType();
|
||||||
|
v = new TypeVal(t, true);
|
||||||
|
|
||||||
|
internal-op Load-Capture
|
||||||
|
class Vi
|
||||||
|
eval $$ = Z_FRAME->GetFunction()->GetCapturesVec()[$1];
|
||||||
|
|
||||||
|
internal-op Load-Managed-Capture
|
||||||
|
class Vi
|
||||||
|
eval auto& lhs = $$;
|
||||||
|
auto& rhs = Z_FRAME->GetFunction()->GetCapturesVec()[$1];
|
||||||
|
zeek::Ref(rhs.ManagedVal());
|
||||||
|
ZVal::DeleteManagedType(lhs);
|
||||||
|
lhs = rhs;
|
||||||
|
|
||||||
|
internal-op Store-Global
|
||||||
|
op1-internal
|
||||||
|
class g
|
||||||
|
eval GlobalID($1)->SetVal(GlobalVal($1).ToVal(Z_TYPE));
|
||||||
|
|
||||||
|
# Both of these have the LHS as v2 not v1, to keep with existing
|
||||||
|
# conventions of OP_VV_I2 op type (as opposed to OP_VV_I1_V2, which doesn't
|
||||||
|
# currently exist, and would be a pain to add).
|
||||||
|
internal-op Store-Capture
|
||||||
|
op1-read
|
||||||
|
class Vi
|
||||||
|
eval Z_FRAME->GetFunction()->GetCapturesVec()[$2] = $1;
|
||||||
|
|
||||||
|
internal-op Store-Managed-Capture
|
||||||
|
op1-read
|
||||||
|
class Vi
|
||||||
|
eval auto& lhs = Z_FRAME->GetFunction()->GetCapturesVec()[$2];
|
||||||
|
auto& rhs = $1;
|
||||||
|
zeek::Ref(rhs.ManagedVal());
|
||||||
|
ZVal::DeleteManagedType(lhs);
|
||||||
|
lhs = rhs;
|
||||||
|
|
||||||
|
|
||||||
|
internal-op Copy-To
|
||||||
|
class VC
|
||||||
|
set-type $1
|
||||||
|
eval AssignTarget($$, CopyVal($1))
|
||||||
|
|
||||||
|
internal-op GoTo
|
||||||
|
class b
|
||||||
|
eval $1
|
||||||
|
|
||||||
|
internal-op Hook-Break
|
||||||
|
class X
|
||||||
|
eval flow = FLOW_BREAK;
|
||||||
|
pc = end_pc;
|
||||||
|
DO_ZAM_PROFILE
|
||||||
|
continue;
|
||||||
|
|
||||||
|
# Slot 2 gives frame size.
|
||||||
|
internal-op Lambda
|
||||||
|
class Vi
|
||||||
|
op-types F I
|
||||||
|
eval auto& primary_func = Z_AUX_PRIMARY_FUNC;
|
||||||
|
auto& body = primary_func->GetBodies()[0].stmts;
|
||||||
|
ASSERT(body->Tag() == STMT_ZAM);
|
||||||
|
auto lamb = make_intrusive<ScriptFunc>(Z_AUX_ID);
|
||||||
|
lamb->AddBody(body, $1);
|
||||||
|
lamb->SetName(Z_AUX_LAMBDA_NAME.c_str());
|
||||||
|
auto& aux = Z_AUX;
|
||||||
|
if ( aux->n > 0 )
|
||||||
|
{
|
||||||
|
auto captures = std::make_unique<std::vector<ZVal>>();
|
||||||
|
for ( auto i = 0; i < aux->n; ++i )
|
||||||
|
{
|
||||||
|
auto slot = aux->elems[i].Slot();
|
||||||
|
if ( slot >= 0 )
|
||||||
|
{
|
||||||
|
auto& cp = frame[slot];
|
||||||
|
if ( aux->elems[i].IsManaged() )
|
||||||
|
zeek::Ref(cp.ManagedVal());
|
||||||
|
captures->push_back(cp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Used for when-locals. */
|
||||||
|
captures->push_back(ZVal());
|
||||||
|
}
|
||||||
|
lamb->CreateCaptures(std::move(captures));
|
||||||
|
}
|
||||||
|
Unref($$);
|
||||||
|
$$ = lamb.release();
|
124
src/script_opt/ZAM/OPs/iterations.op
Normal file
124
src/script_opt/ZAM/OPs/iterations.op
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# Operations corresponding to iterations.
|
||||||
|
|
||||||
|
internal-op Init-Table-Loop
|
||||||
|
op1-read
|
||||||
|
class Vf
|
||||||
|
op-types T I
|
||||||
|
eval $2.BeginLoop({NewRef{}, $1}, frame, Z_AUX);
|
||||||
|
|
||||||
|
internal-op Next-Table-Iter
|
||||||
|
op1-read
|
||||||
|
class fb
|
||||||
|
eval NextTableIterPre($1, $2)
|
||||||
|
$1.NextIter();
|
||||||
|
|
||||||
|
macro NextTableIterPre(iter, BRANCH)
|
||||||
|
if ( iter.IsDoneIterating() )
|
||||||
|
BRANCH
|
||||||
|
|
||||||
|
internal-op Next-Table-Iter-No-Vars
|
||||||
|
op1-read
|
||||||
|
class fb
|
||||||
|
eval NextTableIterPre($1, $2)
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
internal-op Next-Table-Iter-Val-Var
|
||||||
|
# v1 = slot of the "ValueVar"
|
||||||
|
class Vfb
|
||||||
|
eval NextTableIterPre($1, $2)
|
||||||
|
AssignTarget($$, $1.IterValue());
|
||||||
|
$1.NextIter();
|
||||||
|
|
||||||
|
internal-op Next-Table-Iter-Val-Var-No-Vars
|
||||||
|
# v1 = slot of the "ValueVar"
|
||||||
|
class Vfb
|
||||||
|
eval NextTableIterPre($1, $2)
|
||||||
|
AssignTarget($$, $1.IterValue());
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
|
||||||
|
internal-op Init-Vector-Loop
|
||||||
|
op1-read
|
||||||
|
class Vs
|
||||||
|
op-types V I
|
||||||
|
eval auto& vv = $1->RawVec();
|
||||||
|
$2.InitLoop(&vv);
|
||||||
|
|
||||||
|
macro NextVectorIterCore(info, BRANCH)
|
||||||
|
if ( info.IsDoneIterating() )
|
||||||
|
BRANCH
|
||||||
|
const auto& vv = *info.vv;
|
||||||
|
if ( ! vv[info.iter] )
|
||||||
|
{ /* Account for vector hole. Re-execute for next position. */
|
||||||
|
info.IterFinished();
|
||||||
|
REDO
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Next-Vector-Iter
|
||||||
|
# v1 = iteration variable
|
||||||
|
class Vsb
|
||||||
|
op-types U I I
|
||||||
|
eval NextVectorIterCore($1, $2)
|
||||||
|
$$ = $1.iter;
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
internal-op Next-Vector-Blank-Iter
|
||||||
|
op1-internal
|
||||||
|
class sb
|
||||||
|
eval NextVectorIterCore($1, $2)
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
internal-op Next-Vector-Iter-Val-Var
|
||||||
|
# v1 = iteration variable
|
||||||
|
# v2 = value variable
|
||||||
|
op1-read-write
|
||||||
|
class VVsb
|
||||||
|
op-types U X I I
|
||||||
|
eval NextVectorIterCore($2, $3)
|
||||||
|
$$ = $2.iter;
|
||||||
|
if ( Z_IS_MANAGED )
|
||||||
|
$1 = BuildVal(vv[$2.iter]->ToVal(Z_TYPE), Z_TYPE);
|
||||||
|
else
|
||||||
|
$1 = *vv[$2.iter];
|
||||||
|
$2.IterFinished();
|
||||||
|
|
||||||
|
internal-op Next-Vector-Blank-Iter-Val-Var
|
||||||
|
# v1 = value variable
|
||||||
|
class Vsb
|
||||||
|
eval NextVectorIterCore($1, $2)
|
||||||
|
if ( Z_IS_MANAGED )
|
||||||
|
$$ = BuildVal(vv[$1.iter]->ToVal(Z_TYPE), Z_TYPE);
|
||||||
|
else
|
||||||
|
$$ = *vv[$1.iter];
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
|
||||||
|
internal-op Init-String-Loop
|
||||||
|
op1-read
|
||||||
|
classes Vs Cs
|
||||||
|
op-types S I
|
||||||
|
eval $2.InitLoop($1->AsString());
|
||||||
|
|
||||||
|
internal-op Next-String-Iter
|
||||||
|
# v1 = iteration variable
|
||||||
|
class Vsb
|
||||||
|
op-types S I I
|
||||||
|
eval if ( $1.IsDoneIterating() )
|
||||||
|
$2
|
||||||
|
auto bytes = (const char*) $1.s->Bytes() + $1.iter;
|
||||||
|
auto sv = new StringVal(1, bytes);
|
||||||
|
Unref($$);
|
||||||
|
$$ = sv;
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
internal-op Next-String-Blank-Iter
|
||||||
|
op1-internal
|
||||||
|
class sb
|
||||||
|
eval if ( $1.IsDoneIterating() )
|
||||||
|
$2
|
||||||
|
$1.IterFinished();
|
||||||
|
|
||||||
|
internal-op End-Table-Loop
|
||||||
|
op1-internal
|
||||||
|
class f
|
||||||
|
eval $1.Clear();
|
74
src/script_opt/ZAM/OPs/macros.op
Normal file
74
src/script_opt/ZAM/OPs/macros.op
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# General-purpose macros. Those that are specific to a group of instructions
|
||||||
|
# are defined with those templates rather than appearing here.
|
||||||
|
|
||||||
|
# Macros for information associated with the current instruction.
|
||||||
|
|
||||||
|
# The Val frame used to pass in arguments.
|
||||||
|
macro Z_FRAME f
|
||||||
|
|
||||||
|
# The main type.
|
||||||
|
macro Z_TYPE z.GetType()
|
||||||
|
|
||||||
|
# Whether it's managed.
|
||||||
|
macro Z_IS_MANAGED *(z.is_managed)
|
||||||
|
|
||||||
|
# Secondary type.
|
||||||
|
macro Z_TYPE2 z.GetType2()
|
||||||
|
|
||||||
|
# Auxiliary information.
|
||||||
|
macro Z_AUX z.aux
|
||||||
|
macro Z_AUX_ID z.aux->id_val
|
||||||
|
macro Z_AUX_FUNC z.aux->func
|
||||||
|
macro Z_AUX_MAP z.aux->map
|
||||||
|
macro Z_AUX_ATTRS z.aux->attrs
|
||||||
|
macro Z_AUX_WHEN_INFO z.aux->wi
|
||||||
|
macro Z_AUX_EVENT_HANDLER z.aux->event_handler
|
||||||
|
macro Z_AUX_PRIMARY_FUNC z.aux->lambda->PrimaryFunc()
|
||||||
|
macro Z_AUX_LAMBDA_NAME z.aux->lambda->Name()
|
||||||
|
|
||||||
|
# Location in the original script.
|
||||||
|
macro Z_LOC z.loc
|
||||||
|
|
||||||
|
macro SET_RET_TYPE(type) ret_type = type;
|
||||||
|
|
||||||
|
macro INDEX_LIST zam_index_val_list
|
||||||
|
|
||||||
|
macro ERROR(msg) ZAM_run_time_error(Z_LOC, msg)
|
||||||
|
macro ERROR2(msg, obj) ZAM_run_time_error(Z_LOC, msg, obj)
|
||||||
|
|
||||||
|
macro WARN(msg) ZAM_run_time_warning(Z_LOC, msg)
|
||||||
|
|
||||||
|
# The following abstracts the process of creating a frame-assignable value.
|
||||||
|
macro BuildVal(v, t) ZVal(v, t)
|
||||||
|
|
||||||
|
# Returns a memory-managed-if-necessary copy of an existing value.
|
||||||
|
macro CopyVal(v) (Z_IS_MANAGED ? BuildVal((v).ToVal(Z_TYPE), Z_TYPE) : (v))
|
||||||
|
|
||||||
|
# Managed assignments to the given target.
|
||||||
|
macro AssignTarget(target, v) {
|
||||||
|
if ( Z_IS_MANAGED )
|
||||||
|
{
|
||||||
|
/* It's important to hold a reference to v here prior
|
||||||
|
to the deletion in case target points to v. */
|
||||||
|
auto v2 = v;
|
||||||
|
ZVal::DeleteManagedType(target);
|
||||||
|
target = v2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
target = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro Branch(target) { DO_ZAM_PROFILE; pc = target; continue; }
|
||||||
|
|
||||||
|
macro REDO { --pc; /* so we then increment to here again */ break; }
|
||||||
|
|
||||||
|
macro GlobalID(g) globals[g].id
|
||||||
|
macro GlobalVal(g) frame[globals[g].slot]
|
||||||
|
|
||||||
|
macro StepIter(slot) step_iters[slot]
|
||||||
|
macro TableIter(slot) (*tiv_ptr)[slot]
|
||||||
|
|
||||||
|
macro DirectField(r, f) r->RawField(f)
|
||||||
|
macro DirectOptField(r, f) r->RawOptField(f)
|
||||||
|
|
||||||
|
macro LogEnum(v) v.ToVal(ZAM::log_ID_enum_type)
|
267
src/script_opt/ZAM/OPs/non-uniform.op
Normal file
267
src/script_opt/ZAM/OPs/non-uniform.op
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
# Operations corresponding to non-uniform expressions.
|
||||||
|
|
||||||
|
assign-op Field
|
||||||
|
class R
|
||||||
|
field-op
|
||||||
|
assign-val v
|
||||||
|
eval auto r = $1.AsRecord();
|
||||||
|
auto& rv = DirectOptField(r, $2);
|
||||||
|
ZVal v;
|
||||||
|
if ( ! rv )
|
||||||
|
{
|
||||||
|
auto def = r->GetType<RecordType>()->FieldDefault($2);
|
||||||
|
if ( def )
|
||||||
|
v = ZVal(def, Z_TYPE);
|
||||||
|
else
|
||||||
|
ERROR(util::fmt("field value missing: $%s", r->GetType()->AsRecordType()->FieldName($2)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
v = *rv;
|
||||||
|
|
||||||
|
expr-op Has-Field
|
||||||
|
class VRi
|
||||||
|
includes-field-op
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
internal-op Has-Field
|
||||||
|
class VRi
|
||||||
|
op-types I R I
|
||||||
|
eval $$ = $1->HasField($2);
|
||||||
|
|
||||||
|
internal-op Has-Field
|
||||||
|
class VRii
|
||||||
|
op-types R R I I
|
||||||
|
eval DirectOptField($$, $2) = ZVal(zeek_int_t($1->HasField($3)));
|
||||||
|
|
||||||
|
# The following generates an assignment version of Has-Field that we
|
||||||
|
# don't use (because we need the one above that uses "includes-field-op")
|
||||||
|
# but lets us compress the two conditionals.
|
||||||
|
predicate-op Has-Field
|
||||||
|
class Vi
|
||||||
|
op-types R I
|
||||||
|
eval $1->HasField($2)
|
||||||
|
|
||||||
|
predicate-op Table-Has-Elements
|
||||||
|
class V
|
||||||
|
op-types T
|
||||||
|
eval $1->Size() > 0
|
||||||
|
|
||||||
|
predicate-op Vector-Has-Elements
|
||||||
|
class V
|
||||||
|
op-types V
|
||||||
|
eval $1->Size() > 0
|
||||||
|
|
||||||
|
expr-op In
|
||||||
|
class VVV
|
||||||
|
custom-method return CompileInExpr(n1, n2, n3);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
expr-op In
|
||||||
|
class VCV
|
||||||
|
custom-method return CompileInExpr(n1, c, n2);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
expr-op In
|
||||||
|
class VVC
|
||||||
|
custom-method return CompileInExpr(n1, n2, c);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
internal-op P-In-S
|
||||||
|
classes VVV VCV VVC
|
||||||
|
op-types I P S
|
||||||
|
eval $$ = $1->MatchAnywhere($2->AsString()) != 0;
|
||||||
|
|
||||||
|
internal-op Str-In-Pat-Tbl
|
||||||
|
classes VVV VCV
|
||||||
|
op-types I S T
|
||||||
|
eval $$ = $2->MatchPattern({NewRef{}, $1});
|
||||||
|
|
||||||
|
internal-op S-In-S
|
||||||
|
classes VVV VCV VVC
|
||||||
|
op-types I S S
|
||||||
|
eval auto sc = reinterpret_cast<const unsigned char*>($1->CheckString());
|
||||||
|
auto cmp = util::strstr_n($2->Len(), $2->Bytes(), $1->Len(), sc);
|
||||||
|
$$ = cmp != -1;
|
||||||
|
|
||||||
|
internal-op A-In-S
|
||||||
|
classes VVV VCV VVC
|
||||||
|
op-types I A N
|
||||||
|
eval $$ = $2->Contains($1->AsAddr());
|
||||||
|
|
||||||
|
|
||||||
|
# Handled differently because of the unusual middle argument.
|
||||||
|
op L-In-T
|
||||||
|
class VLV
|
||||||
|
custom-method return CompileInExpr(n1, l, n2);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
op L-In-T
|
||||||
|
class VLC
|
||||||
|
custom-method return CompileInExpr(n, l, c);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
op L-In-Vec
|
||||||
|
class VLV
|
||||||
|
custom-method return CompileInExpr(n1, l, n2);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
op L-In-Vec
|
||||||
|
class VLC
|
||||||
|
custom-method return CompileInExpr(n, l, c);
|
||||||
|
no-eval
|
||||||
|
|
||||||
|
|
||||||
|
predicate-op Val-Is-In-Table
|
||||||
|
class VV
|
||||||
|
op-types X T
|
||||||
|
eval $2->Find($1.ToVal(Z_TYPE)) != nullptr
|
||||||
|
|
||||||
|
# Variants for indexing two values, one of which might be a constant.
|
||||||
|
# We set the instructions's *second* type to be that of the first variable
|
||||||
|
# index. We get the type of the second variable (if any) by digging it
|
||||||
|
# out of the table's type. For a constant in either position, we use
|
||||||
|
# the main instruction type, as always.
|
||||||
|
|
||||||
|
macro EvalVal2InTableCore(op1, op2)
|
||||||
|
INDEX_LIST->Clear();
|
||||||
|
INDEX_LIST->Append(op1);
|
||||||
|
INDEX_LIST->Append(op2);
|
||||||
|
|
||||||
|
macro EvalVal2InTableAssignCore(lhs, tbl)
|
||||||
|
lhs.AsIntRef() = tbl.AsTable()->Find(INDEX_LIST) != nullptr;
|
||||||
|
|
||||||
|
macro EvalVal2InTablePre(op1, op2, tbl)
|
||||||
|
auto& tt_ind = tbl.AsTable()->GetType()->AsTableType()->GetIndexTypes();
|
||||||
|
EvalVal2InTableCore(op1.ToVal(Z_TYPE2), op2.ToVal(tt_ind[1]))
|
||||||
|
|
||||||
|
internal-op Val2-Is-In-Table
|
||||||
|
class VVVV
|
||||||
|
eval EvalVal2InTablePre($1,$2,$3)
|
||||||
|
EvalVal2InTableAssignCore($$, $3)
|
||||||
|
|
||||||
|
internal-op Val2-Is-In-Table-Cond
|
||||||
|
op1-read
|
||||||
|
class VVVb
|
||||||
|
eval EvalVal2InTablePre($1,$2,$3)
|
||||||
|
EvalVal2InTableCond($3, INDEX_LIST, $4, !)
|
||||||
|
|
||||||
|
macro EvalVal2InTableCond(tbl, op, BRANCH, negate)
|
||||||
|
if ( negate tbl.AsTable()->Find(op) )
|
||||||
|
BRANCH
|
||||||
|
|
||||||
|
internal-op Val2-Is-Not-In-Table-Cond
|
||||||
|
op1-read
|
||||||
|
class VVVb
|
||||||
|
eval EvalVal2InTablePre($1,$2,$3)
|
||||||
|
EvalVal2InTableCond($3, INDEX_LIST, $4,)
|
||||||
|
|
||||||
|
internal-op Val2-Is-In-Table
|
||||||
|
class VVVC
|
||||||
|
eval EvalVal2InTableCore($1.ToVal(Z_TYPE2), $3.ToVal(Z_TYPE))
|
||||||
|
EvalVal2InTableAssignCore($$, $2)
|
||||||
|
|
||||||
|
internal-op Val2-Is-In-Table
|
||||||
|
class VVCV
|
||||||
|
eval EvalVal2InTableCore($2.ToVal(Z_TYPE), $1.ToVal(Z_TYPE2))
|
||||||
|
EvalVal2InTableAssignCore($$, $3)
|
||||||
|
|
||||||
|
internal-op Val2-Is-In-Table-Cond
|
||||||
|
op1-read
|
||||||
|
class VVbC
|
||||||
|
eval EvalVal2InTableCore($1.ToVal(Z_TYPE2), $4.ToVal(Z_TYPE))
|
||||||
|
EvalVal2InTableCond($2, INDEX_LIST, $3, !)
|
||||||
|
|
||||||
|
internal-op Val2-Is-In-Table-Cond
|
||||||
|
op1-read
|
||||||
|
class VVCb
|
||||||
|
eval EvalVal2InTableCore($3.ToVal(Z_TYPE), $1.ToVal(Z_TYPE2))
|
||||||
|
EvalVal2InTableCond($2, INDEX_LIST, $4, !)
|
||||||
|
|
||||||
|
internal-op Val2-Is-Not-In-Table-Cond
|
||||||
|
op1-read
|
||||||
|
class VVbC
|
||||||
|
eval EvalVal2InTableCore($1.ToVal(Z_TYPE2), $4.ToVal(Z_TYPE))
|
||||||
|
EvalVal2InTableCond($2, INDEX_LIST, $3, )
|
||||||
|
|
||||||
|
internal-op Val2-Is-Not-In-Table-Cond
|
||||||
|
op1-read
|
||||||
|
class VVCb
|
||||||
|
eval EvalVal2InTableCore($3.ToVal(Z_TYPE), $1.ToVal(Z_TYPE2))
|
||||||
|
EvalVal2InTableCond($2, INDEX_LIST, $4, )
|
||||||
|
|
||||||
|
|
||||||
|
predicate-op Const-Is-In-Table
|
||||||
|
class VC
|
||||||
|
op-types T X
|
||||||
|
eval $1->Find($2.ToVal(Z_TYPE)) != nullptr
|
||||||
|
|
||||||
|
internal-op List-Is-In-Table
|
||||||
|
classes VV VC
|
||||||
|
op-types I T
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
$$ = $1->Find(std::move(indices)) != nullptr;
|
||||||
|
|
||||||
|
internal-op Val-Is-In-Vector
|
||||||
|
class VVV
|
||||||
|
op-types I I V
|
||||||
|
eval auto vec = $2;
|
||||||
|
auto ind = $1;
|
||||||
|
$$ = vec->Has(ind);
|
||||||
|
|
||||||
|
internal-op Const-Is-In-Vector
|
||||||
|
class VCV
|
||||||
|
op-types I I V
|
||||||
|
eval auto vec = $2;
|
||||||
|
auto ind = $1;
|
||||||
|
$$ = vec->Has(ind);
|
||||||
|
|
||||||
|
expr-op Cond
|
||||||
|
class VVVV
|
||||||
|
op-types X I X X
|
||||||
|
set-type $2
|
||||||
|
eval AssignTarget($$, $1 ? CopyVal($2) : CopyVal($3))
|
||||||
|
|
||||||
|
expr-op Cond
|
||||||
|
class VVVC
|
||||||
|
op-types X I X X
|
||||||
|
set-type $2
|
||||||
|
eval AssignTarget($$, $1 ? CopyVal($2) : CopyVal($3))
|
||||||
|
|
||||||
|
expr-op Cond
|
||||||
|
class VVCV
|
||||||
|
op-types X I X X
|
||||||
|
set-type $2
|
||||||
|
eval AssignTarget($$, $1 ? CopyVal($2) : CopyVal($3))
|
||||||
|
|
||||||
|
op Bool-Vec-Cond
|
||||||
|
class VVVV
|
||||||
|
op-types V V V V
|
||||||
|
set-type $2
|
||||||
|
eval auto& vsel = $1->RawVec();
|
||||||
|
auto& v1 = $2->RawVec();
|
||||||
|
auto& v2 = $3->RawVec();
|
||||||
|
auto n = v1.size();
|
||||||
|
auto res = new vector<std::optional<ZVal>>(n);
|
||||||
|
for ( auto i = 0U; i < n; ++i )
|
||||||
|
if ( vsel[i] )
|
||||||
|
(*res)[i] = vsel[i]->AsInt() ? v1[i] : v2[i];
|
||||||
|
auto& full_res = $$;
|
||||||
|
Unref(full_res);
|
||||||
|
full_res = new VectorVal(cast_intrusive<VectorType>(Z_TYPE), res);
|
||||||
|
|
||||||
|
# Our instruction format doesn't accommodate two constants, so for
|
||||||
|
# the singular case of a V ? C1 : C2 conditional, we split it into
|
||||||
|
# two operations, V ? C1 and !V ? C2.
|
||||||
|
op CondC1
|
||||||
|
class VVC
|
||||||
|
op-types X I X
|
||||||
|
set-type $$
|
||||||
|
eval if ( $1 )
|
||||||
|
AssignTarget($$, CopyVal($2))
|
||||||
|
|
||||||
|
op CondC2
|
||||||
|
class VVC
|
||||||
|
op-types X I X
|
||||||
|
set-type $$
|
||||||
|
eval if ( ! $1 )
|
||||||
|
AssignTarget($$, CopyVal($2))
|
55
src/script_opt/ZAM/OPs/rel-exprs.op
Normal file
55
src/script_opt/ZAM/OPs/rel-exprs.op
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# Operations corresponding to relational expressions.
|
||||||
|
|
||||||
|
rel-expr-op LT
|
||||||
|
op-type I U D S T A
|
||||||
|
vector
|
||||||
|
eval $1 < $2
|
||||||
|
eval-type S Bstr_cmp($1->AsString(), $2->AsString()) < 0
|
||||||
|
eval-type T $1->IsSubsetOf(*$2) && $1->Size() < $2->Size()
|
||||||
|
eval-type A $1->AsAddr() < $2->AsAddr()
|
||||||
|
|
||||||
|
rel-expr-op LE
|
||||||
|
op-type I U D S T A
|
||||||
|
vector
|
||||||
|
eval $1 <= $2
|
||||||
|
eval-type S Bstr_cmp($1->AsString(), $2->AsString()) <= 0
|
||||||
|
eval-type T $1->IsSubsetOf(*$2)
|
||||||
|
eval-type A $1->AsAddr() < $2->AsAddr() || $1->AsAddr() == $2->AsAddr()
|
||||||
|
|
||||||
|
rel-expr-op EQ
|
||||||
|
op-type I U D S T A N F
|
||||||
|
vector
|
||||||
|
eval $1 == $2
|
||||||
|
eval-type S Bstr_cmp($1->AsString(), $2->AsString()) == 0
|
||||||
|
eval-type T $1->EqualTo(*$2)
|
||||||
|
eval-type A $1->AsAddr() == $2->AsAddr()
|
||||||
|
eval-type N $1->AsSubNet() == $2->AsSubNet()
|
||||||
|
eval-type F util::streq($1->Name(), $2->Name())
|
||||||
|
eval-mixed P S $1->MatchExactly($2->AsString())
|
||||||
|
|
||||||
|
rel-expr-op NE
|
||||||
|
op-type I U D S T A N F
|
||||||
|
vector
|
||||||
|
eval $1 != $2
|
||||||
|
eval-type S Bstr_cmp($1->AsString(), $2->AsString()) != 0
|
||||||
|
eval-type T ! $1->EqualTo(*$2)
|
||||||
|
eval-type A $1->AsAddr() != $2->AsAddr()
|
||||||
|
eval-type N $1->AsSubNet() != $2->AsSubNet()
|
||||||
|
eval-type F ! util::streq($1->Name(), $2->Name())
|
||||||
|
eval-mixed P S ! $1->MatchExactly($2->AsString())
|
||||||
|
|
||||||
|
# Note, canonicalization means that GE and GT shouldn't occur
|
||||||
|
# for Sets (type T).
|
||||||
|
rel-expr-op GE
|
||||||
|
op-type I U D S A
|
||||||
|
vector
|
||||||
|
eval $1 >= $2
|
||||||
|
eval-type S Bstr_cmp($1->AsString(), $2->AsString()) >= 0
|
||||||
|
eval-type A ! ($1->AsAddr() < $2->AsAddr())
|
||||||
|
|
||||||
|
rel-expr-op GT
|
||||||
|
op-type I U D S A
|
||||||
|
vector
|
||||||
|
eval $1 > $2
|
||||||
|
eval-type S Bstr_cmp($1->AsString(), $2->AsString()) > 0
|
||||||
|
eval-type A ! ($1->AsAddr() < $2->AsAddr()) && $1->AsAddr() != $2->AsAddr()
|
57
src/script_opt/ZAM/OPs/script-idioms.op
Normal file
57
src/script_opt/ZAM/OPs/script-idioms.op
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# Operations corresponding to scripting idioms / known script functions.
|
||||||
|
|
||||||
|
internal-op MinU
|
||||||
|
classes VVV VVC
|
||||||
|
op-types U U U
|
||||||
|
eval $$ = std::min($1, $2);
|
||||||
|
|
||||||
|
internal-op MinI
|
||||||
|
classes VVV VVC
|
||||||
|
op-types I I I
|
||||||
|
eval $$ = std::min($1, $2);
|
||||||
|
|
||||||
|
internal-op MinD
|
||||||
|
classes VVV VVC
|
||||||
|
op-types D D D
|
||||||
|
eval $$ = std::min($1, $2);
|
||||||
|
|
||||||
|
internal-op MaxU
|
||||||
|
classes VVV VVC
|
||||||
|
op-types U U U
|
||||||
|
eval $$ = std::max($1, $2);
|
||||||
|
|
||||||
|
internal-op MaxI
|
||||||
|
classes VVV VVC
|
||||||
|
op-types I I I
|
||||||
|
eval $$ = std::max($1, $2);
|
||||||
|
|
||||||
|
internal-op MaxD
|
||||||
|
classes VVV VVC
|
||||||
|
op-types D D D
|
||||||
|
eval $$ = std::max($1, $2);
|
||||||
|
|
||||||
|
internal-op Func-Id-String
|
||||||
|
class VV
|
||||||
|
op-types S R
|
||||||
|
eval auto id_rec = $1;
|
||||||
|
auto orig_h = DirectField(id_rec, 0).AsAddr()->AsAddr().AsString();
|
||||||
|
auto resp_h = DirectField(id_rec, 2).AsAddr()->AsAddr().AsString();
|
||||||
|
auto orig_p = static_cast<uint32_t>(DirectField(id_rec, 1).AsCount()) & ~PORT_SPACE_MASK;
|
||||||
|
auto resp_p = static_cast<uint32_t>(DirectField(id_rec, 3).AsCount()) & ~PORT_SPACE_MASK;
|
||||||
|
/* Maximum address size is for IPv6 with no compression. Each
|
||||||
|
* 8 16-bit hex elements plus 7 colons between them plus the two []'s
|
||||||
|
* = 8*4 + 7 + 2 = 41 characters.
|
||||||
|
*
|
||||||
|
* Maximum port size is 5.
|
||||||
|
*
|
||||||
|
* Two of these = 2*41 + 2*5 = 92.
|
||||||
|
* Other delimiters: two ':', one ' < ' for 5 more.
|
||||||
|
*
|
||||||
|
* TOTAL: 97 characters.
|
||||||
|
*
|
||||||
|
* We use considerably more for safety.
|
||||||
|
*/
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof buf, "%s:%u > %s:%u", orig_h.c_str(), orig_p, resp_h.c_str(), resp_p);
|
||||||
|
Unref($$);
|
||||||
|
$$ = new StringVal(buf);
|
339
src/script_opt/ZAM/OPs/stmts.op
Normal file
339
src/script_opt/ZAM/OPs/stmts.op
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
# Operations corresponding to statements, other than iterations.
|
||||||
|
|
||||||
|
macro EvalScheduleArgs(time, is_delta, build_args)
|
||||||
|
if ( ! run_state::terminating )
|
||||||
|
{
|
||||||
|
double dt = time;
|
||||||
|
if ( is_delta )
|
||||||
|
dt += run_state::network_time;
|
||||||
|
auto handler = EventHandlerPtr(Z_AUX_EVENT_HANDLER);
|
||||||
|
ValVec args;
|
||||||
|
build_args
|
||||||
|
auto timer = new ScheduleTimer(handler, std::move(args), dt);
|
||||||
|
timer_mgr->Add(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro EvalSchedule(time, is_delta)
|
||||||
|
EvalScheduleArgs(time, is_delta, Z_AUX->FillValVec(args, frame);)
|
||||||
|
|
||||||
|
op Schedule
|
||||||
|
class ViHL
|
||||||
|
op-types D I X X
|
||||||
|
op1-read
|
||||||
|
custom-method return CompileSchedule(n, nullptr, i, h, l);
|
||||||
|
eval EvalSchedule($1, $2)
|
||||||
|
|
||||||
|
op Schedule
|
||||||
|
class CiHL
|
||||||
|
op-types D I X X
|
||||||
|
op1-read
|
||||||
|
custom-method return CompileSchedule(nullptr, c, i, h, l);
|
||||||
|
eval EvalSchedule($1, $2)
|
||||||
|
|
||||||
|
internal-op Schedule0
|
||||||
|
classes ViH CiH
|
||||||
|
op-types D I X
|
||||||
|
op1-read
|
||||||
|
eval EvalScheduleArgs($1, $2,)
|
||||||
|
|
||||||
|
macro QueueEvent(eh, args)
|
||||||
|
if ( *eh )
|
||||||
|
event_mgr.Enqueue(eh, std::move(args));
|
||||||
|
|
||||||
|
op Event
|
||||||
|
class HL
|
||||||
|
op1-read
|
||||||
|
custom-method return CompileEvent(h, l);
|
||||||
|
eval ValVec args;
|
||||||
|
Z_AUX->FillValVec(args, frame);
|
||||||
|
QueueEvent(Z_AUX_EVENT_HANDLER, args);
|
||||||
|
|
||||||
|
internal-op Event0
|
||||||
|
class X
|
||||||
|
eval ValVec args(0);
|
||||||
|
QueueEvent(Z_AUX_EVENT_HANDLER, args);
|
||||||
|
|
||||||
|
internal-op Event1
|
||||||
|
class V
|
||||||
|
op1-read
|
||||||
|
eval ValVec args(1);
|
||||||
|
args[0] = $1.ToVal(Z_TYPE);
|
||||||
|
QueueEvent(Z_AUX_EVENT_HANDLER, args);
|
||||||
|
|
||||||
|
internal-op Event2
|
||||||
|
class VV
|
||||||
|
op1-read
|
||||||
|
eval ValVec args(2);
|
||||||
|
args[0] = $1.ToVal(Z_TYPE);
|
||||||
|
args[1] = $2.ToVal(Z_TYPE2);
|
||||||
|
QueueEvent(Z_AUX_EVENT_HANDLER, args);
|
||||||
|
|
||||||
|
internal-op Event3
|
||||||
|
class VVV
|
||||||
|
op1-read
|
||||||
|
eval ValVec args(3);
|
||||||
|
auto& aux = Z_AUX;
|
||||||
|
args[0] = $1.ToVal(Z_TYPE);
|
||||||
|
args[1] = $2.ToVal(Z_TYPE2);
|
||||||
|
args[2] = $3.ToVal(aux->elems[2].GetType());
|
||||||
|
QueueEvent(Z_AUX_EVENT_HANDLER, args);
|
||||||
|
|
||||||
|
internal-op Event4
|
||||||
|
class VVVV
|
||||||
|
op1-read
|
||||||
|
eval ValVec args(4);
|
||||||
|
auto& aux = Z_AUX;
|
||||||
|
args[0] = $1.ToVal(Z_TYPE);
|
||||||
|
args[1] = $2.ToVal(Z_TYPE2);
|
||||||
|
args[2] = $3.ToVal(aux->elems[2].GetType());
|
||||||
|
args[3] = $4.ToVal(aux->elems[3].GetType());
|
||||||
|
QueueEvent(Z_AUX_EVENT_HANDLER, args);
|
||||||
|
|
||||||
|
|
||||||
|
op Return
|
||||||
|
class X
|
||||||
|
eval EvalReturn(nullptr,)
|
||||||
|
|
||||||
|
macro EvalReturn(val, type)
|
||||||
|
ret_u = val;
|
||||||
|
type
|
||||||
|
DO_ZAM_PROFILE
|
||||||
|
pc = end_pc;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
op Return
|
||||||
|
op1-read
|
||||||
|
classes V C
|
||||||
|
set-type $$
|
||||||
|
eval EvalReturn(&$$, SET_RET_TYPE(Z_TYPE))
|
||||||
|
|
||||||
|
op When-Return
|
||||||
|
class X
|
||||||
|
eval static auto any_val = ZVal();
|
||||||
|
EvalReturn(&any_val,);
|
||||||
|
|
||||||
|
|
||||||
|
# Branch on the value of v1 using switch table v2, with default branch to v3
|
||||||
|
|
||||||
|
macro EvalSwitchBody(index, branch, cases, postscript)
|
||||||
|
{
|
||||||
|
auto t = cases[index];
|
||||||
|
if ( t.find(v) == t.end() )
|
||||||
|
pc = branch;
|
||||||
|
else
|
||||||
|
pc = t[v];
|
||||||
|
postscript
|
||||||
|
DO_ZAM_PROFILE
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op SwitchI
|
||||||
|
op1-read
|
||||||
|
class Vii
|
||||||
|
op-types I I I
|
||||||
|
eval auto v = $1;
|
||||||
|
EvalSwitchBody($2, $3, int_cases,)
|
||||||
|
|
||||||
|
internal-op SwitchU
|
||||||
|
op1-read
|
||||||
|
class Vii
|
||||||
|
op-types U I I
|
||||||
|
eval auto v = $1;
|
||||||
|
EvalSwitchBody($2, $3, uint_cases,)
|
||||||
|
|
||||||
|
internal-op SwitchD
|
||||||
|
op1-read
|
||||||
|
class Vii
|
||||||
|
op-types D I I
|
||||||
|
eval auto v = $1;
|
||||||
|
EvalSwitchBody($2, $3, double_cases,)
|
||||||
|
|
||||||
|
internal-op SwitchS
|
||||||
|
op1-read
|
||||||
|
class Vii
|
||||||
|
op-types S I I
|
||||||
|
eval auto vs = $1->AsString()->Render();
|
||||||
|
std::string v(vs);
|
||||||
|
EvalSwitchBody($2, $3, str_cases,delete[] vs;)
|
||||||
|
|
||||||
|
internal-op SwitchA
|
||||||
|
op1-read
|
||||||
|
class Vii
|
||||||
|
op-types A I I
|
||||||
|
eval auto v = $1->AsAddr().AsString();
|
||||||
|
EvalSwitchBody($2, $3, str_cases,)
|
||||||
|
|
||||||
|
internal-op SwitchN
|
||||||
|
op1-read
|
||||||
|
class Vii
|
||||||
|
op-types N I I
|
||||||
|
eval auto v = $1->AsSubNet().AsString();
|
||||||
|
EvalSwitchBody($2, $3, str_cases,)
|
||||||
|
|
||||||
|
|
||||||
|
internal-op Determine-Type-Match
|
||||||
|
class VV
|
||||||
|
op-types I a
|
||||||
|
eval auto& aux = Z_AUX;
|
||||||
|
int match = -1;
|
||||||
|
for ( int i = 0; i < aux->n; ++i )
|
||||||
|
{
|
||||||
|
auto& el = aux->elems[i];
|
||||||
|
auto& et = el.GetType();
|
||||||
|
if ( can_cast_value_to_type($1, et.get()) )
|
||||||
|
{
|
||||||
|
match = i;
|
||||||
|
if ( el.Slot() >= 0 )
|
||||||
|
{
|
||||||
|
auto& tv = frame[el.Slot()];
|
||||||
|
if ( el.IsManaged() )
|
||||||
|
Unref(tv.ManagedVal());
|
||||||
|
tv = ZVal(cast_value_to_type($1, et.get()), et);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$$ = match;
|
||||||
|
|
||||||
|
op CheckAnyLen
|
||||||
|
op1-read
|
||||||
|
class Vi
|
||||||
|
op-types L U
|
||||||
|
eval auto v = $1;
|
||||||
|
if ( v->Vals().size() != $2 )
|
||||||
|
ERROR("mismatch in list lengths");
|
||||||
|
|
||||||
|
op Print
|
||||||
|
class O
|
||||||
|
eval do_print_stmt(Z_AUX->ToValVec(frame));
|
||||||
|
method-post z.aux = v->aux;
|
||||||
|
|
||||||
|
op Print1
|
||||||
|
op1-read
|
||||||
|
classes V C
|
||||||
|
set-type $$
|
||||||
|
eval std::vector<ValPtr> vals;
|
||||||
|
vals.push_back($$.ToVal(Z_TYPE));
|
||||||
|
do_print_stmt(vals);
|
||||||
|
|
||||||
|
|
||||||
|
internal-op If-Else
|
||||||
|
op1-read
|
||||||
|
class Vb
|
||||||
|
op-types I I
|
||||||
|
eval if ( ! $1 ) $2
|
||||||
|
|
||||||
|
internal-op If
|
||||||
|
op1-read
|
||||||
|
class Vb
|
||||||
|
op-types I I
|
||||||
|
eval if ( ! $1 ) $2
|
||||||
|
|
||||||
|
internal-op If-Not
|
||||||
|
op1-read
|
||||||
|
class Vb
|
||||||
|
op-types I I
|
||||||
|
eval if ( $1 ) $2
|
||||||
|
|
||||||
|
|
||||||
|
op AddStmt
|
||||||
|
op1-read
|
||||||
|
class VO
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
EvalAddStmt($1, indices)
|
||||||
|
method-post z.aux = v->aux;
|
||||||
|
|
||||||
|
macro EvalAddStmt(lhs, ind)
|
||||||
|
auto index = ind;
|
||||||
|
bool iterators_invalidated = false;
|
||||||
|
lhs.AsTable()->Assign(std::move(index), nullptr, true, &iterators_invalidated);
|
||||||
|
if ( iterators_invalidated )
|
||||||
|
WARN("possible loop/iterator invalidation");
|
||||||
|
|
||||||
|
op AddStmt1
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
classes VV VC
|
||||||
|
eval EvalAddStmt($1, $2.ToVal(Z_TYPE))
|
||||||
|
|
||||||
|
|
||||||
|
op ClearTable
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types T
|
||||||
|
eval $1->RemoveAll();
|
||||||
|
|
||||||
|
op ClearVector
|
||||||
|
op1-read
|
||||||
|
class V
|
||||||
|
op-types V
|
||||||
|
eval $1->Resize(0);
|
||||||
|
|
||||||
|
|
||||||
|
op DelTable
|
||||||
|
op1-read
|
||||||
|
class VO
|
||||||
|
op-types T X
|
||||||
|
eval auto indices = Z_AUX->ToListVal(frame);
|
||||||
|
bool iterators_invalidated = false;
|
||||||
|
$1->Remove(*indices, true, &iterators_invalidated);
|
||||||
|
if ( iterators_invalidated )
|
||||||
|
WARN("possible loop/iterator invalidation");
|
||||||
|
method-post z.aux = v->aux;
|
||||||
|
|
||||||
|
op DelField
|
||||||
|
op1-read
|
||||||
|
class Vi
|
||||||
|
op-types R I
|
||||||
|
eval $1->Remove($2);
|
||||||
|
|
||||||
|
|
||||||
|
internal-op Init-Record
|
||||||
|
class V
|
||||||
|
op-types R
|
||||||
|
eval auto r = new RecordVal(cast_intrusive<RecordType>(Z_TYPE));
|
||||||
|
Unref($$);
|
||||||
|
$$ = r;
|
||||||
|
|
||||||
|
internal-op Init-Vector
|
||||||
|
class V
|
||||||
|
op-types V
|
||||||
|
eval auto vt = cast_intrusive<VectorType>(Z_TYPE);
|
||||||
|
auto vec = new VectorVal(std::move(vt));
|
||||||
|
Unref($$);
|
||||||
|
$$ = vec;
|
||||||
|
|
||||||
|
internal-op Init-Table
|
||||||
|
class V
|
||||||
|
op-types T
|
||||||
|
eval auto tt = cast_intrusive<TableType>(Z_TYPE);
|
||||||
|
auto t = new TableVal(tt, Z_AUX_ATTRS);
|
||||||
|
Unref($$);
|
||||||
|
$$ = t;
|
||||||
|
|
||||||
|
op When
|
||||||
|
class V
|
||||||
|
op1-read
|
||||||
|
op-types F
|
||||||
|
eval BuildWhen($1, -1.0)
|
||||||
|
|
||||||
|
op When-Timeout
|
||||||
|
classes VV VC
|
||||||
|
op1-read
|
||||||
|
op-types F D
|
||||||
|
eval BuildWhen($1, $2)
|
||||||
|
|
||||||
|
macro BuildWhen(zf, timeout)
|
||||||
|
auto& aux = Z_AUX;
|
||||||
|
auto wi = Z_AUX_WHEN_INFO;
|
||||||
|
FuncPtr func{NewRef{}, zf};
|
||||||
|
auto lambda = make_intrusive<FuncVal>(func);
|
||||||
|
wi->Instantiate(std::move(lambda));
|
||||||
|
std::vector<ValPtr> local_aggrs;
|
||||||
|
for ( int i = 0; i < aux->n; ++i )
|
||||||
|
{
|
||||||
|
auto v = aux->ToVal(frame, i);
|
||||||
|
if ( v )
|
||||||
|
local_aggrs.push_back(v);
|
||||||
|
}
|
||||||
|
(void)make_intrusive<trigger::Trigger>(wi, wi->WhenExprGlobals(), local_aggrs, timeout, Z_FRAME, Z_LOC->Loc());
|
181
src/script_opt/ZAM/OPs/unary-exprs.op
Normal file
181
src/script_opt/ZAM/OPs/unary-exprs.op
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
# Operations corresponding to unary expressions.
|
||||||
|
|
||||||
|
# Direct assignment of an existing value.
|
||||||
|
assign-op Assign
|
||||||
|
class V
|
||||||
|
|
||||||
|
# The same, but where the assignment target (LHS) is a record field.
|
||||||
|
assign-op Field-LHS-Assign
|
||||||
|
op1-read
|
||||||
|
class F
|
||||||
|
|
||||||
|
unary-expr-op Clone
|
||||||
|
no-const
|
||||||
|
op-type X
|
||||||
|
set-type $$
|
||||||
|
set-type2 $1
|
||||||
|
eval auto v = $1.ToVal(Z_TYPE2)->Clone();
|
||||||
|
AssignTarget($$, BuildVal(v, Z_TYPE))
|
||||||
|
|
||||||
|
unary-expr-op Size
|
||||||
|
no-const
|
||||||
|
op-type I U D A N S T V *
|
||||||
|
explicit-result-type
|
||||||
|
set-type $$
|
||||||
|
set-type2 $1
|
||||||
|
eval-type I $$ = ZVal(zeek_int_t($1 < 0 ? -$1 : $1));
|
||||||
|
eval-type U $$ = ZVal($1);
|
||||||
|
eval-type D $$ = ZVal($1 < 0 ? -$1 : $1);
|
||||||
|
eval-type A $$ = ZVal(zeek_uint_t($1->AsAddr().GetFamily() == IPv4 ? 32 : 128));
|
||||||
|
eval-type N $$ = ZVal(pow(2.0, double(128 - $1->AsSubNet().LengthIPv6())));
|
||||||
|
eval-type S $$ = ZVal(zeek_uint_t($1->Len()));
|
||||||
|
eval-type T $$ = ZVal(zeek_uint_t($1->Size()));
|
||||||
|
eval-type V $$ = ZVal(zeek_uint_t($1->Size()));
|
||||||
|
eval auto v = $1.ToVal(Z_TYPE2)->SizeVal();
|
||||||
|
$$ = BuildVal(v, Z_TYPE);
|
||||||
|
|
||||||
|
unary-expr-op Not
|
||||||
|
op-type I
|
||||||
|
eval ! $1
|
||||||
|
|
||||||
|
unary-expr-op Complement
|
||||||
|
op-type U
|
||||||
|
eval ~ $1
|
||||||
|
|
||||||
|
unary-expr-op Positive
|
||||||
|
op-type I U D
|
||||||
|
vector
|
||||||
|
eval $1
|
||||||
|
|
||||||
|
unary-expr-op Negate
|
||||||
|
op-type I U D
|
||||||
|
vector
|
||||||
|
eval -$1
|
||||||
|
|
||||||
|
op IncrI
|
||||||
|
op1-read-write
|
||||||
|
class V
|
||||||
|
op-types I
|
||||||
|
eval ++$$;
|
||||||
|
|
||||||
|
op IncrU
|
||||||
|
op1-read-write
|
||||||
|
class V
|
||||||
|
op-types U
|
||||||
|
eval ++$$;
|
||||||
|
|
||||||
|
op DecrI
|
||||||
|
op1-read-write
|
||||||
|
class V
|
||||||
|
op-types I
|
||||||
|
eval --$$;
|
||||||
|
|
||||||
|
op DecrU
|
||||||
|
op1-read-write
|
||||||
|
class V
|
||||||
|
op-types U
|
||||||
|
eval auto& u = $$;
|
||||||
|
if ( u == 0 )
|
||||||
|
WARN("count underflow");
|
||||||
|
--u;
|
||||||
|
|
||||||
|
unary-op AppendTo
|
||||||
|
# Note, even though it feels like appending both reads and modifies
|
||||||
|
# its first operand, for our purposes it just reads it (to get the
|
||||||
|
# aggregate), and then modifies its *content* but not the operand's
|
||||||
|
# value itself.
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
eval auto vv = $1.AsVector();
|
||||||
|
if ( vv->Size() == 0 )
|
||||||
|
/* Use the slightly more expensive Assign(), since it
|
||||||
|
* knows how to deal with empty vectors that do not yet
|
||||||
|
* have concrete types.
|
||||||
|
*/
|
||||||
|
vv->Assign(0, $2.ToVal(Z_TYPE));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vv->RawVec().push_back(CopyVal($2));
|
||||||
|
vv->Modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
# For vectors-of-any, we always go through the Assign() interface because
|
||||||
|
# it's needed for tracking the potentially differing types.
|
||||||
|
unary-op AppendToAnyVec
|
||||||
|
op1-read
|
||||||
|
set-type $1
|
||||||
|
eval auto vv = $1.AsVector();
|
||||||
|
vv->Assign(vv->Size(), $2.ToVal(Z_TYPE));
|
||||||
|
|
||||||
|
internal-op AddPatternToField
|
||||||
|
classes VVi VCi
|
||||||
|
op1-read
|
||||||
|
op-types R P I
|
||||||
|
eval auto r = $$;
|
||||||
|
auto fpat = r->GetField($2)->AsPatternVal();
|
||||||
|
if ( fpat )
|
||||||
|
{
|
||||||
|
$1->AddTo(fpat, false);
|
||||||
|
r->Modified();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ERROR(util::fmt("field value missing: $%s", r->GetType()->AsRecordType()->FieldName($2)));
|
||||||
|
|
||||||
|
unary-op ExtendPattern
|
||||||
|
op1-read
|
||||||
|
eval $1.AsPattern()->AddTo($$.AsPattern(), false);
|
||||||
|
|
||||||
|
unary-op AddVecToVec
|
||||||
|
op1-read
|
||||||
|
eval if ( ! $1.AsVector()->AddTo($$.AsVector(), false) )
|
||||||
|
ERROR("incompatible vector element assignment");
|
||||||
|
|
||||||
|
unary-op AddTableToTable
|
||||||
|
op1-read
|
||||||
|
eval auto t = $$.AsTable();
|
||||||
|
auto v = $1.AsTable();
|
||||||
|
if ( v->Size() > 0 )
|
||||||
|
{
|
||||||
|
v->AddTo(t, false);
|
||||||
|
t->Modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
unary-op RemoveTableFromTable
|
||||||
|
op1-read
|
||||||
|
eval auto t = $$.AsTable();
|
||||||
|
auto v = $1.AsTable();
|
||||||
|
if ( v->Size() > 0 )
|
||||||
|
{
|
||||||
|
v->RemoveFrom(t);
|
||||||
|
t->Modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
unary-expr-op Cast
|
||||||
|
op-type X
|
||||||
|
set-type $$
|
||||||
|
set-type2 $1
|
||||||
|
eval EvalCast($$, $1.ToVal(Z_TYPE2))
|
||||||
|
|
||||||
|
macro EvalCast(lhs, rhs)
|
||||||
|
std::string error;
|
||||||
|
auto res = cast_value(rhs, Z_TYPE, error);
|
||||||
|
if ( res )
|
||||||
|
AssignTarget(lhs, BuildVal(res, Z_TYPE))
|
||||||
|
else
|
||||||
|
ERROR(error.c_str());
|
||||||
|
|
||||||
|
# Cast an "any" type to the given type. Only needed for type-based switch
|
||||||
|
# statements.
|
||||||
|
internal-op Cast-Any
|
||||||
|
class VV
|
||||||
|
op-types X a
|
||||||
|
eval ValPtr rhs = {NewRef{}, $1};
|
||||||
|
EvalCast($$, rhs)
|
||||||
|
|
||||||
|
direct-unary-op Is Is
|
||||||
|
|
||||||
|
internal-op Is
|
||||||
|
class VV
|
||||||
|
op-types I X
|
||||||
|
eval auto rhs = $1.ToVal(Z_TYPE2).get();
|
||||||
|
$$ = can_cast_value_to_type(rhs, Z_TYPE.get());
|
Loading…
Add table
Add a link
Reference in a new issue